diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -393,11 +393,16 @@ if (!L->getLoopLatch()) return LoopDeletionResult::Unmodified; - auto *BTC = SE.getBackedgeTakenCount(L); - if (!isa(BTC) && SE.isKnownNonZero(BTC)) - return LoopDeletionResult::Unmodified; - if (!BTC->isZero() && !canProveExitOnFirstIteration(L, DT, LI)) - return LoopDeletionResult::Unmodified; + auto *BTCMax = SE.getConstantMaxBackedgeTakenCount(L); + if (!BTCMax->isZero()) { + auto *BTC = SE.getBackedgeTakenCount(L); + if (!BTC->isZero()) { + if (!isa(BTC) && SE.isKnownNonZero(BTC)) + return LoopDeletionResult::Unmodified; + if (!canProveExitOnFirstIteration(L, DT, LI)) + return LoopDeletionResult::Unmodified; + } + } breakLoopBackedge(L, DT, SE, LI, MSSA); return LoopDeletionResult::Deleted; diff --git a/llvm/test/Transforms/LoopDeletion/switch.ll b/llvm/test/Transforms/LoopDeletion/switch.ll --- a/llvm/test/Transforms/LoopDeletion/switch.ll +++ b/llvm/test/Transforms/LoopDeletion/switch.ll @@ -41,3 +41,38 @@ unreachable: unreachable } + +define void @func_2() { +; CHECK-LABEL: @func_2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LBL_2368:%.*]] +; CHECK: lbl_2368: +; CHECK-NEXT: br i1 false, label [[CLEANUP967:%.*]], label [[UNREACHABLE:%.*]] +; CHECK: cleanup967: +; CHECK-NEXT: switch i32 undef, label [[CLEANUP1169:%.*]] [ +; CHECK-NEXT: i32 20, label [[CLEANUP967_LBL_2368_CRIT_EDGE:%.*]] +; CHECK-NEXT: ] +; CHECK: cleanup967.lbl_2368_crit_edge: +; CHECK-NEXT: unreachable +; CHECK: cleanup1169: +; CHECK-NEXT: ret void +; CHECK: unreachable: +; CHECK-NEXT: unreachable +; +entry: + br label %lbl_2368 + +lbl_2368: + br i1 false, label %cleanup967, label %unreachable + +cleanup967: + switch i32 undef, label %cleanup1169 [ + i32 20, label %lbl_2368 + ] + +cleanup1169: + ret void + +unreachable: + unreachable +} diff --git a/llvm/test/Transforms/LoopDeletion/zero-btc.ll b/llvm/test/Transforms/LoopDeletion/zero-btc.ll --- a/llvm/test/Transforms/LoopDeletion/zero-btc.ll +++ b/llvm/test/Transforms/LoopDeletion/zero-btc.ll @@ -239,6 +239,42 @@ ret void } +declare i1 @unknown() + +; We can't compute an exit count for the latch, but we know the upper +; bound on the trip count is zero anyways. +define void @test_dead_latch1() { +; CHECK-LABEL: @test_dead_latch1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: store i32 0, i32* @G, align 4 +; CHECK-NEXT: br i1 false, label [[LATCH:%.*]], label [[EXIT1:%.*]] +; CHECK: latch: +; CHECK-NEXT: [[LATCHCOND:%.*]] = call i1 @unknown() +; CHECK-NEXT: br label [[EXIT2:%.*]] +; CHECK: exit1: +; CHECK-NEXT: ret void +; CHECK: exit2: +; CHECK-NEXT: ret void +; +entry: + br label %loop + +loop: + store i32 0, i32* @G + br i1 false, label %latch, label %exit1 +latch: + %latchcond = call i1 @unknown() + br i1 %latchcond, label %loop, label %exit2 + +exit1: + ret void +exit2: + ret void +} + + define void @test_live_inner() { ; CHECK-LABEL: @test_live_inner( ; CHECK-NEXT: entry: