diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -1336,6 +1336,10 @@ /// be infinite without side effects without also being undefined) bool isMustProgress(const Loop *L); +/// Return true if this loop can be assumed to run for a finite number of +/// iterations. +bool isFinite(const Loop *L); + /// Return whether an MDNode might represent an access group. /// /// Access group metadata nodes have to be distinct and empty. Being diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -1107,6 +1107,10 @@ return getOptionalIntLoopAttribute(TheLoop, Name).getValueOr(Default); } +bool llvm::isFinite(const Loop *L) { + return L->getHeader()->getParent()->willReturn(); +} + static const char *LLVMLoopMustProgress = "llvm.loop.mustprogress"; bool llvm::hasMustProgress(const Loop *L) { diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -7017,7 +7017,7 @@ // A mustprogress loop without side effects must be finite. // TODO: The check used here is very conservative. It's only *specific* // side effects which are well defined in infinite loops. - return isMustProgress(L) && loopHasNoSideEffects(L); + return isFinite(L) || (isMustProgress(L) && loopHasNoSideEffects(L)); } const SCEV *ScalarEvolution::createSCEV(Value *V) { diff --git a/llvm/test/Analysis/ScalarEvolution/lt-overflow.ll b/llvm/test/Analysis/ScalarEvolution/lt-overflow.ll --- a/llvm/test/Analysis/ScalarEvolution/lt-overflow.ll +++ b/llvm/test/Analysis/ScalarEvolution/lt-overflow.ll @@ -28,6 +28,13 @@ ; CHECK: Loop %for.body: Unpredictable backedge-taken count. ; CHECK: Determining loop execution counts for: @test_gt ; CHECK: Loop %for.body: Unpredictable backedge-taken count. +; CHECK: Determining loop execution counts for: @test_willreturn +; CHECK: Loop %for.body: backedge-taken count is ((-1 + (1024 umax %N)) /u 1024) +; CHECK: Determining loop execution counts for: @test_nowillreturn +; CHECK: Loop %for.body: Unpredictable backedge-taken count. +; TODO: investigate why willreturn is still needed on the callsite +; CHECK: Determining loop execution counts for: @test_willreturn_nocallsite +; CHECK: Loop %for.body: Unpredictable backedge-taken count. define void @test(i32 %N) mustprogress { entry: @@ -198,3 +205,50 @@ for.cond.cleanup: ret void } + +declare void @sideeffect() + +define void @test_willreturn(i32 %S, i32 %N) willreturn { +entry: + br label %for.body + +for.body: + %iv = phi i32 [ %iv.next, %for.body ], [ 0, %entry ] + %iv.next = add i32 %iv, 1024 + call void @sideeffect() nounwind willreturn + %cmp = icmp ult i32 %iv.next, %N + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: + ret void +} + +define void @test_nowillreturn(i32 %S, i32 %N) { +entry: + br label %for.body + +for.body: + %iv = phi i32 [ %iv.next, %for.body ], [ 0, %entry ] + %iv.next = add i32 %iv, 1024 + call void @sideeffect() nounwind willreturn + %cmp = icmp ult i32 %iv.next, %N + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: + ret void +} + +define void @test_willreturn_nocallsite(i32 %S, i32 %N) willreturn { +entry: + br label %for.body + +for.body: + %iv = phi i32 [ %iv.next, %for.body ], [ 0, %entry ] + %iv.next = add i32 %iv, 1024 + call void @sideeffect() nounwind + %cmp = icmp ult i32 %iv.next, %N + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: + ret void +}