Skip to content

Commit 180098e

Browse files
committed
Merge pull request #2436 from eeckstein/abcopt-fix
ABCOpt: we should not hoist bounds/overflow checks if the loop has mu…
2 parents abb2879 + 0c97cfa commit 180098e

File tree

2 files changed

+34
-19
lines changed

2 files changed

+34
-19
lines changed

lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -741,9 +741,10 @@ struct InductionInfo {
741741
/// If we compare for equality we need to make sure that the range does wrap.
742742
/// We would have trapped either when overflowing or when accessing an array
743743
/// out of bounds in the original loop.
744-
void checkOverflow(SILBuilder &Builder) {
744+
/// Returns true if an overflow check was inserted.
745+
bool checkOverflow(SILBuilder &Builder) {
745746
if (IsOverflowCheckInserted || Cmp != BuiltinValueKind::ICMP_EQ)
746-
return;
747+
return false;
747748

748749
auto Loc = Inc->getLoc();
749750
auto ResultTy = SILType::getBuiltinIntegerType(1, Builder.getASTContext());
@@ -757,6 +758,7 @@ struct InductionInfo {
757758
auto *CondFail = isOverflowChecked(cast<BuiltinInst>(Inc));
758759
if (CondFail)
759760
CondFail->eraseFromParent();
761+
return true;
760762
}
761763
};
762764

@@ -876,11 +878,16 @@ class InductionAnalysis {
876878
}
877879
};
878880

879-
/// A block in the loop is guaranteed to be executed if it dominates the exiting
880-
/// block.
881+
/// A block in the loop is guaranteed to be executed if it dominates the single
882+
/// exiting block.
881883
static bool isGuaranteedToBeExecuted(DominanceInfo *DT, SILBasicBlock *Block,
882-
SILBasicBlock *ExitingBlk) {
883-
return DT->dominates(Block, ExitingBlk);
884+
SILBasicBlock *SingleExitingBlk) {
885+
// If there are multiple exiting blocks then no block in the loop is
886+
// guaranteed to be executed in _all_ iterations until the upper bound of the
887+
// induction variable is reached.
888+
if (!SingleExitingBlk)
889+
return false;
890+
return DT->dominates(Block, SingleExitingBlk);
884891
}
885892

886893
/// Describes the access function "a[f(i)]" that is based on a canonical
@@ -961,11 +968,12 @@ static bool hasArrayType(SILValue Value, SILModule &M) {
961968
static bool hoistChecksInLoop(DominanceInfo *DT, DominanceInfoNode *DTNode,
962969
ABCAnalysis &ABC, InductionAnalysis &IndVars,
963970
SILBasicBlock *Preheader, SILBasicBlock *Header,
964-
SILBasicBlock *ExitingBlk) {
971+
SILBasicBlock *SingleExitingBlk) {
965972

966973
bool Changed = false;
967974
auto *CurBB = DTNode->getBlock();
968-
bool blockAlwaysExecutes = isGuaranteedToBeExecuted(DT, CurBB, ExitingBlk);
975+
bool blockAlwaysExecutes = isGuaranteedToBeExecuted(DT, CurBB,
976+
SingleExitingBlk);
969977

970978
for (auto Iter = CurBB->begin(); Iter != CurBB->end();) {
971979
auto Inst = &*Iter;
@@ -1054,7 +1062,7 @@ static bool hoistChecksInLoop(DominanceInfo *DT, DominanceInfoNode *DTNode,
10541062
// Traverse the children in the dominator tree.
10551063
for (auto Child: *DTNode)
10561064
Changed |= hoistChecksInLoop(DT, Child, ABC, IndVars, Preheader,
1057-
Header, ExitingBlk);
1065+
Header, SingleExitingBlk);
10581066

10591067
return Changed;
10601068
}
@@ -1127,7 +1135,8 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
11271135
DEBUG(llvm::dbgs() << "Attempting to hoist checks in " << *Loop);
11281136

11291137
// Find an exiting block.
1130-
SILBasicBlock *ExitingBlk = Loop->getExitingBlock();
1138+
SILBasicBlock *SingleExitingBlk = Loop->getExitingBlock();
1139+
SILBasicBlock *ExitingBlk = SingleExitingBlk;
11311140
SILBasicBlock *ExitBlk = Loop->getExitBlock();
11321141
SILBasicBlock *Latch = Loop->getLoopLatch();
11331142
if (!ExitingBlk || !Latch || !ExitBlk) {
@@ -1166,7 +1175,11 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
11661175
for (auto *Arg: Header->getBBArgs()) {
11671176
if (auto *IV = IndVars[Arg]) {
11681177
SILBuilderWithScope B(Preheader->getTerminator(), IV->getInstruction());
1169-
IV->checkOverflow(B);
1178+
1179+
// Only if the loop has a single exiting block (which contains the
1180+
// induction variable check) we may hoist the overflow check.
1181+
if (SingleExitingBlk)
1182+
Changed |= IV->checkOverflow(B);
11701183

11711184
if (!IV->IsOverflowCheckInserted)
11721185
continue;
@@ -1212,7 +1225,7 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
12121225

12131226
// Hoist bounds checks.
12141227
Changed |= hoistChecksInLoop(DT, DT->getNode(Header), ABC, IndVars,
1215-
Preheader, Header, ExitingBlk);
1228+
Preheader, Header, SingleExitingBlk);
12161229
if (Changed) {
12171230
Preheader->getParent()->verify();
12181231
}

test/SILOptimizer/abcopts.sil

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,17 +1124,19 @@ sil @unknown : $@convention(thin) () -> Builtin.Int1
11241124

11251125
// RANGECHECK-LABEL: sil @rangeCheck_early_exit
11261126
// RANGECHECK: bb0
1127+
// RANGECHECK: cond_fail
11271128
// RANGECHECK: cond_br {{.*}}, bb2, bb1
1128-
// RANGECHECK: bb1
1129-
// RANGECHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
1129+
// RANGECHECK: bb1:
1130+
// RANGECHECK-NOT: cond_fail
11301131
// RANGECHECK: br bb3
1131-
// RANGECHECK: bb2
1132+
// RANGECHECK: bb2:
11321133
// RANGECHECK: return
1133-
// RANGECHECK: bb3
1134+
// RANGECHECK: bb3({{.*}}):
1135+
// RANGECHECK: apply
11341136
// RANGECHECK: cond_br {{.*}}, bb4, bb2
1135-
// RANGECHECK: bb4
1136-
// RANGECHECK: builtin "xor_Int1"([[TRUE]]
1137-
// RANGECHECK: builtin "xor_Int1"([[TRUE]]
1137+
// RANGECHECK: bb4:
1138+
// RANGECHECK: cond_fail
1139+
// RANGECHECK: cond_fail
11381140
// RANGECHECK: cond_br {{.*}}, bb2, bb3
11391141
// RANGECHECK: }
11401142
sil @rangeCheck_early_exit : $@convention(thin) (Builtin.Int64) -> () {

0 commit comments

Comments
 (0)