[llvm] 0d04c77 - [ScalarEvolution] Mark a loop as finite if in a willreturn function
William S. Moses via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 28 11:17:09 PST 2022
Author: William S. Moses
Date: 2022-01-28T14:17:05-05:00
New Revision: 0d04c778562a38d8035438e8ea72d280fd11b994
URL: https://github.com/llvm/llvm-project/commit/0d04c778562a38d8035438e8ea72d280fd11b994
DIFF: https://github.com/llvm/llvm-project/commit/0d04c778562a38d8035438e8ea72d280fd11b994.diff
LOG: [ScalarEvolution] Mark a loop as finite if in a willreturn function
A limited version of (https://reviews.llvm.org/D118090) that only marks a loop as finite if in a willreturn function.
Reviewed By: jdoerfert
Differential Revision: https://reviews.llvm.org/D118429
Added:
Modified:
llvm/include/llvm/Analysis/LoopInfo.h
llvm/lib/Analysis/LoopInfo.cpp
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/test/Analysis/ScalarEvolution/lt-overflow.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h
index b2326c4714dd2..1ef198197bfcc 100644
--- a/llvm/include/llvm/Analysis/LoopInfo.h
+++ b/llvm/include/llvm/Analysis/LoopInfo.h
@@ -1336,6 +1336,10 @@ bool hasMustProgress(const Loop *L);
/// 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
index dd69587161272..b161c490a6bc2 100644
--- a/llvm/lib/Analysis/LoopInfo.cpp
+++ b/llvm/lib/Analysis/LoopInfo.cpp
@@ -1107,6 +1107,10 @@ int llvm::getIntLoopAttribute(const Loop *TheLoop, StringRef Name,
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
index 07aac1523b478..56eb7c6b767d7 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -7017,7 +7017,7 @@ bool ScalarEvolution::loopIsFiniteByAssumption(const Loop *L) {
// 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
index 58c2cc3e1da21..62a14c4525445 100644
--- a/llvm/test/Analysis/ScalarEvolution/lt-overflow.ll
+++ b/llvm/test/Analysis/ScalarEvolution/lt-overflow.ll
@@ -28,6 +28,13 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK: Loop %for.body: <multiple exits> 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.body:
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
+}
More information about the llvm-commits
mailing list