@@ -284,9 +284,14 @@ struct ThreadInfo {
284
284
285
285
} // end anonymous namespace
286
286
287
+ // FIXME: It would be far more efficient to clone the jump-threaded region using
288
+ // a single invocation of the RegionCloner (see ArrayPropertyOpt) instead of a
289
+ // BasicBlockCloner. Cloning a single block at a time forces the cloner to
290
+ // create four extra blocks that immediately become dead after the conditional
291
+ // branch and its clone is converted to an unconditional branch.
287
292
bool SimplifyCFG::threadEdge (const ThreadInfo &ti) {
288
293
LLVM_DEBUG (llvm::dbgs () << " thread edge from bb" << ti.Src ->getDebugID ()
289
- << " to bb" << ti.Dest ->getDebugID () << ' \n ' );
294
+ << " to bb" << ti.Dest ->getDebugID () << ' \n ' );
290
295
auto *SrcTerm = cast<BranchInst>(ti.Src ->getTerminator ());
291
296
292
297
BasicBlockCloner Cloner (SrcTerm->getDestBB ());
@@ -297,28 +302,33 @@ bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
297
302
298
303
// We have copied the threaded block into the edge.
299
304
auto *clonedSrc = Cloner.getNewBB ();
305
+ SmallVector<SILBasicBlock *, 4 > clonedSuccessors (
306
+ clonedSrc->getSuccessorBlocks ().begin (),
307
+ clonedSrc->getSuccessorBlocks ().end ());
308
+ SILBasicBlock *ThreadedSuccessorBlock = nullptr ;
300
309
301
310
// Rewrite the cloned branch to eliminate the non-taken path.
302
311
if (auto *CondTerm = dyn_cast<CondBranchInst>(clonedSrc->getTerminator ())) {
303
312
// We know the direction this conditional branch is going to take thread
304
313
// it.
305
- assert (clonedSrc->getSuccessors ().size () > ti.ThreadedSuccessorIdx &&
306
- " Threaded terminator does not have enough successors" );
314
+ assert (clonedSrc->getSuccessors ().size () > ti.ThreadedSuccessorIdx
315
+ && " Threaded terminator does not have enough successors" );
307
316
308
- auto * ThreadedSuccessorBlock =
309
- clonedSrc->getSuccessors ()[ti.ThreadedSuccessorIdx ].getBB ();
317
+ ThreadedSuccessorBlock =
318
+ clonedSrc->getSuccessors ()[ti.ThreadedSuccessorIdx ].getBB ();
310
319
auto Args = ti.ThreadedSuccessorIdx == 0 ? CondTerm->getTrueArgs ()
311
- : CondTerm->getFalseArgs ();
320
+ : CondTerm->getFalseArgs ();
312
321
313
- SILBuilderWithScope (CondTerm)
314
- . createBranch (CondTerm-> getLoc (), ThreadedSuccessorBlock, Args);
322
+ SILBuilderWithScope (CondTerm). createBranch (CondTerm-> getLoc (),
323
+ ThreadedSuccessorBlock, Args);
315
324
316
325
CondTerm->eraseFromParent ();
326
+
317
327
} else {
318
328
// Get the enum element and the destination block of the block we jump
319
329
// thread.
320
330
auto *SEI = cast<SwitchEnumInst>(clonedSrc->getTerminator ());
321
- auto * ThreadedSuccessorBlock = SEI->getCaseDestination (ti.EnumCase );
331
+ ThreadedSuccessorBlock = SEI->getCaseDestination (ti.EnumCase );
322
332
323
333
// Instantiate the payload if necessary.
324
334
SILBuilderWithScope Builder (SEI);
@@ -329,19 +339,29 @@ bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
329
339
auto Ty = EnumTy.getEnumElementType (ti.EnumCase , SEI->getModule (),
330
340
Builder.getTypeExpansionContext ());
331
341
SILValue UED (
332
- Builder.createUncheckedEnumData (Loc, EnumVal, ti.EnumCase , Ty));
333
- assert (UED->getType () ==
334
- (*ThreadedSuccessorBlock->args_begin ())->getType () &&
335
- " Argument types must match" );
342
+ Builder.createUncheckedEnumData (Loc, EnumVal, ti.EnumCase , Ty));
343
+ assert (UED->getType ()
344
+ == (*ThreadedSuccessorBlock->args_begin ())->getType ()
345
+ && " Argument types must match" );
336
346
Builder.createBranch (SEI->getLoc (), ThreadedSuccessorBlock, {UED});
337
- } else
347
+
348
+ } else {
338
349
Builder.createBranch (SEI->getLoc (), ThreadedSuccessorBlock,
339
350
ArrayRef<SILValue>());
351
+ }
340
352
SEI->eraseFromParent ();
341
353
}
342
- // After rewriting the cloned branch, split the critical edge.
343
- // This does not currently update DominanceInfo.
344
- Cloner.splitCriticalEdges (nullptr , nullptr );
354
+ // If the jump-threading target "Dest" had multiple predecessors, then the
355
+ // cloner will have created unconditional branch predecessors, which can
356
+ // now be removed or folded after converting the source block "Src" to an
357
+ // unconditional branch.
358
+ for (auto *succBB : clonedSuccessors) {
359
+ removeIfDead (succBB);
360
+ }
361
+ if (auto *branchInst =
362
+ dyn_cast<BranchInst>(ThreadedSuccessorBlock->getTerminator ())) {
363
+ simplifyBranchBlock (branchInst);
364
+ }
345
365
Cloner.updateSSAAfterCloning ();
346
366
return true ;
347
367
}
@@ -564,8 +584,9 @@ bool SimplifyCFG::dominatorBasedSimplifications(SILFunction &Fn,
564
584
return Changed;
565
585
566
586
for (auto &ThreadInfo : JumpThreadableEdges) {
567
- if (threadEdge (ThreadInfo))
587
+ if (threadEdge (ThreadInfo)) {
568
588
Changed = true ;
589
+ }
569
590
}
570
591
571
592
return Changed;
@@ -1269,6 +1290,10 @@ static bool hasLessInstructions(SILBasicBlock *block, SILBasicBlock *other) {
1269
1290
1270
1291
// / simplifyBranchBlock - Simplify a basic block that ends with an unconditional
1271
1292
// / branch.
1293
+ // /
1294
+ // / Performs trivial trampoline removal. May be called as a utility to cleanup
1295
+ // / successors after removing conditional branches or predecessors after
1296
+ // / deleting unreachable blocks.
1272
1297
bool SimplifyCFG::simplifyBranchBlock (BranchInst *BI) {
1273
1298
// If we are asked to not simplify unconditional branches (for testing
1274
1299
// purposes), exit early.
@@ -1385,13 +1410,6 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
1385
1410
1386
1411
return true ;
1387
1412
}
1388
-
1389
- // If this unconditional branch has BBArgs, check to see if duplicating the
1390
- // destination would allow it to be simplified. This is a simple form of jump
1391
- // threading.
1392
- if (!isVeryLargeFunction && tryJumpThreading (BI))
1393
- return true ;
1394
-
1395
1413
return Simplified;
1396
1414
}
1397
1415
@@ -2652,6 +2670,13 @@ bool SimplifyCFG::simplifyBlocks() {
2652
2670
Changed = true ;
2653
2671
continue ;
2654
2672
}
2673
+ // If this unconditional branch has BBArgs, check to see if duplicating
2674
+ // the destination would allow it to be simplified. This is a simple form
2675
+ // of jump threading.
2676
+ if (!isVeryLargeFunction && tryJumpThreading (cast<BranchInst>(TI))) {
2677
+ Changed = true ;
2678
+ continue ;
2679
+ }
2655
2680
break ;
2656
2681
case TermKind::CondBranchInst:
2657
2682
Changed |= simplifyCondBrBlock (cast<CondBranchInst>(TI));
0 commit comments