[llvm] a0a2a1e - [LoopPeel] Make sure exit condition has a single use when peeling last.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Sun May 18 03:48:48 PDT 2025
Author: Florian Hahn
Date: 2025-05-18T11:47:12+01:00
New Revision: a0a2a1e095ddd092e668b0b3f9a7dfa9655255e1
URL: https://github.com/llvm/llvm-project/commit/a0a2a1e095ddd092e668b0b3f9a7dfa9655255e1
DIFF: https://github.com/llvm/llvm-project/commit/a0a2a1e095ddd092e668b0b3f9a7dfa9655255e1.diff
LOG: [LoopPeel] Make sure exit condition has a single use when peeling last.
Update the check in canPeelLastIteration to make sure the exiting
condition has a single use. When peeling the last iteration, we adjust
the condition in the loop body to be true one iteration early, which
would be incorrect for other users.
Fixes https://github.com/llvm/llvm-project/issues/140444.
Added:
Modified:
llvm/lib/Transforms/Utils/LoopPeel.cpp
llvm/test/Transforms/LoopUnroll/peel-last-iteration.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/LoopPeel.cpp b/llvm/lib/Transforms/Utils/LoopPeel.cpp
index 646354bba9df6..4eaa3c9714370 100644
--- a/llvm/lib/Transforms/Utils/LoopPeel.cpp
+++ b/llvm/lib/Transforms/Utils/LoopPeel.cpp
@@ -343,12 +343,12 @@ bool llvm::canPeelLastIteration(const Loop &L, ScalarEvolution &SE) {
// codegen. For now, it must
// * exit via the latch,
// * the exit condition must be a NE/EQ compare of an induction with step
- // of 1.
+ // of 1 and must only be used by the exiting branch.
BasicBlock *Latch = L.getLoopLatch();
return Latch && Latch == L.getExitingBlock() &&
match(Latch->getTerminator(),
- m_Br(m_ICmp(Pred, m_Value(Inc), m_Value()), m_BasicBlock(Succ1),
- m_BasicBlock(Succ2))) &&
+ m_Br(m_OneUse(m_ICmp(Pred, m_Value(Inc), m_Value())),
+ m_BasicBlock(Succ1), m_BasicBlock(Succ2))) &&
((Pred == CmpInst::ICMP_EQ && Succ2 == L.getHeader()) ||
(Pred == CmpInst::ICMP_NE && Succ1 == L.getHeader())) &&
isa<SCEVAddRecExpr>(SE.getSCEV(Inc)) &&
diff --git a/llvm/test/Transforms/LoopUnroll/peel-last-iteration.ll b/llvm/test/Transforms/LoopUnroll/peel-last-iteration.ll
index 78a13b83ec8d1..b28c5db7dc9a0 100644
--- a/llvm/test/Transforms/LoopUnroll/peel-last-iteration.ll
+++ b/llvm/test/Transforms/LoopUnroll/peel-last-iteration.ll
@@ -635,6 +635,46 @@ exit:
ret i64 %iv
}
+; Test for https://github.com/llvm/llvm-project/issues/140444.
+define void @exit_condition_has_other_loop_users() {
+; CHECK-LABEL: define void @exit_condition_has_other_loop_users() {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
+; CHECK: [[LOOP_HEADER]]:
+; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i16 [ 0, %[[ENTRY]] ], [ [[IV_NEXT_PEEL:%.*]], %[[LOOP_LATCH:.*]] ]
+; CHECK-NEXT: [[IV_NEXT_PEEL]] = add i16 [[IV_NEXT_LCSSA]], 1
+; CHECK-NEXT: [[EC_PEEL:%.*]] = icmp eq i16 [[IV_NEXT_LCSSA]], 100
+; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[LOOP_LATCH]], label %[[THEN:.*]]
+; CHECK: [[THEN]]:
+; CHECK-NEXT: call void @foo(i32 10)
+; CHECK-NEXT: br label %[[LOOP_LATCH]]
+; CHECK: [[LOOP_LATCH]]:
+; CHECK-NEXT: call void @foo(i32 20)
+; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[EXIT:.*]], label %[[LOOP_HEADER]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %loop.header
+
+loop.header:
+ %iv = phi i16 [ 0, %entry ], [ %iv.next, %loop.latch ]
+ %iv.next = add i16 %iv, 1
+ %ec = icmp eq i16 %iv, 100
+ br i1 %ec, label %loop.latch, label %then
+
+then:
+ call void @foo(i32 10)
+ br label %loop.latch
+
+loop.latch:
+ call void @foo(i32 20)
+ br i1 %ec, label %exit, label %loop.header
+
+exit:
+ ret void
+}
+
declare void @foo(i32)
declare i1 @cond()
;.
More information about the llvm-commits
mailing list