Skip to content

Commit ef51eed

Browse files
committed
[LoopDeletion] Handle inner loops w/untaken backedges
This builds on the restricted after initial revert form of D93906, and adds back support for breaking backedges of inner loops. It turns out the original invalidation logic wasn't quite right, specifically around the handling of LCSSA. When breaking the backedge of an inner loop, we can cause blocks which were in the outer loop only because they were also included in a sub-loop to be removed from both loops. This results in the exit block set for our original parent loop changing, and thus a need for new LCSSA phi nodes. This case happens when the inner loop has an exit block which is also an exit block of the parent, and there's a block in the child which reaches an exit to said block without also reaching an exit to the parent loop. (I'm describing this in terms of the immediate parent, but the problem is general for any transitive parent in the nest.) The approach implemented here involves a potentially expensive LCSSA rebuild. Perf testing during review didn't show anything concerning, but we may end up needing to revert this if anyone encounters a practical compile time issue. Differential Revision: https://reviews.llvm.org/D94378
1 parent ba5628f commit ef51eed

File tree

4 files changed

+26
-16
lines changed

4 files changed

+26
-16
lines changed

Diff for: llvm/lib/Transforms/Scalar/LoopDeletion.cpp

-8
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,6 @@ breakBackedgeIfNotTaken(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
151151
if (!BTC->isZero())
152152
return LoopDeletionResult::Unmodified;
153153

154-
// For non-outermost loops, the tricky case is that we can drop blocks
155-
// out of both inner and outer loops at the same time. This results in
156-
// new exiting block for the outer loop appearing, and possibly needing
157-
// an lcssa phi inserted. (See loop_nest_lcssa test case in zero-btc.ll)
158-
// TODO: We can handle a bunch of cases here without much work, revisit.
159-
if (!L->isOutermost())
160-
return LoopDeletionResult::Unmodified;
161-
162154
breakLoopBackedge(L, DT, SE, LI, MSSA);
163155
return LoopDeletionResult::Deleted;
164156
}

Diff for: llvm/lib/Transforms/Utils/LoopUtils.cpp

+15-2
Original file line numberDiff line numberDiff line change
@@ -761,13 +761,18 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
761761
}
762762
}
763763

