Skip to content

Commit a0a2a1e

Browse files
committed
[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 #140444.
1 parent 0b553e0 commit a0a2a1e

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

llvm/lib/Transforms/Utils/LoopPeel.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,12 +343,12 @@ bool llvm::canPeelLastIteration(const Loop &L, ScalarEvolution &SE) {
343343
// codegen. For now, it must
344344
// * exit via the latch,
345345
// * the exit condition must be a NE/EQ compare of an induction with step
346-
// of 1.
346+
// of 1 and must only be used by the exiting branch.
347347
BasicBlock *Latch = L.getLoopLatch();
348348
return Latch && Latch == L.getExitingBlock() &&
349349
match(Latch->getTerminator(),
350-
m_Br(m_ICmp(Pred, m_Value(Inc), m_Value()), m_BasicBlock(Succ1),
351-
m_BasicBlock(Succ2))) &&
350+
m_Br(m_OneUse(m_ICmp(Pred, m_Value(Inc), m_Value())),
351+
m_BasicBlock(Succ1), m_BasicBlock(Succ2))) &&
352352
((Pred == CmpInst::ICMP_EQ && Succ2 == L.getHeader()) ||
353353
(Pred == CmpInst::ICMP_NE && Succ1 == L.getHeader())) &&
354354
isa<SCEVAddRecExpr>(SE.getSCEV(Inc)) &&

llvm/test/Transforms/LoopUnroll/peel-last-iteration.ll

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,46 @@ exit:
635635
ret i64 %iv
636636
}
637637

638+
; Test for https://github.com/llvm/llvm-project/issues/140444.
639+
define void @exit_condition_has_other_loop_users() {
640+
; CHECK-LABEL: define void @exit_condition_has_other_loop_users() {
641+
; CHECK-NEXT: [[ENTRY:.*]]:
642+
; CHECK-NEXT: br label %[[LOOP_HEADER:.*]]
643+
; CHECK: [[LOOP_HEADER]]:
644+
; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i16 [ 0, %[[ENTRY]] ], [ [[IV_NEXT_PEEL:%.*]], %[[LOOP_LATCH:.*]] ]
645+
; CHECK-NEXT: [[IV_NEXT_PEEL]] = add i16 [[IV_NEXT_LCSSA]], 1
646+
; CHECK-NEXT: [[EC_PEEL:%.*]] = icmp eq i16 [[IV_NEXT_LCSSA]], 100
647+
; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[LOOP_LATCH]], label %[[THEN:.*]]
648+
; CHECK: [[THEN]]:
649+
; CHECK-NEXT: call void @foo(i32 10)
650+
; CHECK-NEXT: br label %[[LOOP_LATCH]]
651+
; CHECK: [[LOOP_LATCH]]:
652+
; CHECK-NEXT: call void @foo(i32 20)
653+
; CHECK-NEXT: br i1 [[EC_PEEL]], label %[[EXIT:.*]], label %[[LOOP_HEADER]]
654+
; CHECK: [[EXIT]]:
655+
; CHECK-NEXT: ret void
656+
;
657+
entry:
658+
br label %loop.header
659+
660+
loop.header:
661+
%iv = phi i16 [ 0, %entry ], [ %iv.next, %loop.latch ]
662+
%iv.next = add i16 %iv, 1
663+
%ec = icmp eq i16 %iv, 100
664+
br i1 %ec, label %loop.latch, label %then
665+
666+
then:
667+
call void @foo(i32 10)
668+
br label %loop.latch
669+
670+
loop.latch:
671+
call void @foo(i32 20)
672+
br i1 %ec, label %exit, label %loop.header
673+
674+
exit:
675+
ret void
676+
}
677+
638678
declare void @foo(i32)
639679
declare i1 @cond()
640680
;.

0 commit comments

Comments
 (0)