@@ -1682,39 +1682,65 @@ PhaseStatus Compiler::optOptimizeBools()
16821682//
16831683bool Compiler::fgFoldCondToReturnBlock (BasicBlock* block)
16841684{
1685+ bool modified = false ;
1686+
16851687 assert (block->KindIs (BBJ_COND));
16861688
16871689#ifdef JIT32_GCENCODER
16881690 // JIT32_GCENCODER has a hard limit on the number of epilogues.
1689- return false ;
1691+ return changed ;
16901692#endif
16911693
16921694 // Early out if the current method is not returning a boolean.
16931695 if ((info.compRetType != TYP_UBYTE) || (genReturnBB != nullptr ))
16941696 {
1695- return false ;
1697+ return modified ;
16961698 }
16971699
16981700 // Both edges must be BBJ_RETURN
16991701 BasicBlock* retTrueBb = block->GetTrueEdge ()->getDestinationBlock ();
17001702 BasicBlock* retFalseBb = block->GetFalseEdge ()->getDestinationBlock ();
1703+
1704+ // Although, we might want to fold fallthrough BBJ_ALWAYS blocks first
1705+ if (fgCanCompactBlock (retTrueBb))
1706+ {
1707+ fgCompactBlock (retTrueBb);
1708+ modified = true ;
1709+ }
1710+
1711+ if (fgCanCompactBlock (retFalseBb))
1712+ {
1713+ fgCompactBlock (retFalseBb);
1714+ modified = true ;
1715+ }
1716+
1717+ if (!block->KindIs (BBJ_COND))
1718+ {
1719+ // In rare cases fgCompactBlock() might have changed the current block
1720+ return modified;
1721+ }
1722+
1723+ retTrueBb = block->GetTrueEdge ()->getDestinationBlock ();
1724+ retFalseBb = block->GetFalseEdge ()->getDestinationBlock ();
17011725 if (!retTrueBb->KindIs (BBJ_RETURN) || !retFalseBb->KindIs (BBJ_RETURN))
17021726 {
1703- return false ;
1727+ return modified ;
17041728 }
17051729
1730+ // It has to be JTRUE(cond) or JTRUE(comma(cond)), but let's be resilient.
1731+ assert (block->lastStmt () != nullptr );
17061732 GenTree* node = block->lastStmt ()->GetRootNode ();
17071733 GenTree* cond = node->gtGetOp1 ();
17081734 if (!cond->OperIsCompare ())
17091735 {
1710- return false ;
1736+ return modified ;
17111737 }
17121738
17131739 if ((retTrueBb->GetUniquePred (this ) == nullptr ) && (retFalseBb->GetUniquePred (this ) == nullptr ))
17141740 {
17151741 // Both return blocks have multiple predecessors - bail out.
17161742 // We don't want to introduce a new epilogue.
1717- return false ;
1743+ return modified ;
17181744 }
17191745
17201746 // Is block a BBJ_RETURN(1/0) ? (single statement)
@@ -1732,15 +1758,15 @@ bool Compiler::fgFoldCondToReturnBlock(BasicBlock* block)
17321758 bool retFalseTrue = isReturnBool (retTrueBb, false ) && isReturnBool (retFalseBb, true );
17331759 if (!retTrueFalse && !retFalseTrue)
17341760 {
1735- return false ;
1761+ return modified ;
17361762 }
17371763
17381764 // Reverse the condition if we jump to "return false" on true.
17391765 if (retFalseTrue)
17401766 {
17411767 cond->SetOper (GenTree::ReverseRelop (cond->OperGet ()));
17421768 }
1743-
1769+ modified = true ;
17441770 assert (cond->TypeIs (TYP_INT));
17451771 assert (BasicBlock::sameEHRegion (block, retTrueBb));
17461772 assert (BasicBlock::sameEHRegion (block, retFalseBb));
@@ -1753,11 +1779,14 @@ bool Compiler::fgFoldCondToReturnBlock(BasicBlock* block)
17531779 node->ChangeType (TYP_INT);
17541780 cond->gtFlags &= ~GTF_RELOP_JMP_USED;
17551781
1756- // It's difficult to restore the original weight of the block
1782+ // It's difficult to restore the original weight of the block, profile repair will handle it.
17571783 fgPgoConsistent = false ;
17581784 block->bbCodeOffsEnd = max (retTrueBb->bbCodeOffsEnd , retFalseBb->bbCodeOffsEnd );
17591785 gtSetStmtInfo (block->lastStmt ());
17601786 fgSetStmtSeq (block->lastStmt ());
17611787 gtUpdateStmtSideEffects (block->lastStmt ());
1762- return true ;
1788+
1789+ JITDUMP (" fgFoldCondToReturnBlock: folding " FMT_BB " from BBJ_COND into BBJ_RETURN:" , block->bbNum );
1790+ DISPBLOCK (block)
1791+ return modified;
17631792}
0 commit comments