Skip to content

Commit 824cf85

Browse files
committed
Fix SimplifyCFG jump-threading to cleanup after itself.
Avoid extra blocks and/or extra iterations in the simplify loop.
1 parent 8278332 commit 824cf85

File tree

1 file changed

+50
-25
lines changed

1 file changed

+50
-25
lines changed

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,14 @@ struct ThreadInfo {
284284

285285
} // end anonymous namespace
286286

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.
287292
bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
288293
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');
290295
auto *SrcTerm = cast<BranchInst>(ti.Src->getTerminator());
291296

292297
BasicBlockCloner Cloner(SrcTerm->getDestBB());
@@ -297,28 +302,33 @@ bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
297302

298303
// We have copied the threaded block into the edge.
299304
auto *clonedSrc = Cloner.getNewBB();
305+
SmallVector<SILBasicBlock *, 4> clonedSuccessors(
306+
clonedSrc->getSuccessorBlocks().begin(),
307+
clonedSrc->getSuccessorBlocks().end());
308+
SILBasicBlock *ThreadedSuccessorBlock = nullptr;
300309

301310
// Rewrite the cloned branch to eliminate the non-taken path.
302311
if (auto *CondTerm = dyn_cast<CondBranchInst>(clonedSrc->getTerminator())) {
303312
// We know the direction this conditional branch is going to take thread
304313
// 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");
307316

308-
auto *ThreadedSuccessorBlock =
309-
clonedSrc->getSuccessors()[ti.ThreadedSuccessorIdx].getBB();
317+
ThreadedSuccessorBlock =
318+
clonedSrc->getSuccessors()[ti.ThreadedSuccessorIdx].getBB();
310319
auto Args = ti.ThreadedSuccessorIdx == 0 ? CondTerm->getTrueArgs()
311-
: CondTerm->getFalseArgs();
320+
: CondTerm->getFalseArgs();
312321

313-
SILBuilderWithScope(CondTerm)
314-
.createBranch(CondTerm->getLoc(), ThreadedSuccessorBlock, Args);
322+
SILBuilderWithScope(CondTerm).createBranch(CondTerm->getLoc(),
323+
ThreadedSuccessorBlock, Args);
315324

316325
CondTerm->eraseFromParent();
326+
317327
} else {
318328
// Get the enum element and the destination block of the block we jump
319329
// thread.
320330
auto *SEI = cast<SwitchEnumInst>(clonedSrc->getTerminator());
321-
auto *ThreadedSuccessorBlock = SEI->getCaseDestination(ti.EnumCase);
331+
ThreadedSuccessorBlock = SEI->getCaseDestination(ti.EnumCase);
322332

323333
// Instantiate the payload if necessary.
324334
SILBuilderWithScope Builder(SEI);
@@ -329,19 +339,29 @@ bool SimplifyCFG::threadEdge(const ThreadInfo &ti) {
329339
auto Ty = EnumTy.getEnumElementType(ti.EnumCase, SEI->getModule(),
330340
Builder.getTypeExpansionContext());
331341
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");
336346
Builder.createBranch(SEI->getLoc(), ThreadedSuccessorBlock, {UED});
337-
} else
347+
348+
} else {
338349
Builder.createBranch(SEI->getLoc(), ThreadedSuccessorBlock,
339350
ArrayRef<SILValue>());
351+
}
340352
SEI->eraseFromParent();
341353
}
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+
}
345365
Cloner.updateSSAAfterCloning();
346366
return true;
347367
}
@@ -564,8 +584,9 @@ bool SimplifyCFG::dominatorBasedSimplifications(SILFunction &Fn,
564584
return Changed;
565585

566586
for (auto &ThreadInfo : JumpThreadableEdges) {
567-
if (threadEdge(ThreadInfo))
587+
if (threadEdge(ThreadInfo)) {
568588
Changed = true;
589+
}
569590
}
570591

571592
return Changed;
@@ -1269,6 +1290,10 @@ static bool hasLessInstructions(SILBasicBlock *block, SILBasicBlock *other) {
12691290

12701291
/// simplifyBranchBlock - Simplify a basic block that ends with an unconditional
12711292
/// 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.
12721297
bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
12731298
// If we are asked to not simplify unconditional branches (for testing
12741299
// purposes), exit early.
@@ -1385,13 +1410,6 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
13851410

13861411
return true;
13871412
}
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-
13951413
return Simplified;
13961414
}
13971415

@@ -2652,6 +2670,13 @@ bool SimplifyCFG::simplifyBlocks() {
26522670
Changed = true;
26532671
continue;
26542672
}
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+
}
26552680
break;
26562681
case TermKind::CondBranchInst:
26572682
Changed |= simplifyCondBrBlock(cast<CondBranchInst>(TI));

0 commit comments

Comments
 (0)