Skip to content

Commit 6662dd5

Browse files
authored
Merge pull request #3569 from gottesmm/rdar26904047
2 parents 0917c01 + ac30242 commit 6662dd5

File tree

3 files changed

+80
-7
lines changed

3 files changed

+80
-7
lines changed

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ PASS(LSLocationPrinter, "lslocation-dump",
169169
"Dump LSLocation results from analyzing all accessed locations")
170170
PASS(MergeCondFails, "merge-cond_fails",
171171
"Remove redundant overflow checks")
172+
PASS(MoveCondFailToPreds, "move-cond-fail-to-preds",
173+
"Test pass that hoists conditional fails to predecessors blocks when "
174+
"profitable")
172175
PASS(NoReturnFolding, "noreturn-folding",
173176
"Add 'unreachable' after noreturn calls")
174177
PASS(RCIdentityDumper, "rc-id-dumper",

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,18 +2121,22 @@ static bool tryMoveCondFailToPreds(SILBasicBlock *BB) {
21212121
// execute the cond_fail speculatively.
21222122
if (!Pred->getSingleSuccessor())
21232123
return false;
2124-
2124+
2125+
// If we already found a constant pred, we do not need to check the incoming
2126+
// value to see if it is constant. We are already going to perform the
2127+
// optimization.
2128+
if (somePredsAreConst)
2129+
continue;
2130+
21252131
SILValue incoming = condArg->getIncomingValue(Pred);
2126-
if (isa<IntegerLiteralInst>(incoming)) {
2127-
somePredsAreConst = true;
2128-
break;
2129-
}
2132+
somePredsAreConst |= isa<IntegerLiteralInst>(incoming);
21302133
}
2134+
21312135
if (!somePredsAreConst)
21322136
return false;
2133-
2137+
21342138
DEBUG(llvm::dbgs() << "move to predecessors: " << *CFI);
2135-
2139+
21362140
// Move the cond_fail to the predecessor blocks.
21372141
for (auto *Pred : BB->getPreds()) {
21382142
SILValue incoming = condArg->getIncomingValue(Pred);
@@ -3504,6 +3508,22 @@ class SROABBArgs : public SILFunctionTransform {
35043508
StringRef getName() override { return "SROA BB Arguments"; }
35053509
};
35063510

3511+
// Used to test tryMoveCondFailToPreds with sil-opt
3512+
class MoveCondFailToPreds : public SILFunctionTransform {
3513+
public:
3514+
MoveCondFailToPreds() {}
3515+
void run() override {
3516+
for (auto &BB : *getFunction()) {
3517+
if (tryMoveCondFailToPreds(&BB)) {
3518+
invalidateAnalysis(
3519+
SILAnalysis::InvalidationKind::BranchesAndInstructions);
3520+
}
3521+
}
3522+
}
3523+
3524+
StringRef getName() override { return "Move Cond Fail To Preds"; }
3525+
};
3526+
35073527
} // End anonymous namespace.
35083528

35093529
/// Splits all critical edges in a function.
@@ -3523,3 +3543,8 @@ SILTransform *swift::createSROABBArgs() { return new SROABBArgs(); }
35233543
SILTransform *swift::createSimplifyBBArgs() {
35243544
return new SimplifyBBArgs();
35253545
}
3546+
3547+
// Moves cond_fail instructions to predecessors.
3548+
SILTransform *swift::createMoveCondFailToPreds() {
3549+
return new MoveCondFailToPreds();
3550+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -move-cond-fail-to-preds | FileCheck %s
2+
3+
import Builtin
4+
import Swift
5+
6+
sil_stage canonical
7+
8+
// Make sure that we actually check all predecessors when we try to hoist
9+
// cond_fails.
10+
//
11+
// CHECK-LABEL: sil @check_all_preds_when_hoisting_cond_fails : $@convention(thin) (Builtin.Int1) -> () {
12+
sil @check_all_preds_when_hoisting_cond_fails : $@convention(thin) (Builtin.Int1) -> () {
13+
bb0(%0 : $Builtin.Int1):
14+
%1 = integer_literal $Builtin.Int1, 0
15+
%2 = integer_literal $Builtin.Int64, 1
16+
%3 = integer_literal $Builtin.Int64, 3
17+
cond_br %0, bb3, bb2
18+
19+
// Make sure that the predecessor order here is not changed. This is necessary
20+
// for the test to actually test that we are checking /all/ predecessors.
21+
//
22+
// CHECK: bb1({{.*}}): // Preds: bb2 bb1
23+
bb1(%7 : $Builtin.Int64, %8 : $Builtin.Int64, %9 : $Builtin.Int1):
24+
%10 = builtin "sadd_with_overflow_Int64"(%8 : $Builtin.Int64, %2 : $Builtin.Int64, %1 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
25+
%11 = tuple_extract %10 : $(Builtin.Int64, Builtin.Int1), 0
26+
cond_fail %9 : $Builtin.Int1
27+
%13 = builtin "sadd_with_overflow_Int64"(%7 : $Builtin.Int64, %2 : $Builtin.Int64, %1 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
28+
%14 = tuple_extract %13 : $(Builtin.Int64, Builtin.Int1), 0
29+
%15 = tuple_extract %13 : $(Builtin.Int64, Builtin.Int1), 1
30+
cond_fail %15 : $Builtin.Int1
31+
%17 = builtin "cmp_eq_Int64"(%14 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
32+
%18 = builtin "cmp_eq_Int64"(%11 : $Builtin.Int64, %3 : $Builtin.Int64) : $Builtin.Int1
33+
cond_br %18, bb3, bb1(%14 : $Builtin.Int64, %11 : $Builtin.Int64, %17 : $Builtin.Int1)
34+
35+
// Make sure there can not be any cond_fail here.
36+
// CHECK: bb2:
37+
// CHECK-NEXT: br bb1
38+
bb2:
39+
br bb1(%2 : $Builtin.Int64, %2 : $Builtin.Int64, %1 : $Builtin.Int1)
40+
41+
// CHECK: bb3:
42+
bb3:
43+
%5 = tuple()
44+
return %5 : $()
45+
}

0 commit comments

Comments
 (0)