Skip to content

Commit 9036976

Browse files
committed
Fix EagerSpecializer to avoid critical edges.
1 parent 5a87482 commit 9036976

File tree

6 files changed

+419
-356
lines changed

6 files changed

+419
-356
lines changed

include/swift/SIL/SILBuilder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2501,6 +2501,10 @@ class SILBuilderWithScope : public SILBuilder {
25012501
: SILBuilder(BB, InheritScopeFrom->getDebugScope(),
25022502
B.getBuilderContext()) {}
25032503

2504+
explicit SILBuilderWithScope(SILBasicBlock *BB, SILBuilderContext &C,
2505+
const SILDebugScope *debugScope)
2506+
: SILBuilder(BB, debugScope, C) {}
2507+
25042508
/// Creates a new SILBuilder with an insertion point at the
25052509
/// beginning of BB and the debug scope from the first
25062510
/// non-metainstruction in the BB.

include/swift/SILOptimizer/Utils/CFGOptUtils.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@ void splitEdgesFromTo(SILBasicBlock *from, SILBasicBlock *to,
118118
DominanceInfo *domInfo = nullptr,
119119
SILLoopInfo *loopInfo = nullptr);
120120

121+
/// Create a basic block to serve as the target of a conditional branch, or
122+
/// other terminator with multiple successors. This avoids introducing critical
123+
/// edges when inserting conditional branches.
124+
///
125+
/// This is a lightweight helper that assumes no block arguments and does not
126+
/// update dominators or loops. For more general functionality, just create the
127+
/// conditional branch then call splitCriticalEdge to fix it up.
128+
SILBasicBlock *createSplitBranchTarget(SILBasicBlock *targetBlock,
129+
SILBuilder &builder,
130+
SILLocation loc);
131+
121132
/// Splits the basic block before the instruction with an unconditional branch
122133
/// and updates the dominator tree and loop info. Returns the new, branched to
123134
/// block that contains the end of \p SplitBeforeInst's block.

lib/SILOptimizer/Transforms/EagerSpecializer.cpp

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ emitTypeCheck(SILBasicBlock *FailedTypeCheckBB, SubstitutableType *ParamTy,
483483
{GenericMTVal, SpecializedMTVal});
484484

485485
auto *SuccessBB = Builder.getFunction().createBasicBlock();
486-
Builder.createCondBranch(Loc, Cmp, SuccessBB, FailedTypeCheckBB);
486+
auto *FailBB = createSplitBranchTarget(FailedTypeCheckBB, Builder, Loc);
487+
Builder.createCondBranch(Loc, Cmp, SuccessBB, FailBB);
487488
Builder.emitBlock(SuccessBB);
488489
}
489490

@@ -510,7 +511,8 @@ void EagerDispatch::emitIsTrivialCheck(SILBasicBlock *FailedTypeCheckBB,
510511
auto IsPOD = Builder.createBuiltin(Loc, Ctx.getIdentifier("ispod"), BoolTy,
511512
SubMap, {GenericMT});
512513
auto *SuccessBB = Builder.getFunction().createBasicBlock();
513-
Builder.createCondBranch(Loc, IsPOD, SuccessBB, FailedTypeCheckBB);
514+
auto *FailBB = createSplitBranchTarget(FailedTypeCheckBB, Builder, Loc);
515+
Builder.createCondBranch(Loc, IsPOD, SuccessBB, FailBB);
514516
Builder.emitBlock(SuccessBB);
515517
}
516518

@@ -542,14 +544,16 @@ void EagerDispatch::emitTrivialAndSizeCheck(SILBasicBlock *FailedTypeCheckBB,
542544
{ParamSize, LayoutSize});
543545

