Skip to content

Commit c2b13cd

Browse files
authored
Merge pull request #34635 from atrick/verify-critedge
Verify non-critical edges in OSSA
2 parents 56928ba + da0f1ed commit c2b13cd

File tree

5 files changed

+37
-42
lines changed

5 files changed

+37
-42
lines changed

include/swift/SILOptimizer/Utils/CFGOptUtils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ void replaceBranchTarget(TermInst *t, SILBasicBlock *oldDest,
8383
/// Check if the edge from the terminator is critical.
8484
bool isCriticalEdge(TermInst *t, unsigned edgeIdx);
8585

86+
inline bool isNonCriticalEdge(SILBasicBlock *predBB, SILBasicBlock *succBB) {
87+
return predBB->getSingleSuccessorBlock() == succBB
88+
|| succBB->getSinglePredecessorBlock() == predBB;
89+
}
90+
8691
/// Splits the edge from terminator if it is critical.
8792
///
8893
/// Updates dominance information and loop information if not null.

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5201,37 +5201,30 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
52015201

52025202
void verifyBranches(const SILFunction *F) {
52035203
// Verify no critical edge.
5204-
auto isCriticalEdgePred = [](const TermInst *T, unsigned EdgeIdx) {
5205-
assert(T->getSuccessors().size() > EdgeIdx && "Not enough successors");
5206-
5204+
auto requireNonCriticalSucc = [this](const TermInst *termInst,
5205+
const Twine &message) {
52075206
// A critical edge has more than one outgoing edges from the source
52085207
// block.
5209-
auto SrcSuccs = T->getSuccessors();
5210-
if (SrcSuccs.size() <= 1)
5211-
return false;
5212-
5213-
// And its destination block has more than one predecessor.
5214-
SILBasicBlock *DestBB = SrcSuccs[EdgeIdx];
5215-
assert(!DestBB->pred_empty() && "There should be a predecessor");
5216-
if (DestBB->getSinglePredecessorBlock())
5217-
return false;
5208+
auto succBlocks = termInst->getSuccessorBlocks();
5209+
if (succBlocks.size() <= 1)
5210+
return;
52185211

5219-
return true;
5212+
for (const SILBasicBlock *destBB : succBlocks) {
5213+
// And its destination block has more than one predecessor.
5214+
_require(destBB->getSinglePredecessorBlock(), message);
5215+
}
52205216
};
52215217

5222-
for (auto &BB : *F) {
5223-
const TermInst *TI = BB.getTerminator();
5224-
CurInstruction = TI;
5218+
for (auto &bb : *F) {
5219+
const TermInst *termInst = bb.getTerminator();
5220+
CurInstruction = termInst;
52255221

5226-
// FIXME: In OSSA, critical edges will never be allowed.
5227-
// In Lowered SIL, they are allowed on unconditional branches only.
5228-
// if (!(isSILOwnershipEnabled() && F->hasOwnership()))
5229-
if (AllowCriticalEdges && isa<CondBranchInst>(TI))
5230-
continue;
5231-
5232-
for (unsigned Idx = 0, e = BB.getSuccessors().size(); Idx != e; ++Idx) {
5233-
require(!isCriticalEdgePred(TI, Idx),
5234-
"non cond_br critical edges not allowed");
5222+
if (isSILOwnershipEnabled() && F->hasOwnership()) {
5223+
requireNonCriticalSucc(termInst, "critical edges not allowed in OSSA");
5224+
}
5225+
// In Lowered SIL, they are allowed on conditional branches only.
5226+
if (!AllowCriticalEdges && !isa<CondBranchInst>(termInst)) {
5227+
requireNonCriticalSucc(termInst, "only cond_br critical edges allowed");
52355228
}
52365229
}
52375230
}

lib/SILOptimizer/Transforms/CopyPropagation.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -453,12 +453,10 @@ static bool computeLiveness(CopyPropagationState &pass) {
453453
/// (assuming no critical edges).
454454
static void insertDestroyOnCFGEdge(SILBasicBlock *predBB, SILBasicBlock *succBB,
455455
CopyPropagationState &pass) {
456-
// FIXME: ban critical edges and avoid invalidating CFG analyses.
457-
auto *destroyBB = splitIfCriticalEdge(predBB, succBB);
458-
if (destroyBB != succBB)
459-
pass.markInvalid(SILAnalysis::InvalidationKind::Branches);
456+
assert(succBB->getSinglePredecessorBlock() == predBB &&
457+
"value is live-out on another predBB successor: critical edge?");
460458

461-
SILBuilderWithScope builder(destroyBB->begin());
459+
SILBuilderWithScope builder(succBB->begin());
462460
auto *di =
463461
builder.createDestroyValue(succBB->begin()->getLoc(), pass.currDef);
464462

@@ -543,13 +541,8 @@ static void findOrInsertDestroys(CopyPropagationState &pass) {
543541
auto visitBB = [&](SILBasicBlock *bb, SILBasicBlock *succBB) {
544542
switch (pass.liveness.isBlockLive(bb)) {
545543
case LiveOut:
546-
// If succBB is null, then the original destroy must be an inner
547-
// nested destroy, so just skip it.
548-
//
549-
// Otherwise, this CFG edge is a liveness boundary, so insert a new
550-
// destroy on the edge.
551-
if (succBB)
552-
insertDestroyOnCFGEdge(bb, succBB, pass);
544+
assert(succBB && "value live-out of a block where it is consumed");
545+
insertDestroyOnCFGEdge(bb, succBB, pass);
553546
break;
554547
case LiveWithin:
555548
// The liveness boundary is inside this block. Insert a final destroy

lib/SILOptimizer/Utils/CFGOptUtils.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -601,9 +601,10 @@ bool swift::hasCriticalEdges(SILFunction &f, bool onlyNonCondBr) {
601601
if (isa<BranchInst>(bb.getTerminator()))
602602
continue;
603603

604-
for (unsigned idx = 0, e = bb.getSuccessors().size(); idx != e; ++idx)
605-
if (isCriticalEdge(bb.getTerminator(), idx))
604+
for (SILBasicBlock *succBB : bb.getSuccessorBlocks()) {
605+
if (!isNonCriticalEdge(&bb, succBB))
606606
return true;
607+
}
607608
}
608609
return false;
609610
}

test/SILOptimizer/copy_propagation.sil

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,18 @@ bb0(%arg : @owned $T, %addr : $*T):
166166
// CHECK-LABEL: } // end sil function 'testDestroyEdge'
167167
sil [ossa] @testDestroyEdge : $@convention(thin) <T> (@in T, @inout T, Builtin.Int1) -> () {
168168
bb0(%arg : @owned $T, %addr : $*T, %z : $Builtin.Int1):
169-
cond_br %z, bb1, bb2
169+
cond_br %z, bb2, bb1
170170

171171
bb1:
172+
br bb3
173+
174+
bb2:
172175
debug_value %arg : $T
173176
%copy = copy_value %arg : $T
174177
destroy_value %copy : $T
175-
br bb2
178+
br bb3
176179

177-
bb2:
180+
bb3:
178181
destroy_value %arg : $T
179182
%10 = tuple ()
180183
return %10 : $()

0 commit comments

Comments
 (0)