@@ -741,9 +741,10 @@ struct InductionInfo {
741
741
// / If we compare for equality we need to make sure that the range does wrap.
742
742
// / We would have trapped either when overflowing or when accessing an array
743
743
// / 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) {
745
746
if (IsOverflowCheckInserted || Cmp != BuiltinValueKind::ICMP_EQ)
746
- return ;
747
+ return false ;
747
748
748
749
auto Loc = Inc->getLoc ();
749
750
auto ResultTy = SILType::getBuiltinIntegerType (1 , Builder.getASTContext ());
@@ -757,6 +758,7 @@ struct InductionInfo {
757
758
auto *CondFail = isOverflowChecked (cast<BuiltinInst>(Inc));
758
759
if (CondFail)
759
760
CondFail->eraseFromParent ();
761
+ return true ;
760
762
}
761
763
};
762
764
@@ -876,11 +878,16 @@ class InductionAnalysis {
876
878
}
877
879
};
878
880
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.
881
883
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);
884
891
}
885
892
886
893
// / Describes the access function "a[f(i)]" that is based on a canonical
@@ -961,11 +968,12 @@ static bool hasArrayType(SILValue Value, SILModule &M) {
961
968
static bool hoistChecksInLoop (DominanceInfo *DT, DominanceInfoNode *DTNode,
962
969
ABCAnalysis &ABC, InductionAnalysis &IndVars,
963
970
SILBasicBlock *Preheader, SILBasicBlock *Header,
964
- SILBasicBlock *ExitingBlk ) {
971
+ SILBasicBlock *SingleExitingBlk ) {
965
972
966
973
bool Changed = false ;
967
974
auto *CurBB = DTNode->getBlock ();
968
- bool blockAlwaysExecutes = isGuaranteedToBeExecuted (DT, CurBB, ExitingBlk);
975
+ bool blockAlwaysExecutes = isGuaranteedToBeExecuted (DT, CurBB,
976
+ SingleExitingBlk);
969
977
970
978
for (auto Iter = CurBB->begin (); Iter != CurBB->end ();) {
971
979
auto Inst = &*Iter;
@@ -1054,7 +1062,7 @@ static bool hoistChecksInLoop(DominanceInfo *DT, DominanceInfoNode *DTNode,
1054
1062
// Traverse the children in the dominator tree.
1055
1063
for (auto Child: *DTNode)
1056
1064
Changed |= hoistChecksInLoop (DT, Child, ABC, IndVars, Preheader,
1057
- Header, ExitingBlk );
1065
+ Header, SingleExitingBlk );
1058
1066
1059
1067
return Changed;
1060
1068
}
@@ -1127,7 +1135,8 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
1127
1135
DEBUG (llvm::dbgs () << " Attempting to hoist checks in " << *Loop);
1128
1136
1129
1137
// Find an exiting block.
1130
- SILBasicBlock *ExitingBlk = Loop->getExitingBlock ();
1138
+ SILBasicBlock *SingleExitingBlk = Loop->getExitingBlock ();
1139
+ SILBasicBlock *ExitingBlk = SingleExitingBlk;
1131
1140
SILBasicBlock *ExitBlk = Loop->getExitBlock ();
1132
1141
SILBasicBlock *Latch = Loop->getLoopLatch ();
1133
1142
if (!ExitingBlk || !Latch || !ExitBlk) {
@@ -1166,7 +1175,11 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
1166
1175
for (auto *Arg: Header->getBBArgs ()) {
1167
1176
if (auto *IV = IndVars[Arg]) {
1168
1177
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);
1170
1183
1171
1184
if (!IV->IsOverflowCheckInserted )
1172
1185
continue ;
@@ -1212,7 +1225,7 @@ static bool hoistBoundsChecks(SILLoop *Loop, DominanceInfo *DT, SILLoopInfo *LI,
1212
1225
1213
1226
// Hoist bounds checks.
1214
1227
Changed |= hoistChecksInLoop (DT, DT->getNode (Header), ABC, IndVars,
1215
- Preheader, Header, ExitingBlk );
1228
+ Preheader, Header, SingleExitingBlk );
1216
1229
if (Changed) {
1217
1230
Preheader->getParent ()->verify ();
1218
1231
}
0 commit comments