544546
auto *SuccessBB1 = Builder.getFunction().createBasicBlock();
545-
Builder.createCondBranch(Loc, Cmp, SuccessBB1, FailedTypeCheckBB);
547+
auto *FailBB1 = createSplitBranchTarget(FailedTypeCheckBB, Builder, Loc);
548+
Builder.createCondBranch(Loc, Cmp, SuccessBB1, FailBB1);
546549
Builder.emitBlock(SuccessBB1);
547550
// Emit a check that it is a pod object.
548551
// TODO: Perform this check before all the fixed size checks!
549552
auto IsPOD = Builder.createBuiltin(Loc, Ctx.getIdentifier("ispod"),
550553
BoolTy, SubMap, { GenericMT });
551554
auto *SuccessBB2 = Builder.getFunction().createBasicBlock();
552-
Builder.createCondBranch(Loc, IsPOD, SuccessBB2, FailedTypeCheckBB);
555+
auto *FailBB2 = createSplitBranchTarget(FailedTypeCheckBB, Builder, Loc);
556+
Builder.createCondBranch(Loc, IsPOD, SuccessBB2, FailBB2);
553557
Builder.emitBlock(SuccessBB2);
554558
}
555559

@@ -580,11 +584,11 @@ void EagerDispatch::emitRefCountedObjectCheck(SILBasicBlock *FailedTypeCheckBB,
580584
{CanBeClass, ClassConst});
581585

582586
auto *SuccessBB = Builder.getFunction().createBasicBlock();
583-
auto *MayBeCallsCheckBB = Builder.getFunction().createBasicBlock();
584-
Builder.createCondBranch(Loc, Cmp1, SuccessBB,
585-
MayBeCallsCheckBB);
587+
auto *MayBeClassCheckBB = Builder.getFunction().createBasicBlock();
588+
auto *SwiftClassBB = createSplitBranchTarget(SuccessBB, Builder, Loc);
589+
Builder.createCondBranch(Loc, Cmp1, SwiftClassBB, MayBeClassCheckBB);
586590

587-
Builder.emitBlock(MayBeCallsCheckBB);
591+
Builder.emitBlock(MayBeClassCheckBB);
588592

589593
auto MayBeClassConst =
590594
Builder.createIntegerLiteral(Loc, Int8Ty, 2);
@@ -594,8 +598,9 @@ void EagerDispatch::emitRefCountedObjectCheck(SILBasicBlock *FailedTypeCheckBB,
594598
{CanBeClass, MayBeClassConst});
595599

596600
auto *IsClassCheckBB = Builder.getFunction().createBasicBlock();
597-
Builder.createCondBranch(Loc, Cmp2, IsClassCheckBB,
598-
FailedTypeCheckBB);
601+
auto *FailClassCheckBB =
602+
createSplitBranchTarget(FailedTypeCheckBB, Builder, Loc);
603+
Builder.createCondBranch(Loc, Cmp2, IsClassCheckBB, FailClassCheckBB);
599604

600605
Builder.emitBlock(IsClassCheckBB);
601606

@@ -610,7 +615,9 @@ void EagerDispatch::emitRefCountedObjectCheck(SILBasicBlock *FailedTypeCheckBB,
610615
auto Member = Members[0];
611616
auto BoolValue =
612617
Builder.emitStructExtract(Loc, IsClassRuntimeCheck, Member, BoolTy);
613-
Builder.createCondBranch(Loc, BoolValue, SuccessBB, FailedTypeCheckBB);
618+
auto *FailBB = createSplitBranchTarget(FailedTypeCheckBB, Builder, Loc);
619+
auto *ObjCOrExistentialBB = createSplitBranchTarget(SuccessBB, Builder, Loc);
620+
Builder.createCondBranch(Loc, BoolValue, ObjCOrExistentialBB, FailBB);
614621

615622
Builder.emitBlock(SuccessBB);
616623
}

lib/SILOptimizer/Utils/CFGOptUtils.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,17 @@ bool swift::isCriticalEdge(TermInst *t, unsigned edgeIdx) {
494494
return true;
495495
}
496496

497+
SILBasicBlock *swift::createSplitBranchTarget(SILBasicBlock *targetBlock,
498+
SILBuilder &builder,
499+
SILLocation loc) {
500+
auto *function = targetBlock->getParent();
501+
auto *edgeBB = function->createBasicBlockBefore(targetBlock);
502+
SILBuilderWithScope(edgeBB, builder.getBuilderContext(),
503+
builder.getCurrentDebugScope())
504+
.createBranch(loc, targetBlock);
505+
return edgeBB;
506+
}
507+
497508
/// Splits the basic block at the iterator with an unconditional branch and
498509
/// updates the dominator tree and loop info.
499510
SILBasicBlock *swift::splitBasicBlockAndBranch(SILBuilder &builder,

0 commit comments

Comments
 (0)