764+
static Loop *getOutermostLoop(Loop *L) {
765+
while (Loop *Parent = L->getParentLoop())
766+
L = Parent;
767+
return L;
768+
}
769+
764770
void llvm::breakLoopBackedge(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
765771
LoopInfo &LI, MemorySSA *MSSA) {
766-
767-
assert(L->isOutermost() && "Can't yet preserve LCSSA for this case");
768772
auto *Latch = L->getLoopLatch();
769773
assert(Latch && "multiple latches not yet supported");
770774
auto *Header = L->getHeader();
775+
Loop *OutermostLoop = getOutermostLoop(L);
771776

772777
SE.forgetLoop(L);
773778

@@ -790,6 +795,14 @@ void llvm::breakLoopBackedge(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
790795
// Erase (and destroy) this loop instance. Handles relinking sub-loops
791796
// and blocks within the loop as needed.
792797
LI.erase(L);
798+
799+
// If the loop we broke had a parent, then changeToUnreachable might have
800+
// caused a block to be removed from the parent loop (see loop_nest_lcssa
801+
// test case in zero-btc.ll for an example), thus changing the parent's
802+
// exit blocks. If that happened, we need to rebuild LCSSA on the outermost
803+
// loop which might have a had a block removed.
804+
if (OutermostLoop != L)
805+
formLCSSARecursively(*OutermostLoop, DT, &LI, &SE);
793806
}
794807

795808

Diff for: llvm/test/Transforms/IndVarSimplify/X86/pr45360.ll

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ define dso_local i32 @main() {
2323
; CHECK-NEXT: [[I6:%.*]] = load i32, i32* @a, align 4
2424
; CHECK-NEXT: [[I24:%.*]] = load i32, i32* @b, align 4
2525
; CHECK-NEXT: [[D_PROMOTED9:%.*]] = load i32, i32* @d, align 4
26-
; CHECK-NEXT: br label [[BB1:%.*]]
27-
; CHECK: bb1:
26+
; CHECK-NEXT: br label [[BB13_PREHEADER:%.*]]
27+
; CHECK: bb13.preheader:
2828
; CHECK-NEXT: [[I8_LCSSA10:%.*]] = phi i32 [ [[D_PROMOTED9]], [[BB:%.*]] ], [ [[I8:%.*]], [[BB19_PREHEADER:%.*]] ]
2929
; CHECK-NEXT: [[I8]] = and i32 [[I8_LCSSA10]], [[I6]]
3030
; CHECK-NEXT: [[I21:%.*]] = icmp eq i32 [[I8]], 0
@@ -33,7 +33,7 @@ define dso_local i32 @main() {
3333
; CHECK-NEXT: [[I26:%.*]] = urem i32 [[I24]], [[I8]]
3434
; CHECK-NEXT: store i32 [[I26]], i32* @e, align 4
3535
; CHECK-NEXT: [[I30_NOT:%.*]] = icmp eq i32 [[I26]], 0
36-
; CHECK-NEXT: br i1 [[I30_NOT]], label [[BB32_LOOPEXIT:%.*]], label [[BB1]]
36+
; CHECK-NEXT: br i1 [[I30_NOT]], label [[BB32_LOOPEXIT:%.*]], label [[BB13_PREHEADER]]
3737
; CHECK: bb13.preheader.bb27.thread.split_crit_edge:
3838
; CHECK-NEXT: store i32 -1, i32* @f, align 4
3939
; CHECK-NEXT: store i32 0, i32* @d, align 4

Diff for: llvm/test/Transforms/LoopDeletion/zero-btc.ll

+8-3
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,9 @@ define void @test_live_outer() {
302302
; CHECK-NEXT: br label [[INNER:%.*]]
303303
; CHECK: inner:
304304
; CHECK-NEXT: store i32 0, i32* @G, align 4
305-
; CHECK-NEXT: br i1 false, label [[INNER]], label [[LATCH]]
305+
; CHECK-NEXT: br i1 false, label [[INNER_INNER_CRIT_EDGE:%.*]], label [[LATCH]]
306+
; CHECK: inner.inner_crit_edge:
307+
; CHECK-NEXT: unreachable
306308
; CHECK: latch:
307309
; CHECK-NEXT: store i32 [[IV]], i32* @G, align 4
308310
; CHECK-NEXT: [[IV_INC]] = add i32 [[IV]], 1
@@ -346,11 +348,14 @@ define void @loop_nest_lcssa() {
346348
; CHECK: inner_header:
347349
; CHECK-NEXT: br i1 false, label [[INNER_LATCH:%.*]], label [[OUTER_LATCH:%.*]]
348350
; CHECK: inner_latch:
349-
; CHECK-NEXT: br i1 false, label [[INNER_HEADER]], label [[LOOPEXIT:%.*]]
351+
; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi i32 [ [[TMP0]], [[INNER_HEADER]] ]
352+
; CHECK-NEXT: br i1 false, label [[INNER_LATCH_INNER_HEADER_CRIT_EDGE:%.*]], label [[LOOPEXIT:%.*]]
353+
; CHECK: inner_latch.inner_header_crit_edge:
354+
; CHECK-NEXT: unreachable
350355
; CHECK: outer_latch:
351356
; CHECK-NEXT: br label [[OUTER_HEADER]]
352357
; CHECK: loopexit:
353-
; CHECK-NEXT: [[DOTLCSSA32:%.*]] = phi i32 [ [[TMP0]], [[INNER_LATCH]] ]
358+
; CHECK-NEXT: [[DOTLCSSA32:%.*]] = phi i32 [ [[DOTLCSSA]], [[INNER_LATCH]] ]
354359
; CHECK-NEXT: unreachable
355360
;
356361
entry:

0 commit comments

Comments
 (0)