[llvm] b09fceb - [LoopFusion] Reform LCSSA after peelFusionCandidate's peelLoop (#200442)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 01:43:35 PDT 2026


Author: Madhur Amilkanthwar
Date: 2026-06-04T08:43:30Z
New Revision: b09fceba26bf6d34465821460deb40b3834cf50f

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

LOG: [LoopFusion] Reform LCSSA after peelFusionCandidate's peelLoop (#200442)

peelLoop's internal simplifyLoop call requires LCSSA to be preserved
across it, but the cloned exit edges and cloned defs that peelLoop
introduces are not reflected in the existing LCSSA phis, so the contract
cannot be honoured. Pass PreserveLCSSA=false to peelLoop here and reform
LCSSA on the affected nest immediately afterward. LCSSA is expected
before and after peel+fuse, just not during it.

Caught by yarpgen fuzzing of clang -O3 -fexperimental-loop-fusion -mllvm
-loop-fusion-peel-max-count=8 on AArch64.

Fixes #199418

Added: 
    llvm/test/Transforms/LoopFusion/peel-preserve-lcssa.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 bce9a04ddd0b2..be3da8aa8c0b6 100644
--- a/llvm/lib/Transforms/Scalar/LoopFuse.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
@@ -665,7 +665,11 @@ struct LoopFuser {
                       << " iterations of the first loop. \n");
 
     ValueToValueMapTy VMap;
-    peelLoop(FC0.L, PeelCount, false, &LI, &SE, DT, &AC, true, VMap);
+    // LoopFusion is a function pass that neither requires nor preserves
+    // LCSSA, so peelLoop need not preserve it across its internal
+    // simplifyLoop call.
+    peelLoop(FC0.L, PeelCount, /*PeelLast=*/false, &LI, &SE, DT, &AC,
+             /*PreserveLCSSA=*/false, VMap);
     FC0.Peeled = true;
     LLVM_DEBUG(dbgs() << "Done Peeling\n");
 

diff  --git a/llvm/test/Transforms/LoopFusion/peel-preserve-lcssa.ll b/llvm/test/Transforms/LoopFusion/peel-preserve-lcssa.ll
new file mode 100644
index 0000000000000..295c07fe55f2c
--- /dev/null
+++ b/llvm/test/Transforms/LoopFusion/peel-preserve-lcssa.ll
@@ -0,0 +1,45 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=loop-fusion -loop-fusion-peel-max-count=8 < %s | FileCheck %s
+
+define void @lcssa_peel_repro() {
+; CHECK-LABEL: define void @lcssa_peel_repro() {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[OUTER_HEADER:.*]]
+; CHECK:       [[OUTER_HEADER_LOOPEXIT:.*]]:
+; CHECK-NEXT:    br label %[[OUTER_HEADER]]
+; CHECK:       [[OUTER_HEADER]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[XOR:%.*]], %[[OUTER_HEADER_LOOPEXIT]] ]
+; CHECK-NEXT:    br label %[[INNER1_PEEL_BEGIN:.*]]
+; CHECK:       [[INNER1_PEEL_BEGIN]]:
+; CHECK-NEXT:    br label %[[INNER1_PEEL:.*]]
+; CHECK:       [[INNER1_PEEL]]:
+; CHECK-NEXT:    [[XOR_PEEL:%.*]] = xor i64 0, 0
+; CHECK-NEXT:    [[CMP_PEEL:%.*]] = icmp ult i64 0, 1
+; CHECK-NEXT:    br label %[[INNER1_PEEL_NEXT:.*]]
+; CHECK:       [[INNER1_PEEL_NEXT]]:
+; CHECK-NEXT:    br label %[[INNER1_PEEL_NEXT1:.*]]
+; CHECK:       [[INNER1_PEEL_NEXT1]]:
+; CHECK-NEXT:    br label %[[OUTER_HEADER_PEEL_NEWPH:.*]]
+; CHECK:       [[OUTER_HEADER_PEEL_NEWPH]]:
+; CHECK-NEXT:    br label %[[INNER1:.*]]
+; CHECK:       [[INNER1]]:
+; CHECK-NEXT:    [[XOR]] = xor i64 0, 0
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 1, 1
+; CHECK-NEXT:    br i1 false, label %[[INNER1]], label %[[OUTER_HEADER_LOOPEXIT]]
+;
+entry:
+  br label %outer.header
+
+outer.header:                                     ; preds = %inner2, %entry
+  %iv = phi i64 [ 0, %entry ], [ %xor, %inner2 ]
+  br label %inner1
+
+inner1:                                           ; preds = %inner1, %outer.header
+  %i = phi i64 [ 0, %outer.header ], [ 1, %inner1 ]
+  %xor = xor i64 0, 0
+  %cmp = icmp ult i64 %i, 1
+  br i1 %cmp, label %inner1, label %inner2
+
+inner2:                                           ; preds = %inner2, %inner1
+  br i1 false, label %inner2, label %outer.header
+}


        


More information about the llvm-commits mailing list