[llvm] [loop-idiom] Forget outer loop scev when loop-idiom introduces memset… (PR #150916)

Sushant Gokhale via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 28 03:04:58 PDT 2025


https://github.com/sushgokh created https://github.com/llvm/llvm-project/pull/150916

… in the outer loop

Before 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.
Ideally, I would expect store to be considered as an instruction that introduces side effects like the memset but this generates lot of test failures.

Fixes #149377

>From b3fc9c68e31c264f4e53a973c97bdef126e679be Mon Sep 17 00:00:00 2001
From: sgokhale <sgokhale at nvidia.com>
Date: Mon, 28 Jul 2025 02:48:10 -0700
Subject: [PATCH] [loop-idiom] Forget outer loop scev when loop-idiom
 introduces memset in the outer loop

Before 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.
Ideally, I would expect store to be considered as an instruction that
introduces side effects like the memset but this generates lot of test
failures.

Fixes #149377
---
 .../Transforms/Scalar/LoopIdiomRecognize.cpp  |  5 ++
 .../AArch64/introduce-memset-in-outerloop.ll  | 48 +++++++++++++++++++
 2 files changed, 53 insertions(+)
 create mode 100644 llvm/test/Transforms/LoopIdiom/AArch64/introduce-memset-in-outerloop.ll

diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 03b92d3338a98..7cee8a7525c42 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -1154,6 +1154,11 @@ bool LoopIdiomRecognize::processLoopStridedStore(
 
   NewCall->setDebugLoc(TheStore->getDebugLoc());
 
+  auto *MemsetLoop = LI->getLoopFor(NewCall->getParent());
+  // FIXME: We should invalidate scev only if the loop already does not have any
+  // side effects.
+  SE->forgetLoop(MemsetLoop);
+
   if (MSSAU) {
     MemoryAccess *NewMemAcc = MSSAU->createMemoryAccessInBB(
         NewCall, nullptr, NewCall->getParent(), MemorySSA::BeforeTerminator);
diff --git a/llvm/test/Transforms/LoopIdiom/AArch64/introduce-memset-in-outerloop.ll b/llvm/test/Transforms/LoopIdiom/AArch64/introduce-memset-in-outerloop.ll
new file mode 100644
index 0000000000000..924db26cd573e
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/AArch64/introduce-memset-in-outerloop.ll
@@ -0,0 +1,48 @@
+; REQUIRES: asserts
+; RUN: opt <%s -p "loop(loop-idiom)" -verify-scev -o /dev/null
+
+
+; 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;
+; }
+
+; Make sure we do not crash when verifying scev.
+
+ at a = external global [0 x i8]
+
+define void @foo()  {
+entry:
+  br label %outerL
+
+outerL:                              ; preds = %entry, %outerLatch
+  %e = phi i64 [ undef, %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