[llvm] e8918c3 - [SCEV] Consider non-volatile memory intrinsics as not having side-effect for forward progress (#150916)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 11 00:24:53 PDT 2025
Author: Sushant Gokhale
Date: 2025-08-11T00:24:50-07:00
New Revision: e8918c318ee62973867e7ac3d3250a4478f2f04d
URL: https://github.com/llvm/llvm-project/commit/e8918c318ee62973867e7ac3d3250a4478f2f04d
DIFF: https://github.com/llvm/llvm-project/commit/e8918c318ee62973867e7ac3d3250a4478f2f04d.diff
LOG: [SCEV] Consider non-volatile memory intrinsics as not having side-effect for forward progress (#150916)
For the attached test:
Before the loop-idiom pass, we have a store into the inner loop which is
considered simple and one that does not have any side effects on the
loop. Post loop-idiom pass, we get a memset into the outer loop that is
considered to introduce side effects on the loop. This changes the
backedge taken count before and after the pass and hence, the crash with
verify-scev.
We try to consider non-volatile memory intrinsics as not having
side-effect for forward progress to fix the issue.
Fixes #149377
Added:
llvm/test/Transforms/LoopIdiom/introduce-memset-in-outerloop.ll
Modified:
llvm/lib/Analysis/ScalarEvolution.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 477e4771e04aa..c20b1bdaf94c7 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -7435,7 +7435,15 @@ ScalarEvolution::getLoopProperties(const Loop *L) {
if (auto *SI = dyn_cast<StoreInst>(I))
return !SI->isSimple();
- return I->mayThrow() || I->mayWriteToMemory();
+ if (I->mayThrow())
+ return true;
+
+ // Non-volatile memset / memcpy do not count as side-effect for forward
+ // progress.
+ if (isa<MemIntrinsic>(I) && !I->isVolatile())
+ return false;
+
+ return I->mayWriteToMemory();
};
LoopProperties LP = {/* HasNoAbnormalExits */ true,
diff --git a/llvm/test/Transforms/LoopIdiom/introduce-memset-in-outerloop.ll b/llvm/test/Transforms/LoopIdiom/introduce-memset-in-outerloop.ll
new file mode 100644
index 0000000000000..bf78ebae3dc3d
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/introduce-memset-in-outerloop.ll
@@ -0,0 +1,47 @@
+; RUN: opt <%s -p "print<scalar-evolution>" -disable-output 2>&1 | FileCheck %s
+; RUN: opt <%s -p "loop(loop-idiom),print<scalar-evolution>" -disable-output 2>&1 | FileCheck %s
+
+; CHECK: backedge-taken count is i64 1
+
+; IR corresponds to the following C test:
+; extern char a[];
+; void foo() {
+; for (long c = 0; c < 6; c += -2078836808675943215)
+; for (long d; d < 6; d++)
+; a[c + d] = 0;
+; }
+
+ at a = external global [0 x i8]
+
+define void @foo() {
+entry:
+ br label %outerL
+
+outerL: ; preds = %entry, %outerLatch
+ %e = phi i64 [ poison, %entry ], [ %lcssa, %outerLatch ]
+ %c = phi i64 [ 0, %entry ], [ %c.next, %outerLatch ]
+ %e.cmp = icmp slt i64 %e, 6
+ br i1 %e.cmp, label %innerL, label %outerLatch
+
+innerL: ; preds = %outerL, %innerL
+ %d = phi i64 [ %d.next, %innerL ], [ %e, %outerL ]
+ %add = add nsw i64 %d, %c
+ %arrayidx = getelementptr inbounds [0 x i8], ptr @a, i64 0, i64 %add
+ store i8 0, ptr %arrayidx
+ %d.next = add nsw i64 %d, 1
+ %d.cmp = icmp slt i64 %d, 5
+ br i1 %d.cmp, label %innerL, label %outerLatch, !llvm.loop !0
+
+outerLatch: ; preds = %innerL, %outerL
+ %lcssa = phi i64 [ %e, %outerL ], [ %d.next, %innerL ]
+ %c.next = add nsw i64 %c, -2078836808675943215
+ %c.cmp = icmp slt i64 %c, 2078836808675943221
+ br i1 %c.cmp, label %outerL, label %exit, !llvm.loop !1
+
+exit: ; preds = %outerLatch
+ ret void
+}
+
+!0 = distinct !{!0, !2}
+!1 = distinct !{!1, !2}
+!2 = !{!"llvm.loop.mustprogress"}
More information about the llvm-commits
mailing list