[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