blob: 3cce7bc9c8d0865de218f51de59751c125153839 [file] [log] [blame]
commit 0159652058ca555b05db6a209fe9cf660c3bf8e6
Author: Stefan Pintilie <stefanp@ca.ibm.com>
Date: Fri May 28 11:35:25 2021 -0500
Revert "Return "[LoopDeletion] Break backedge if we can prove that the loop is exited on 1st iteration" (try 2)"
This reverts commit be1a23203b1de655b8c7dac7549818d975a0cbbf.
diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 41be776ec141..fd0e983b6199 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -17,7 +17,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/GlobalsModRef.h"
-#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
@@ -136,168 +135,6 @@ static bool isLoopNeverExecuted(Loop *L) {
return true;
}
-static const SCEV *
-getSCEVOnFirstIteration(Value *V, Loop *L, ScalarEvolution &SE,
- DenseMap<Value *, const SCEV *> &FirstIterSCEV) {
- // Fist, check in cache.
- auto Existing = FirstIterSCEV.find(V);
- if (Existing != FirstIterSCEV.end())
- return Existing->second;
- const SCEV *S = nullptr;
- // TODO: Once ScalarEvolution supports getValueOnNthIteration for anything
- // else but AddRecs, it's a good use case for it. So far, just consider some
- // simple cases, like arithmetic operations.
- Value *LHS, *RHS;
- using namespace PatternMatch;
- if (match(V, m_Add(m_Value(LHS), m_Value(RHS)))) {
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
- S = SE.getAddExpr(LHSS, RHSS);
- } else if (match(V, m_Sub(m_Value(LHS), m_Value(RHS)))) {
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
- S = SE.getMinusSCEV(LHSS, RHSS);
- } else if (match(V, m_Mul(m_Value(LHS), m_Value(RHS)))) {
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
- S = SE.getMulExpr(LHSS, RHSS);
- } else
- S = SE.getSCEV(V);
- assert(S && "Case not handled?");
- FirstIterSCEV[V] = S;
- return S;
-}
-
-// Try to prove that one of conditions that dominates the latch must exit on 1st
-// iteration.
-static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT,
- ScalarEvolution &SE, LoopInfo &LI) {
- BasicBlock *Latch = L->getLoopLatch();
-
- if (!Latch)
- return false;
-
- LoopBlocksRPO RPOT(L);
- RPOT.perform(&LI);
-
- BasicBlock *Header = L->getHeader();
- // Blocks that are reachable on the 1st iteration.
- SmallPtrSet<BasicBlock *, 4> LiveBlocks;
- // Edges that are reachable on the 1st iteration.
- DenseSet<BasicBlockEdge> LiveEdges;
- LiveBlocks.insert(L->getHeader());
-
- auto MarkLiveEdge = [&](BasicBlock *From, BasicBlock *To) {
- assert(LiveBlocks.count(From) && "Must be live!");
- LiveBlocks.insert(To);
- LiveEdges.insert({ From, To });
- };
-
- auto MarkAllSuccessorsLive = [&](BasicBlock *BB) {
- for (auto *Succ : successors(BB))
- MarkLiveEdge(BB, Succ);
- };
-
- // Check if there is only one predecessor on 1st iteration. Note that because
- // we iterate in RPOT, we have already visited all its (non-latch)
- // predecessors.
- auto GetSolePredecessorOnFirstIteration = [&](BasicBlock * BB)->BasicBlock * {
- if (BB == Header)
- return L->getLoopPredecessor();
- BasicBlock *OnlyPred = nullptr;
- for (auto *Pred : predecessors(BB))
- if (OnlyPred != Pred && LiveEdges.count({ Pred, BB })) {
- // 2 live preds.
- if (OnlyPred)
- return nullptr;
- OnlyPred = Pred;
- }
-
- assert(OnlyPred && "No live predecessors?");
- return OnlyPred;
- };
- DenseMap<Value *, const SCEV *> FirstIterSCEV;
- SmallPtrSet<BasicBlock *, 4> Visited;
-
- // Use the following algorithm to prove we never take the latch on the 1st
- // iteration:
- // 1. Traverse in topological order, so that whenever we visit a block, all
- // its predecessors are already visited.
- // 2. If we can prove that the block may have only 1 predecessor on the 1st
- // iteration, map all its phis onto input from this predecessor.
- // 3a. If we can prove which successor of out block is taken on the 1st
- // iteration, mark this successor live.
- // 3b. If we cannot prove it, conservatively assume that all successors are
- // live.
- for (auto *BB : RPOT) {
- Visited.insert(BB);
-
- // This block is not reachable on the 1st iterations.
- if (!LiveBlocks.count(BB))
- continue;
-
- // Skip inner loops.
- if (LI.getLoopFor(BB) != L) {
- MarkAllSuccessorsLive(BB);
- continue;
- }
-
- // If RPOT exists, we should never visit a block before all of its
- // predecessors are visited. The only situation when this can be broken is
- // irreducible CFG. Do not deal with such cases.
- if (BB != Header)
- for (auto *Pred : predecessors(BB))
- if (!Visited.count(Pred))
- return false;
-
- // If this block has only one live pred, map its phis onto their SCEVs.
- if (auto *OnlyPred = GetSolePredecessorOnFirstIteration(BB))
- for (auto &PN : BB->phis()) {
- if (!SE.isSCEVable(PN.getType()))
- continue;
- auto *Incoming = PN.getIncomingValueForBlock(OnlyPred);
- if (DT.dominates(Incoming, BB->getTerminator())) {
- const SCEV *IncSCEV =
- getSCEVOnFirstIteration(Incoming, L, SE, FirstIterSCEV);
- FirstIterSCEV[&PN] = IncSCEV;
- }
- }
-
- using namespace PatternMatch;
- ICmpInst::Predicate Pred;
- Value *LHS, *RHS;
- const BasicBlock *IfTrue, *IfFalse;
- // TODO: Handle switches.
- if (!match(BB->getTerminator(),
- m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)),
- m_BasicBlock(IfTrue), m_BasicBlock(IfFalse)))) {
- MarkAllSuccessorsLive(BB);
- continue;
- }
-
- if (!SE.isSCEVable(LHS->getType())) {
- MarkAllSuccessorsLive(BB);
- continue;
- }
-
- // Can we prove constant true or false for this condition?
- const SCEV *LHSS = getSCEVOnFirstIteration(LHS, L, SE, FirstIterSCEV);
- const SCEV *RHSS = getSCEVOnFirstIteration(RHS, L, SE, FirstIterSCEV);
- // TODO: isKnownPredicateAt is more powerful, but it's too compile time
- // consuming. So we avoid using it here.
- if (SE.isKnownPredicate(Pred, LHSS, RHSS))
- MarkLiveEdge(BB, BB->getTerminator()->getSuccessor(0));
- else if (SE.isKnownPredicate(ICmpInst::getInversePredicate(Pred), LHSS,
- RHSS))
- MarkLiveEdge(BB, BB->getTerminator()->getSuccessor(1));
- else
- MarkAllSuccessorsLive(BB);
- }
-
- // We can break the latch if it wasn't live.
- return !LiveEdges.count({ Latch, Header });
-}
-
/// If we can prove the backedge is untaken, remove it. This destroys the
/// loop, but leaves the (now trivially loop invariant) control flow and
/// side effects (if any) in place.
@@ -311,7 +148,7 @@ breakBackedgeIfNotTaken(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
return LoopDeletionResult::Unmodified;
auto *BTC = SE.getBackedgeTakenCount(L);
- if (!BTC->isZero() && !canProveExitOnFirstIteration(L, DT, SE, LI))
+ if (!BTC->isZero())
return LoopDeletionResult::Unmodified;
breakLoopBackedge(L, DT, SE, LI, MSSA);
diff --git a/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll b/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll
index bed479e408eb..98dafebe0df0 100644
--- a/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll
+++ b/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll
@@ -344,19 +344,17 @@ define i32 @test_ne_const() {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0
-; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE]] ], [ [[SUB]], [[LOOP]] ]
-; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]]
+; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]]
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[SUM_NEXT]], 4
-; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]]
-; CHECK: backedge.loop_crit_edge:
-; CHECK-NEXT: unreachable
+; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
@@ -396,19 +394,17 @@ define i32 @test_slt_const() {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0
-; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE]] ], [ [[SUB]], [[LOOP]] ]
-; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]]
+; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]]
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[SUM_NEXT]], 4
-; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]]
-; CHECK: backedge.loop_crit_edge:
-; CHECK-NEXT: unreachable
+; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
@@ -448,19 +444,17 @@ define i32 @test_ult_const() {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0
-; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE]] ], [ [[SUB]], [[LOOP]] ]
-; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]]
+; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]]
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[SUM_NEXT]], 4
-; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]]
-; CHECK: backedge.loop_crit_edge:
-; CHECK-NEXT: unreachable
+; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
@@ -500,19 +494,17 @@ define i32 @test_sgt_const() {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0
-; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE]] ], [ [[SUB]], [[LOOP]] ]
-; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]]
+; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]]
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sgt i32 [[SUM_NEXT]], 4
-; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]]
-; CHECK: backedge.loop_crit_edge:
-; CHECK-NEXT: unreachable
+; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
@@ -552,19 +544,17 @@ define i32 @test_ugt_const() {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0
-; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[BACKEDGE]], label [[IF_FALSE:%.*]]
; CHECK: if.false:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE]] ], [ [[SUB]], [[LOOP]] ]
-; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]]
+; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]]
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ugt i32 [[SUM_NEXT]], 4
-; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]]
-; CHECK: backedge.loop_crit_edge:
-; CHECK-NEXT: unreachable
+; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
@@ -604,24 +594,22 @@ define i32 @test_multiple_pred_const() {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ]
; CHECK-NEXT: [[SUB:%.*]] = sub i32 4, [[SUM]]
; CHECK-NEXT: [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0
; CHECK-NEXT: br i1 [[IS_POSITIVE]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
; CHECK: if.true:
; CHECK-NEXT: switch i32 4, label [[FAILURE:%.*]] [
-; CHECK-NEXT: i32 100, label [[BACKEDGE:%.*]]
+; CHECK-NEXT: i32 100, label [[BACKEDGE]]
; CHECK-NEXT: i32 200, label [[BACKEDGE]]
; CHECK-NEXT: ]
; CHECK: if.false:
; CHECK-NEXT: br label [[BACKEDGE]]
; CHECK: backedge:
; CHECK-NEXT: [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE]] ], [ [[SUB]], [[IF_TRUE]] ], [ [[SUB]], [[IF_TRUE]] ]
-; CHECK-NEXT: [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]]
+; CHECK-NEXT: [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]]
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ne i32 [[SUM_NEXT]], 4
-; CHECK-NEXT: br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]]
-; CHECK: backedge.loop_crit_edge:
-; CHECK-NEXT: unreachable
+; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
; CHECK: done:
; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[SUM_NEXT_LCSSA]]
diff --git a/llvm/test/Transforms/LoopDeletion/zero-btc.ll b/llvm/test/Transforms/LoopDeletion/zero-btc.ll
index 958de0505af7..413b0a877dd4 100644
--- a/llvm/test/Transforms/LoopDeletion/zero-btc.ll
+++ b/llvm/test/Transforms/LoopDeletion/zero-btc.ll
@@ -161,16 +161,14 @@ define void @test_multi_exit3(i1 %cond1) {
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[LATCH:%.*]] ]
; CHECK-NEXT: store i32 0, i32* @G, align 4
-; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LATCH:%.*]], label [[EXIT:%.*]]
+; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LATCH]], label [[EXIT:%.*]]
; CHECK: latch:
; CHECK-NEXT: store i32 1, i32* @G, align 4
-; CHECK-NEXT: [[IV_INC:%.*]] = add i32 [[IV]], 1
+; CHECK-NEXT: [[IV_INC]] = add i32 [[IV]], 1
; CHECK-NEXT: [[BE_TAKEN:%.*]] = icmp ne i32 [[IV_INC]], 1
-; CHECK-NEXT: br i1 [[BE_TAKEN]], label [[LATCH_LOOP_CRIT_EDGE:%.*]], label [[EXIT]]
-; CHECK: latch.loop_crit_edge:
-; CHECK-NEXT: unreachable
+; CHECK-NEXT: br i1 [[BE_TAKEN]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
;