@@ -1123,49 +1123,79 @@ static bool onlyHasTerminatorAndDebugInsts(SILBasicBlock *BB) {
1123
1123
return true ;
1124
1124
}
1125
1125
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) {
1129
1157
// Ignore blocks with more than one instruction.
1130
- if (!onlyHasTerminatorAndDebugInsts (SBB ))
1131
- return nullptr ;
1158
+ if (!onlyHasTerminatorAndDebugInsts (targetBB ))
1159
+ return ;
1132
1160
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 ;
1136
1164
1137
- // Disallow infinite loops through SBB .
1165
+ // Disallow infinite loops through targetBB .
1138
1166
llvm::SmallPtrSet<SILBasicBlock *, 8 > VisitedBBs;
1139
- BranchInst *NextBI = BI ;
1167
+ BranchInst *nextBI = targetBranch ;
1140
1168
do {
1141
- SILBasicBlock *NextBB = NextBI ->getDestBB ();
1169
+ SILBasicBlock *nextBB = nextBI ->getDestBB ();
1142
1170
// We don't care about infinite loops after SBB.
1143
- if (!VisitedBBs.insert (NextBB ).second )
1171
+ if (!VisitedBBs.insert (nextBB ).second )
1144
1172
break ;
1145
1173
// 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);
1154
1178
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
+ }
1166
1185
}
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 ();
1169
1199
}
1170
1200
1171
1201
// / \return If this is a basic block without any arguments and it has
@@ -1334,17 +1364,18 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
1334
1364
1335
1365
// If the destination block is a simple trampoline (jump to another block)
1336
1366
// 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 );
1342
1373
// Eliminating the trampoline can expose opportunities to improve the
1343
1374
// new block we branch to.
1344
1375
if (LoopHeaders.count (DestBB))
1345
1376
LoopHeaders.insert (BB);
1346
1377
1347
- addToWorklist (TrampolineDest );
1378
+ addToWorklist (trampolineDest. destBB );
1348
1379
BI->eraseFromParent ();
1349
1380
removeIfDead (DestBB);
1350
1381
addToWorklist (BB);
@@ -1535,14 +1566,17 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
1535
1566
1536
1567
// If the destination block is a simple trampoline (jump to another block)
1537
1568
// 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 ());
1543
1576
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 ());
1546
1580
BI->eraseFromParent ();
1547
1581
1548
1582
if (LoopHeaders.count (TrueSide))
@@ -1552,15 +1586,17 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
1552
1586
return true ;
1553
1587
}
1554
1588
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 ());
1560
1596
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 ());
1564
1600
BI->eraseFromParent ();
1565
1601
if (LoopHeaders.count (FalseSide))
1566
1602
LoopHeaders.insert (ThisBB);
@@ -1571,31 +1607,32 @@ bool SimplifyCFG::simplifyCondBrBlock(CondBranchInst *BI) {
1571
1607
1572
1608
// Simplify cond_br where both sides jump to the same blocks with the same
1573
1609
// args.
1574
- auto condBrToBr = [&](OperandValueArrayRef branchArgs,
1575
- SILBasicBlock *newDest) {
1610
+ auto condBrToBr = [&](ArrayRef<SILValue> branchArgs, SILBasicBlock *newDest) {
1576
1611
LLVM_DEBUG (llvm::dbgs ()
1577
1612
<< " replace cond_br with same dests with br: " << *BI);
1578
1613
SILBuilderWithScope (BI).createBranch (BI->getLoc (), newDest, branchArgs);
1579
1614
BI->eraseFromParent ();
1580
1615
addToWorklist (ThisBB);
1581
1616
++NumConstantFolded;
1582
1617
};
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 ;
1597
1635
}
1598
-
1599
1636
auto *TrueTrampolineBr = getTrampolineWithoutBBArgsTerminator (TrueSide);
1600
1637
if (TrueTrampolineBr &&
1601
1638
!wouldIntroduceCriticalEdge (BI, TrueTrampolineBr->getDestBB ())) {
@@ -2531,32 +2568,31 @@ bool SimplifyCFG::simplifyTryApplyBlock(TryApplyInst *TAI) {
2531
2568
// to trampoline jumps to the same destination block. The successor blocks
2532
2569
// and the destination blocks may have no arguments.
2533
2570
bool SimplifyCFG::simplifyTermWithIdenticalDestBlocks (SILBasicBlock *BB) {
2534
- SILBasicBlock * commonDest = nullptr ;
2571
+ TrampolineDest commonDest;
2535
2572
for (auto *SuccBlock : BB->getSuccessorBlocks ()) {
2536
2573
if (SuccBlock->getNumArguments () != 0 )
2537
2574
return false ;
2538
- SILBasicBlock *DestBlock = getTrampolineDest ( SuccBlock);
2539
- if (!DestBlock)
2575
+ auto trampolineDest = TrampolineDest (BB, SuccBlock);
2576
+ if (!trampolineDest) {
2540
2577
return false ;
2578
+ }
2579
+ // The branch must have the same destination and same branch arguments.
2541
2580
if (!commonDest) {
2542
- commonDest = DestBlock ;
2543
- } else if (DestBlock != commonDest) {
2581
+ commonDest = std::move (trampolineDest) ;
2582
+ } else if (trampolineDest != commonDest) {
2544
2583
return false ;
2545
2584
}
2546
2585
}
2547
- if (!commonDest)
2586
+ if (!commonDest) {
2548
2587
return false ;
2549
-
2550
- assert (commonDest->getNumArguments () == 0 &&
2551
- " getTrampolineDest should have checked that commonDest has no args" );
2552
-
2588
+ }
2553
2589
TermInst *Term = BB->getTerminator ();
2554
2590
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 );
2557
2593
Term->eraseFromParent ();
2558
2594
addToWorklist (BB);
2559
- addToWorklist (commonDest);
2595
+ addToWorklist (commonDest. destBB );
2560
2596
return true ;
2561
2597
}
2562
2598
0 commit comments