[llvm] 599c273 - [LoopFusion] Forget cached SCEV values after the fusion (#177455)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 22 16:50:26 PST 2026


Author: Alireza Torabian
Date: 2026-01-22T19:50:21-05:00
New Revision: 599c2731b3bbe9add135558377dbee2e1fa24358

URL: https://github.com/llvm/llvm-project/commit/599c2731b3bbe9add135558377dbee2e1fa24358
DIFF: https://github.com/llvm/llvm-project/commit/599c2731b3bbe9add135558377dbee2e1fa24358.diff

LOG: [LoopFusion] Forget cached SCEV values after the fusion (#177455)

This patch fixes the issue #115279. After the fusion, some of the cached
SCEV values such as the induction variable may not be valid anymore and
need to be forgotten.

Added: 
    llvm/test/Transforms/LoopFusion/pr115279.ll

Modified: 
    llvm/lib/Transforms/Scalar/LoopFuse.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/LoopFuse.cpp b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
index 9c86b73dfc8d0..0deeb557ddab8 100644
--- a/llvm/lib/Transforms/Scalar/LoopFuse.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
@@ -1702,6 +1702,10 @@ struct LoopFuser {
     // since merging the latches may affect the dispositions.
     SE.forgetBlockAndLoopDispositions();
 
+    // Forget the cached SCEV values including the induction variable that may
+    // have changed after the fusion.
+    SE.forgetLoop(FC0.L);
+
     // Merge the loops.
     SmallVector<BasicBlock *, 8> Blocks(FC1.L->blocks());
     for (BasicBlock *BB : Blocks) {

diff  --git a/llvm/test/Transforms/LoopFusion/pr115279.ll b/llvm/test/Transforms/LoopFusion/pr115279.ll
new file mode 100644
index 0000000000000..64ea639aaa8fc
--- /dev/null
+++ b/llvm/test/Transforms/LoopFusion/pr115279.ll
@@ -0,0 +1,53 @@
+; REQUIRES: asserts
+; RUN: opt -passes=loop-fusion -disable-output -stats < %s 2>&1 | FileCheck -check-prefix=STAT %s
+; STAT: 1 loop-fusion - Loops fused
+
+; C Code
+;
+;;  for (i = 0; i < n; i++)
+;;      array2[i] = array1[i] * 2;
+;;  for (i = 0; i < n; i++)
+;;      if (array1[i] % 2 == 0)
+;;          array2[i] = array1[i] * array1[i];
+; Loop fusion should not crash due to incorrect cached SCEV values as now
+; forgetLoop() is used to reset them after the fusion.
+
+define dso_local noundef i32 @forget_induction_scev(ptr noalias %array1, ptr noalias %array2) {
+entry:
+  br label %for.body
+
+for.body:
+  %indvars.iv54 = phi i64 [ %indvars.iv.next55, %for.body ], [ 0, %entry ]
+  %arrayidx6 = getelementptr inbounds i32, ptr %array1, i64 %indvars.iv54
+  %0 = load i32, ptr %arrayidx6, align 4
+  %mul = shl nsw i32 %0, 1
+  %arrayidx8 = getelementptr inbounds i32, ptr %array2, i64 %indvars.iv54
+  store i32 %mul, ptr %arrayidx8, align 4
+  %indvars.iv.next55 = add nuw nsw i64 %indvars.iv54, 1
+  %exitcond57.not = icmp eq i64 %indvars.iv.next55, 1024
+  br i1 %exitcond57.not, label %for.body14, label %for.body
+
+for.body14:
+  %indvars.iv58 = phi i64 [ %indvars.iv.next59, %for.inc26 ], [ 0, %for.body ]
+  %arrayidx16 = getelementptr inbounds i32, ptr %array1, i64 %indvars.iv58
+  %1 = load i32, ptr %arrayidx16, align 4
+  %2 = and i32 %1, 1
+  %cmp18 = icmp eq i32 %2, 0
+  br i1 %cmp18, label %if.then, label %for.inc26
+
+if.then:
+  %mul23 = mul nsw i32 %1, %1
+  %arrayidx25 = getelementptr inbounds i32, ptr %array2, i64 %indvars.iv58
+  store i32 %mul23, ptr %arrayidx25, align 4
+  br label %for.inc26
+
+for.inc26:
+  %indvars.iv.next59 = add nuw nsw i64 %indvars.iv58, 1
+  %exitcond61.not = icmp eq i64 %indvars.iv.next59, 1024
+  br i1 %exitcond61.not, label %for.end28, label %for.body14
+
+for.end28:
+  %arrayidx30 = getelementptr inbounds i8, ptr %array2, i64 4092
+  %3 = load i32, ptr %arrayidx30, align 4
+  ret i32 %3
+}


        


More information about the llvm-commits mailing list