@@ -1123,49 +1123,79 @@ static bool onlyHasTerminatorAndDebugInsts(SILBasicBlock *BB) {
11231123 return true ;
11241124}
11251125
1126- // / \return If this basic blocks has a single br instruction passing all of the
1127- // / arguments in the original order, then returns the destination of that br.
1128- static SILBasicBlock *getTrampolineDest (SILBasicBlock *SBB) {
1126+ namespace {
1127+
1128+ // / Will be valid if the constructor's targetBB has a a single branch and all
1129+ // / its block arguments are only used by that branch.
1130+ struct TrampolineDest {
1131+ SILBasicBlock *destBB = nullptr ;
1132+ // Source block's branch args after bypassing targetBB.
1133+ SmallVector<SILValue, 4 > newSourceBranchArgs;
1134+
1135+ TrampolineDest () {}
1136+ TrampolineDest (SILBasicBlock *sourceBB, SILBasicBlock *targetBB);
1137+ TrampolineDest (const TrampolineDest &) = delete ;
1138+ TrampolineDest &operator =(const TrampolineDest &) = delete ;
1139+ TrampolineDest (TrampolineDest &&) = default ;
1140+ TrampolineDest &operator =(TrampolineDest &&) = default ;
1141+
1142+ bool operator ==(const TrampolineDest &rhs) {
1143+ return destBB == rhs.destBB
1144+ && newSourceBranchArgs == rhs.newSourceBranchArgs ;
1145+ }
1146+ bool operator !=(const TrampolineDest &rhs) {
1147+ return !(*this == rhs);
1148+ }
1149+
1150+ operator bool () const { return destBB != nullptr ; }
1151+ };
1152+
1153+ } // end anonymous namespace
1154+
1155+ TrampolineDest::TrampolineDest (SILBasicBlock *sourceBB,
1156+ SILBasicBlock *targetBB) {
11291157 // Ignore blocks with more than one instruction.
1130- if (!onlyHasTerminatorAndDebugInsts (SBB ))
1131- return nullptr ;
1158+ if (!onlyHasTerminatorAndDebugInsts (targetBB ))
1159+ return ;
11321160
1133- auto *BI = dyn_cast<BranchInst>(SBB ->getTerminator ());
1134- if (!BI )
1135- return nullptr ;
1161+ auto *targetBranch = dyn_cast<BranchInst>(targetBB ->getTerminator ());
1162+ if (!targetBranch )
1163+ return ;
11361164
1137- // Disallow infinite loops through SBB .
1165+ // Disallow infinite loops through targetBB .
11381166 llvm::SmallPtrSet<SILBasicBlock *, 8 > VisitedBBs;
1139- BranchInst *NextBI = BI ;
1167+ BranchInst *nextBI = targetBranch ;
11401168 do {
1141- SILBasicBlock *NextBB = NextBI ->getDestBB ();
1169+ SILBasicBlock *nextBB = nextBI ->getDestBB ();
11421170 // We don't care about infinite loops after SBB.
1143- if (!VisitedBBs.insert (NextBB ).second )
1171+ if (!VisitedBBs.insert (nextBB ).second )
11441172 break ;
11451173 // Only if the infinite loop goes through SBB directly we bail.
1146- if (NextBB == SBB)
1147- return nullptr ;
1148- NextBI = dyn_cast<BranchInst>(NextBB->getTerminator ());
1149- } while (NextBI);
1150-
1151- auto BrArgs = BI->getArgs ();
1152- if (BrArgs.size () != SBB->getNumArguments ())
1153- return nullptr ;
1174+ if (nextBB == targetBB)
1175+ return ;
1176+ nextBI = dyn_cast<BranchInst>(nextBB->getTerminator ());
1177+ } while (nextBI);
11541178
1155- // Check that the arguments are the same and in the right order.
1156- for (int i = 0 , e = SBB->getNumArguments (); i < e; ++i) {
1157- SILArgument *BBArg = SBB->getArgument (i);
1158- if (BrArgs[i] != BBArg)
1159- return nullptr ;
1160-
1161- // The arguments may not be used in another block, because when the
1162- // predecessor of SBB directly jumps to the successor, the SBB block does
1163- // not dominate the other use anymore.
1164- if (!BBArg->hasOneUse ())
1165- return nullptr ;
1179+ // Check that all the target block arguments are only used by the branch.
1180+ for (SILValue blockArg : targetBB->getArguments ()) {
1181+ Operand *operand = blockArg->getSingleUse ();
1182+ if (!operand || operand->getUser () != targetBranch) {
1183+ return ;
1184+ }
11661185 }
1167-
1168- return BI->getDestBB ();
1186+ newSourceBranchArgs.reserve (targetBranch->getArgs ().size ());
1187+ for (SILValue branchArg : targetBranch->getArgs ()) {
1188+ if (branchArg->getParentBlock () == targetBB) {
1189+ auto *phi = dyn_cast<SILPhiArgument>(branchArg);
1190+ if (!phi || !phi->isPhiArgument ()) {
1191+ return ;
1192+ }
1193+ branchArg = phi->getIncomingPhiValue (sourceBB);
1194+ }
1195+ newSourceBranchArgs.push_back (branchArg);
1196+ }
1197+ // Setting destBB constructs a valid TrampolineDest.
1198+ destBB = targetBranch->getDestBB ();
11691199}
11701200
11711201// / \return If this is a basic block without any arguments and it has
@@ -1334,17 +1364,18 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
13341364
13351365 // If the destination block is a simple trampoline (jump to another block)
13361366 // then jump directly.
1337- if (SILBasicBlock *TrampolineDest = getTrampolineDest (DestBB)) {
1338- LLVM_DEBUG (llvm::dbgs () << " jump to trampoline from bb" << BB->getDebugID ()
1339- << " to bb" << TrampolineDest->getDebugID () <<' \n ' );
1340- SILBuilderWithScope (BI).createBranch (BI->getLoc (), TrampolineDest,
1341- BI->getArgs ());
1367+ if (auto trampolineDest = TrampolineDest (BB, DestBB)) {
1368+ LLVM_DEBUG (llvm::dbgs ()
1369+ << " jump to trampoline from bb" << BB->getDebugID () << " to bb"
1370+ << trampolineDest.destBB ->getDebugID () << ' \n ' );
1371+ SILBuilderWithScope (BI).createBranch (BI->getLoc (), trampolineDest.destBB ,
1372+ trampolineDest.newSourceBranchArgs );
13421373 // Eliminating the trampoline can expose opportunities to improve the
13431374 // new block we branch to.
13441375 if (LoopHeaders.count (DestBB))
13451376 LoopHeaders.insert (BB);
13461377
1347- addToWorklist (TrampolineDest );
1378+ addToWorklist (trampolineDest. destBB );
13481379 BI->eraseFromParent ();
13491380 removeIfDead (DestBB);
13501381 addToWorklist (BB);
@@ -1535,14 +1566,17 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
15351566
15361567 // If the destination block is a simple trampoline (jump to another block)
15371568 // then jump directly.
1538- SILBasicBlock *TrueTrampolineDest = getTrampolineDest (TrueSide);
1539- if (TrueTrampolineDest && TrueTrampolineDest != FalseSide) {
1540- LLVM_DEBUG (llvm::dbgs () << " true-trampoline from bb" << ThisBB->getDebugID ()
1541- << " to bb" << TrueTrampolineDest->getDebugID ()
1542- << ' \n ' );
1569+ auto trueTrampolineDest = TrampolineDest (ThisBB, TrueSide);
1570+ if (trueTrampolineDest
1571+ && trueTrampolineDest.destBB ->getSinglePredecessorBlock ()) {
1572+ LLVM_DEBUG (llvm::dbgs ()
1573+ << " true-trampoline from bb" << ThisBB->getDebugID () << " to bb"
1574+ << trueTrampolineDest.destBB ->getDebugID () << ' \n ' );
1575+ SmallVector<SILValue, 4 > falseArgsCopy (FalseArgs.begin (), FalseArgs.end ());
15431576 SILBuilderWithScope (BI).createCondBranch (
1544- BI->getLoc (), BI->getCondition (), TrueTrampolineDest, TrueArgs,
1545- FalseSide, FalseArgs, BI->getTrueBBCount (), BI->getFalseBBCount ());
1577+ BI->getLoc (), BI->getCondition (), trueTrampolineDest.destBB ,
1578+ trueTrampolineDest.newSourceBranchArgs , FalseSide, falseArgsCopy,
1579+ BI->getTrueBBCount (), BI->getFalseBBCount ());
15461580 BI->eraseFromParent ();
15471581
15481582 if (LoopHeaders.count (TrueSide))
@@ -1552,15 +1586,17 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
15521586 return true ;
15531587 }
15541588
1555- SILBasicBlock *FalseTrampolineDest = getTrampolineDest (FalseSide);
1556- if (FalseTrampolineDest && FalseTrampolineDest != TrueSide) {
1557- LLVM_DEBUG (llvm::dbgs () << " false-trampoline from bb"
1558- << ThisBB->getDebugID () << " to bb"
1559- << FalseTrampolineDest->getDebugID () << ' \n ' );
1589+ auto falseTrampolineDest = TrampolineDest (ThisBB, FalseSide);
1590+ if (falseTrampolineDest
1591+ && falseTrampolineDest.destBB ->getSinglePredecessorBlock ()) {
1592+ LLVM_DEBUG (llvm::dbgs ()
1593+ << " false-trampoline from bb" << ThisBB->getDebugID () << " to bb"
1594+ << falseTrampolineDest.destBB ->getDebugID () << ' \n ' );
1595+ SmallVector<SILValue, 4 > trueArgsCopy (TrueArgs.begin (), TrueArgs.end ());
15601596 SILBuilderWithScope (BI).createCondBranch (
1561- BI->getLoc (), BI->getCondition (), TrueSide, TrueArgs ,
1562- FalseTrampolineDest, FalseArgs, BI-> getTrueBBCount () ,
1563- BI->getFalseBBCount ());
1597+ BI->getLoc (), BI->getCondition (), TrueSide, trueArgsCopy ,
1598+ falseTrampolineDest. destBB , falseTrampolineDest. newSourceBranchArgs ,
1599+ BI->getTrueBBCount (), BI-> getFalseBBCount ());
15641600 BI->eraseFromParent ();
15651601 if (LoopHeaders.count (FalseSide))
15661602 LoopHeaders.insert (ThisBB);
@@ -1571,31 +1607,32 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
15711607
15721608 // Simplify cond_br where both sides jump to the same blocks with the same
15731609 // args.
1574- auto condBrToBr = [&](OperandValueArrayRef branchArgs,
1575- SILBasicBlock *newDest) {
1610+ auto condBrToBr = [&](ArrayRef<SILValue> branchArgs, SILBasicBlock *newDest) {
15761611 LLVM_DEBUG (llvm::dbgs ()
15771612 << " replace cond_br with same dests with br: " << *BI);
15781613 SILBuilderWithScope (BI).createBranch (BI->getLoc (), newDest, branchArgs);
15791614 BI->eraseFromParent ();
15801615 addToWorklist (ThisBB);
15811616 ++NumConstantFolded;
15821617 };
1583- if (TrueArgs == FalseArgs) {
1584- if (TrueTrampolineDest) {
1585- if (TrueTrampolineDest == FalseSide
1586- || TrueTrampolineDest == FalseTrampolineDest) {
1587- condBrToBr (TrueArgs, TrueTrampolineDest);
1588- removeIfDead (TrueSide);
1589- removeIfDead (FalseSide);
1590- return true ;
1591- }
1592- } else if (FalseTrampolineDest == TrueSide) {
1593- condBrToBr (TrueArgs, FalseTrampolineDest);
1594- removeIfDead (FalseSide);
1595- return true ;
1596- }
1618+ if (trueTrampolineDest.destBB == FalseSide
1619+ && trueTrampolineDest.newSourceBranchArgs == FalseArgs) {
1620+ condBrToBr (trueTrampolineDest.newSourceBranchArgs , FalseSide);
1621+ removeIfDead (TrueSide);
1622+ return true ;
1623+ }
1624+ if (falseTrampolineDest.destBB == TrueSide) {
1625+ condBrToBr (falseTrampolineDest.newSourceBranchArgs , TrueSide);
1626+ removeIfDead (FalseSide);
1627+ return true ;
1628+ }
1629+ if (trueTrampolineDest && (trueTrampolineDest == falseTrampolineDest)) {
1630+ condBrToBr (trueTrampolineDest.newSourceBranchArgs ,
1631+ trueTrampolineDest.destBB );
1632+ removeIfDead (TrueSide);
1633+ removeIfDead (FalseSide);
1634+ return true ;
15971635 }
1598-
15991636 auto *TrueTrampolineBr = getTrampolineWithoutBBArgsTerminator (TrueSide);
16001637 if (TrueTrampolineBr &&
16011638 !wouldIntroduceCriticalEdge (BI, TrueTrampolineBr->getDestBB ())) {
@@ -2531,32 +2568,31 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
25312568// to trampoline jumps to the same destination block. The successor blocks
25322569// and the destination blocks may have no arguments.
25332570bool SimplifyCFG::simplifyTermWithIdenticalDestBlocks (SILBasicBlock *BB) {
2534- SILBasicBlock * commonDest = nullptr ;
2571+ TrampolineDest commonDest;
25352572 for (auto *SuccBlock : BB->getSuccessorBlocks ()) {
25362573 if (SuccBlock->getNumArguments () != 0 )
25372574 return false ;
2538- SILBasicBlock *DestBlock = getTrampolineDest ( SuccBlock);
2539- if (!DestBlock)
2575+ auto trampolineDest = TrampolineDest (BB, SuccBlock);
2576+ if (!trampolineDest) {
25402577 return false ;
2578+ }
2579+ // The branch must have the same destination and same branch arguments.
25412580 if (!commonDest) {
2542- commonDest = DestBlock ;
2543- } else if (DestBlock != commonDest) {
2581+ commonDest = std::move (trampolineDest) ;
2582+ } else if (trampolineDest != commonDest) {
25442583 return false ;
25452584 }
25462585 }
2547- if (!commonDest)
2586+ if (!commonDest) {
25482587 return false ;
2549-
2550- assert (commonDest->getNumArguments () == 0 &&
2551- " getTrampolineDest should have checked that commonDest has no args" );
2552-
2588+ }
25532589 TermInst *Term = BB->getTerminator ();
25542590 LLVM_DEBUG (llvm::dbgs () << " replace term with identical dests: " << *Term);
2555- SILBuilderWithScope (Term).createBranch (Term->getLoc (), commonDest,
2556- ArrayRef<SILValue>() );
2591+ SILBuilderWithScope (Term).createBranch (Term->getLoc (), commonDest. destBB ,
2592+ commonDest. newSourceBranchArgs );
25572593 Term->eraseFromParent ();
25582594 addToWorklist (BB);
2559- addToWorklist (commonDest);
2595+ addToWorklist (commonDest. destBB );
25602596 return true ;
25612597}
25622598
0 commit comments