diff options
-rw-r--r-- | llvm/include/llvm/Analysis/ScalarEvolution.h | 8 | ||||
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 20 | ||||
-rw-r--r-- | llvm/test/Analysis/ScalarEvolution/nsw.ll | 20 |
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 +} |