summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Analysis/ScalarEvolution.h8
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp20
-rw-r--r--llvm/test/Analysis/ScalarEvolution/nsw.ll20
3 files changed, 36 insertions, 12 deletions
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index d7661272899..408d1233412 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -782,8 +782,12 @@ namespace llvm {
LoopDispositions;
/// A cache of the predicate "does the given loop contain an instruction
- /// that can throw?"
- DenseMap<const Loop *, bool> LoopMayThrow;
+ /// that can abnormally exit the loop (i.e. via throwing an exception, by
+ /// terminating the thread cleanly or by infinite looping in a called
+ /// function)?" The last one is strictly not leaving the loop, but is
+ /// identical to leaving the loop from the viewpoint of reasoning about
+ /// undefined behavior.
+ DenseMap<const Loop *, bool> LoopHasAbnormalExit;
/// Compute a LoopDisposition value.
LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L);
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 111b9b61d1e..2bd7e611917 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4909,19 +4909,19 @@ bool ScalarEvolution::isAddRecNeverPoison(const Instruction *I, const Loop *L) {
if (!LatchControlDependentOnPoison)
return false;
- // Now check if loop is no-throw, and cache the information. In the future,
- // we can consider commoning this logic with LICMSafetyInfo into a separate
- // analysis pass.
+ // Now check if loop has abonormal exits (or not), and cache the information.
- auto Itr = LoopMayThrow.find(L);
- if (Itr == LoopMayThrow.end()) {
- bool MayThrow = false;
+ auto Itr = LoopHasAbnormalExit.find(L);
+ if (Itr == LoopHasAbnormalExit.end()) {
+ bool HasAbnormalExit = false;
for (auto *BB : L->getBlocks()) {
- MayThrow = any_of(*BB, [](Instruction &I) { return I.mayThrow(); });
- if (MayThrow)
+ HasAbnormalExit = any_of(*BB, [](Instruction &I) {
+ return !isGuaranteedToTransferExecutionToSuccessor(&I);
+ });
+ if (HasAbnormalExit)
break;
}
- auto InsertPair = LoopMayThrow.insert({L, MayThrow});
+ auto InsertPair = LoopHasAbnormalExit.insert({L, HasAbnormalExit});
assert(InsertPair.second && "We just checked!");
Itr = InsertPair.first;
}
@@ -5490,7 +5490,7 @@ void ScalarEvolution::forgetLoop(const Loop *L) {
for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I)
forgetLoop(*I);
- LoopMayThrow.erase(L);
+ LoopHasAbnormalExit.erase(L);
}
void ScalarEvolution::forgetValue(Value *V) {
diff --git a/llvm/test/Analysis/ScalarEvolution/nsw.ll b/llvm/test/Analysis/ScalarEvolution/nsw.ll
index e89973be2b0..49050c53d06 100644
--- a/llvm/test/Analysis/ScalarEvolution/nsw.ll
+++ b/llvm/test/Analysis/ScalarEvolution/nsw.ll
@@ -240,3 +240,23 @@ loop:
leave:
ret void
}
+
+declare void @may_exit() nounwind
+
+define void @pr28012(i32 %n) {
+; CHECK-LABEL: Classifying expressions for: @pr28012
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
+ %iv.inc = add nsw i32 %iv, 7
+; CHECK: %iv.inc = add nsw i32 %iv, 7
+; CHECK-NEXT: --> {7,+,7}<nuw><%loop>
+ %becond = icmp ult i32 %iv.inc, %n
+ call void @may_exit()
+ br i1 %becond, label %loop, label %leave
+
+leave:
+ ret void
+}
OpenPOWER on IntegriCloud