[llvm] Scev assume finite flag (PR #91104)
via llvm-commits
llvm-commits at lists.llvm.org
Sat May 4 21:18:41 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-analysis
Author: Manuel Drehwald (ZuseZ4)
<details>
<summary>Changes</summary>
@<!-- -->nikic The first of three PRs, as mentioned in https://github.com/llvm/llvm-project/pull/83052#issuecomment-2060253177
@<!-- -->skewballfox is busy with some other work, so we discussed that I'll try to finish the upstreaming.
---
Full diff: https://github.com/llvm/llvm-project/pull/91104.diff
3 Files Affected:
- (modified) llvm/include/llvm/Analysis/ScalarEvolution.h (+3)
- (modified) llvm/lib/Analysis/ScalarEvolution.cpp (+4-1)
- (modified) llvm/unittests/Analysis/ScalarEvolutionTest.cpp (+30)
``````````diff
diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 5828cc156cc785..0399499a6224e6 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -460,6 +460,9 @@ class ScalarEvolution {
LoopComputable ///< The SCEV varies predictably with the loop.
};
+ bool AssumeLoopFinite = false;
+ void setAssumeLoopExits();
+
/// An enum describing the relationship between a SCEV and a basic block.
enum BlockDisposition {
DoesNotDominateBlock, ///< The SCEV does not dominate the block.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 93f885c5d5ad8b..2f8bdb3ee366dc 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -509,6 +509,8 @@ const SCEV *ScalarEvolution::getVScale(Type *Ty) {
return S;
}
+void ScalarEvolution::setAssumeLoopExits() { this->AssumeLoopFinite = true; }
+
const SCEV *ScalarEvolution::getElementCount(Type *Ty, ElementCount EC) {
const SCEV *Res = getConstant(Ty, EC.getKnownMinValue());
if (EC.isScalable())
@@ -7422,7 +7424,8 @@ 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 isFinite(L) || (isMustProgress(L) && loopHasNoSideEffects(L));
+ return AssumeLoopFinite || isFinite(L) ||
+ (isMustProgress(L) && loopHasNoSideEffects(L));
}
const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
diff --git a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
index a7b3c5c404ab75..24c07096b12b3f 100644
--- a/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -1085,6 +1085,36 @@ TEST_F(ScalarEvolutionsTest, SCEVComputeExpressionSize) {
EXPECT_EQ(S2S->getExpressionSize(), 5u);
}
+TEST_F(ScalarEvolutionsTest, AssumeLoopExists) {
+ LLVMContext C;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(
+ "define void @foo(i32 %N) { "
+ "entry: "
+ " %cmp3 = icmp sgt i32 %N, 0 "
+ " br i1 %cmp3, label %for.body, label %for.cond.cleanup "
+ "for.cond.cleanup: "
+ " ret void "
+ "for.body: "
+ " br label %for.body "
+ "} "
+ "declare i32 @llvm.loop.decrement.reg.i32.i32.i32(i32, i32) ",
+ Err, C);
+
+ ASSERT_TRUE(M && "Could not parse module?");
+ ASSERT_TRUE(!verifyModule(*M) && "Must have been well formed!");
+
+ runWithSE(*M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
+ BasicBlock *L = F.begin()->getNextNode()->getNextNode();
+ auto *Loop = LI.getLoopFor(L);
+ bool IsFinite = SE.loopIsFiniteByAssumption(Loop);
+ EXPECT_FALSE(IsFinite);
+ SE.setAssumeLoopExits();
+ IsFinite = SE.loopIsFiniteByAssumption(Loop);
+ EXPECT_TRUE(IsFinite);
+ });
+}
+
TEST_F(ScalarEvolutionsTest, SCEVLoopDecIntrinsic) {
LLVMContext C;
SMDiagnostic Err;
``````````
</details>
https://github.com/llvm/llvm-project/pull/91104
More information about the llvm-commits
mailing list