[llvm] 7c63aac - Revert "[LoopDeletion] Break backedge of loops when known not taken"

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 4 09:52:00 PST 2021


Author: Philip Reames
Date: 2021-01-04T09:50:47-08:00
New Revision: 7c63aac7bd4e5ce3402f2ef7c1d5b66047230147

URL: https://github.com/llvm/llvm-project/commit/7c63aac7bd4e5ce3402f2ef7c1d5b66047230147
DIFF: https://github.com/llvm/llvm-project/commit/7c63aac7bd4e5ce3402f2ef7c1d5b66047230147.diff

LOG: Revert "[LoopDeletion] Break backedge of loops when known not taken"

This reverts commit dd6bb367d19e3bf18353e40de54d35480999a930.

Multi-stage builders are showing an assertion failure w/LCSSA not being preserved on entry to IndVars.  Reason isn't clear, reverting while investigating.

Added: 
    

Modified: 
    llvm/include/llvm/Transforms/Utils/LoopUtils.h
    llvm/lib/Transforms/Scalar/LoopDeletion.cpp
    llvm/lib/Transforms/Utils/LoopUtils.cpp
    llvm/test/Transforms/IndVarSimplify/X86/pr45360.ll
    llvm/test/Transforms/IndVarSimplify/exit_value_test2.ll
    llvm/test/Transforms/LoopDeletion/update-scev.ll

Removed: 
    llvm/test/Transforms/LoopDeletion/zero-btc.ll


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index 82c0d9e070d7..b29add4cba0e 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -179,12 +179,6 @@ bool hoistRegion(DomTreeNode *, AAResults *, LoopInfo *, DominatorTree *,
 void deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
                     LoopInfo *LI, MemorySSA *MSSA = nullptr);
 
-/// Remove the backedge of the specified loop.  Handles loop nests and general
-/// loop structures subject to the precondition that the loop has a single
-/// latch block.  Preserves all listed analyses.
-void breakLoopBackedge(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
-                       LoopInfo &LI, MemorySSA *MSSA);
-
 /// Try to promote memory values to scalars by sinking stores out of
 /// the loop and moving loads to before the loop.  We do this by looping over
 /// the stores in the loop, looking for stores to Must pointers which are

diff  --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 04120032f0f4..065db647561e 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -26,7 +26,6 @@
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/Scalar/LoopPassManager.h"
 #include "llvm/Transforms/Utils/LoopUtils.h"
-
 using namespace llvm;
 
 #define DEBUG_TYPE "loop-delete"
@@ -39,14 +38,6 @@ enum class LoopDeletionResult {
   Deleted,
 };
 
-static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B) {
-  if (A == LoopDeletionResult::Deleted || B == LoopDeletionResult::Deleted)
-    return LoopDeletionResult::Deleted;
-  if (A == LoopDeletionResult::Modified || B == LoopDeletionResult::Modified)
-    return LoopDeletionResult::Modified;
-  return LoopDeletionResult::Unmodified;
-}
-
 /// Determines if a loop is dead.
 ///
 /// This assumes that we've already checked for unique exit and exiting blocks,
@@ -135,26 +126,6 @@ static bool isLoopNeverExecuted(Loop *L) {
   return true;
 }
 
-/// 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.
-static LoopDeletionResult
-breakBackedgeIfNotTaken(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
-                        LoopInfo &LI, MemorySSA *MSSA,
-                        OptimizationRemarkEmitter &ORE) {
-  assert(L->isLCSSAForm(DT) && "Expected LCSSA!");
-
-  if (!L->getLoopLatch())
-    return LoopDeletionResult::Unmodified;
-
-  auto *BTC = SE.getBackedgeTakenCount(L);
-  if (!BTC->isZero())
-    return LoopDeletionResult::Unmodified;
-
-  breakLoopBackedge(L, DT, SE, LI, MSSA);
-  return LoopDeletionResult::Deleted;
-}
-
 /// Remove a loop if it is dead.
 ///
 /// A loop is considered dead if it does not impact the observable behavior of
@@ -191,6 +162,7 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT,
     return LoopDeletionResult::Unmodified;
   }
 
+
   BasicBlock *ExitBlock = L->getUniqueExitBlock();
 
   if (ExitBlock && isLoopNeverExecuted(L)) {
@@ -268,14 +240,6 @@ PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM,
   // but ORE cannot be preserved (see comment before the pass definition).
   OptimizationRemarkEmitter ORE(L.getHeader()->getParent());
   auto Result = deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI, AR.MSSA, ORE);
-
-  // If we can prove the backedge isn't taken, just break it and be done.  This
-  // leaves the loop structure in place which means it can handle dispatching
-  // to the right exit based on whatever loop invariant structure remains.
-  if (Result != LoopDeletionResult::Deleted)
-    Result = merge(Result, breakBackedgeIfNotTaken(&L, AR.DT, AR.SE, AR.LI,
-                                                   AR.MSSA, ORE));
-
   if (Result == LoopDeletionResult::Unmodified)
     return PreservedAnalyses::all();
 
@@ -335,12 +299,6 @@ bool LoopDeletionLegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) {
 
   LoopDeletionResult Result = deleteLoopIfDead(L, DT, SE, LI, MSSA, ORE);
 
-  // If we can prove the backedge isn't taken, just break it and be done.  This
-  // leaves the loop structure in place which means it can handle dispatching
-  // to the right exit based on whatever loop invariant structure remains.
-  if (Result != LoopDeletionResult::Deleted)
-    Result = merge(Result, breakBackedgeIfNotTaken(L, DT, SE, LI, MSSA, ORE));
-
   if (Result == LoopDeletionResult::Deleted)
     LPM.markLoopAsDeleted(*L);
 

diff  --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 4f9899547c26..96f1d4219bac 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -756,37 +756,6 @@ void llvm::deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE,
   }
 }
 
-void llvm::breakLoopBackedge(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
-                             LoopInfo &LI, MemorySSA *MSSA) {
-
-  auto *Latch = L->getLoopLatch();
-  assert(Latch);
-  auto *Header = L->getHeader();
-
-  SE.forgetLoop(L);
-
-  // Note: By splitting the backedge, and then explicitly making it unreachable
-  // we gracefully handle corner cases such as non-bottom tested loops and the
-  // like.  We also have the benefit of being able to reuse existing well tested
-  // code.  It might be worth special casing the common bottom tested case at
-  // some point to avoid code churn.
-
-  std::unique_ptr<MemorySSAUpdater> MSSAU;
-  if (MSSA)
-    MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
-
-  auto *BackedgeBB = SplitEdge(Latch, Header, &DT, &LI, MSSAU.get());
-
-  DomTreeUpdater DTU(&DT, DomTreeUpdater::UpdateStrategy::Eager);
-  (void)changeToUnreachable(BackedgeBB->getTerminator(), /*UseTrap*/false,
-                            /*PreserveLCSSA*/true, &DTU, MSSAU.get());
-
-  // Erase (and destroy) this loop instance.  Handles relinking sub-loops
-  // and blocks within the loop as needed.
-  LI.erase(L);
-}
-
-
 /// Checks if \p L has single exit through latch block except possibly
 /// "deoptimizing" exits. Returns branch instruction terminating the loop
 /// latch if above check is successful, nullptr otherwise.

diff  --git a/llvm/test/Transforms/IndVarSimplify/X86/pr45360.ll b/llvm/test/Transforms/IndVarSimplify/X86/pr45360.ll
index 397c23cfd3ea..d0857fa707b1 100644
--- a/llvm/test/Transforms/IndVarSimplify/X86/pr45360.ll
+++ b/llvm/test/Transforms/IndVarSimplify/X86/pr45360.ll
@@ -23,8 +23,8 @@ define dso_local i32 @main() {
 ; CHECK-NEXT:    [[I6:%.*]] = load i32, i32* @a, align 4
 ; CHECK-NEXT:    [[I24:%.*]] = load i32, i32* @b, align 4
 ; CHECK-NEXT:    [[D_PROMOTED9:%.*]] = load i32, i32* @d, align 4
-; CHECK-NEXT:    br label [[BB13_PREHEADER:%.*]]
-; CHECK:       bb13.preheader:
+; CHECK-NEXT:    br label [[BB1:%.*]]
+; CHECK:       bb1:
 ; CHECK-NEXT:    [[I8_LCSSA10:%.*]] = phi i32 [ [[D_PROMOTED9]], [[BB:%.*]] ], [ [[I8:%.*]], [[BB19_PREHEADER:%.*]] ]
 ; CHECK-NEXT:    [[I8]] = and i32 [[I8_LCSSA10]], [[I6]]
 ; CHECK-NEXT:    [[I21:%.*]] = icmp eq i32 [[I8]], 0
@@ -33,7 +33,7 @@ define dso_local i32 @main() {
 ; CHECK-NEXT:    [[I26:%.*]] = urem i32 [[I24]], [[I8]]
 ; CHECK-NEXT:    store i32 [[I26]], i32* @e, align 4
 ; CHECK-NEXT:    [[I30_NOT:%.*]] = icmp eq i32 [[I26]], 0
-; CHECK-NEXT:    br i1 [[I30_NOT]], label [[BB32_LOOPEXIT:%.*]], label [[BB13_PREHEADER]]
+; CHECK-NEXT:    br i1 [[I30_NOT]], label [[BB32_LOOPEXIT:%.*]], label [[BB1]]
 ; CHECK:       bb13.preheader.bb27.thread.split_crit_edge:
 ; CHECK-NEXT:    store i32 -1, i32* @f, align 4
 ; CHECK-NEXT:    store i32 0, i32* @d, align 4

diff  --git a/llvm/test/Transforms/IndVarSimplify/exit_value_test2.ll b/llvm/test/Transforms/IndVarSimplify/exit_value_test2.ll
index 674003910373..93cced597cac 100644
--- a/llvm/test/Transforms/IndVarSimplify/exit_value_test2.ll
+++ b/llvm/test/Transforms/IndVarSimplify/exit_value_test2.ll
@@ -89,10 +89,8 @@ define i32 @zero_backedge_count_test(i32 %unknown_init, i32* %unknown_mem) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[UNKNOWN_NEXT:%.*]] = load volatile i32, i32* [[UNKNOWN_MEM:%.*]], align 4
-; CHECK-NEXT:    br i1 false, label [[LOOP_LOOP_CRIT_EDGE:%.*]], label [[LEAVE:%.*]]
-; CHECK:       loop.loop_crit_edge:
-; CHECK-NEXT:    unreachable
+; CHECK-NEXT:    [[UNKNOWN_NEXT:%.*]] = load volatile i32, i32* [[UNKNOWN_MEM:%.*]]
+; CHECK-NEXT:    br i1 false, label [[LOOP]], label [[LEAVE:%.*]]
 ; CHECK:       leave:
 ; CHECK-NEXT:    ret i32 [[UNKNOWN_INIT:%.*]]
 ;

diff  --git a/llvm/test/Transforms/LoopDeletion/update-scev.ll b/llvm/test/Transforms/LoopDeletion/update-scev.ll
index f156af538049..44d23aa4060d 100644
--- a/llvm/test/Transforms/LoopDeletion/update-scev.ll
+++ b/llvm/test/Transforms/LoopDeletion/update-scev.ll
@@ -44,8 +44,7 @@ for.body6:                                        ; preds = %for.body6, %for.bod
   %conv10 = zext i1 %cmp9 to i32
   %and = and i32 %conv10, %g.138
   %inc = add i32 %h.039, 1
-  %exit = icmp eq i32 %inc, 20000
-  br i1 %exit, label %for.inc11, label %for.body6
+  br i1 undef, label %for.inc11, label %for.body6
 
 for.inc11:                                        ; preds = %for.body6
   %and.lcssa = phi i32 [ %and, %for.body6 ]

diff  --git a/llvm/test/Transforms/LoopDeletion/zero-btc.ll b/llvm/test/Transforms/LoopDeletion/zero-btc.ll
deleted file mode 100644
index ab0423f3e036..000000000000
--- a/llvm/test/Transforms/LoopDeletion/zero-btc.ll
+++ /dev/null
@@ -1,335 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -loop-deletion -S | FileCheck %s
-
- at G = external global i32
-
-define void @test_trivial() {
-; CHECK-LABEL: @test_trivial(
-; 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 [[LOOP_LOOP_CRIT_EDGE:%.*]], label [[EXIT:%.*]]
-; CHECK:       loop.loop_crit_edge:
-; CHECK-NEXT:    unreachable
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  store i32 0, i32* @G
-  br i1 false, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-
-define void @test_bottom_tested() {
-; CHECK-LABEL: @test_bottom_tested(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; 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 [[LOOP_LOOP_CRIT_EDGE:%.*]], label [[EXIT:%.*]]
-; CHECK:       loop.loop_crit_edge:
-; CHECK-NEXT:    unreachable
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  %iv = phi i32 [ 0, %entry], [ %iv.inc, %loop ]
-  store i32 0, i32* @G
-  %iv.inc = add i32 %iv, 1
-  %be_taken = icmp ne i32 %iv.inc, 1
-  br i1 %be_taken, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-define void @test_early_exit() {
-; CHECK-LABEL: @test_early_exit(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; 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:%.*]], label [[EXIT:%.*]]
-; CHECK:       latch:
-; CHECK-NEXT:    br label [[LATCH_SPLIT:%.*]]
-; CHECK:       latch.split:
-; CHECK-NEXT:    unreachable
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  %iv = phi i32 [ 0, %entry], [ %iv.inc, %latch ]
-  store i32 0, i32* @G
-  %iv.inc = add i32 %iv, 1
-  %be_taken = icmp ne i32 %iv.inc, 1
-  br i1 %be_taken, label %latch, label %exit
-latch:
-  br label %loop
-
-exit:
-  ret void
-}
-
-define void @test_multi_exit1() {
-; CHECK-LABEL: @test_multi_exit1(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; 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:%.*]], label [[EXIT:%.*]]
-; CHECK:       latch:
-; CHECK-NEXT:    store i32 1, i32* @G, align 4
-; CHECK-NEXT:    [[COND2:%.*]] = icmp ult i32 [[IV_INC]], 30
-; CHECK-NEXT:    br i1 [[COND2]], label [[LATCH_LOOP_CRIT_EDGE:%.*]], label [[EXIT]]
-; CHECK:       latch.loop_crit_edge:
-; CHECK-NEXT:    unreachable
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  %iv = phi i32 [ 0, %entry], [ %iv.inc, %latch ]
-  store i32 0, i32* @G
-  %iv.inc = add i32 %iv, 1
-  %be_taken = icmp ne i32 %iv.inc, 1
-  br i1 %be_taken, label %latch, label %exit
-latch:
-  store i32 1, i32* @G
-  %cond2 = icmp ult i32 %iv.inc, 30
-  br i1 %cond2, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-define void @test_multi_exit2() {
-; CHECK-LABEL: @test_multi_exit2(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; CHECK-NEXT:    br i1 true, label [[LATCH:%.*]], label [[EXIT:%.*]]
-; CHECK:       latch:
-; CHECK-NEXT:    store i32 1, i32* @G, align 4
-; CHECK-NEXT:    br i1 false, label [[LATCH_LOOP_CRIT_EDGE:%.*]], label [[EXIT]]
-; CHECK:       latch.loop_crit_edge:
-; CHECK-NEXT:    unreachable
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  store i32 0, i32* @G
-  br i1 true, label %latch, label %exit
-latch:
-  store i32 1, i32* @G
-  br i1 false, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-; TODO: SCEV seems not to recognize this as a zero btc loop
-define void @test_multi_exit3(i1 %cond1) {
-; CHECK-LABEL: @test_multi_exit3(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; 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:       latch:
-; CHECK-NEXT:    store i32 1, i32* @G, align 4
-; 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 [[LOOP]], label [[EXIT]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  %iv = phi i32 [ 0, %entry], [ %iv.inc, %latch ]
-  store i32 0, i32* @G
-  br i1 %cond1, label %latch, label %exit
-latch:
-  store i32 1, i32* @G
-  %iv.inc = add i32 %iv, 1
-  %be_taken = icmp ne i32 %iv.inc, 1
-  br i1 %be_taken, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-; Subtle - This is either zero btc, or infinite, thus, can't break
-; backedge
-define void @test_multi_exit4(i1 %cond1, i1 %cond2) {
-; CHECK-LABEL: @test_multi_exit4(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LATCH:%.*]], label [[EXIT:%.*]]
-; CHECK:       latch:
-; CHECK-NEXT:    store i32 1, i32* @G, align 4
-; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP]], label [[EXIT]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  store i32 0, i32* @G
-  br i1 %cond1, label %latch, label %exit
-latch:
-  store i32 1, i32* @G
-  br i1 %cond2, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-; A simple case with multiple exit blocks
-define void @test_multi_exit5() {
-; CHECK-LABEL: @test_multi_exit5(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; CHECK-NEXT:    br i1 true, label [[LATCH:%.*]], label [[EXIT1:%.*]]
-; CHECK:       latch:
-; CHECK-NEXT:    store i32 1, i32* @G, align 4
-; CHECK-NEXT:    br i1 false, label [[LATCH_LOOP_CRIT_EDGE:%.*]], label [[EXIT2:%.*]]
-; CHECK:       latch.loop_crit_edge:
-; CHECK-NEXT:    unreachable
-; CHECK:       exit1:
-; CHECK-NEXT:    ret void
-; CHECK:       exit2:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  store i32 0, i32* @G
-  br i1 true, label %latch, label %exit1
-latch:
-  store i32 1, i32* @G
-  br i1 false, label %loop, label %exit2
-
-exit1:
-  ret void
-exit2:
-  ret void
-}
-
-define void @test_live_inner() {
-; CHECK-LABEL: @test_live_inner(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; CHECK-NEXT:    br label [[INNER:%.*]]
-; CHECK:       inner:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[LOOP]] ], [ [[IV_INC:%.*]], [[INNER]] ]
-; CHECK-NEXT:    store i32 [[IV]], i32* @G, align 4
-; CHECK-NEXT:    [[IV_INC]] = add i32 [[IV]], 1
-; CHECK-NEXT:    [[CND:%.*]] = icmp ult i32 [[IV_INC]], 200
-; CHECK-NEXT:    br i1 [[CND]], label [[INNER]], label [[LATCH:%.*]]
-; CHECK:       latch:
-; CHECK-NEXT:    br i1 false, label [[LATCH_LOOP_CRIT_EDGE:%.*]], label [[EXIT:%.*]]
-; CHECK:       latch.loop_crit_edge:
-; CHECK-NEXT:    unreachable
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  store i32 0, i32* @G
-  br label %inner
-
-inner:
-  %iv = phi i32 [0, %loop], [%iv.inc, %inner]
-  store i32 %iv, i32* @G
-  %iv.inc = add i32 %iv, 1
-  %cnd = icmp ult i32 %iv.inc, 200
-  br i1 %cnd, label %inner, label %latch
-
-latch:
-  br i1 false, label %loop, label %exit
-
-exit:
-  ret void
-}
-
-define void @test_live_outer() {
-; CHECK-LABEL: @test_live_outer(
-; CHECK-NEXT:  entry:
-; CHECK-NEXT:    br label [[LOOP:%.*]]
-; CHECK:       loop:
-; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_INC:%.*]], [[LATCH:%.*]] ]
-; CHECK-NEXT:    br label [[INNER:%.*]]
-; CHECK:       inner:
-; CHECK-NEXT:    store i32 0, i32* @G, align 4
-; CHECK-NEXT:    br i1 false, label [[INNER_INNER_CRIT_EDGE:%.*]], label [[LATCH]]
-; CHECK:       inner.inner_crit_edge:
-; CHECK-NEXT:    unreachable
-; CHECK:       latch:
-; CHECK-NEXT:    store i32 [[IV]], i32* @G, align 4
-; CHECK-NEXT:    [[IV_INC]] = add i32 [[IV]], 1
-; CHECK-NEXT:    [[CND:%.*]] = icmp ult i32 [[IV_INC]], 200
-; CHECK-NEXT:    br i1 [[CND]], label [[LOOP]], label [[EXIT:%.*]]
-; CHECK:       exit:
-; CHECK-NEXT:    ret void
-;
-entry:
-  br label %loop
-
-loop:
-  %iv = phi i32 [0, %entry], [%iv.inc, %latch]
-  br label %inner
-
-inner:
-  store i32 0, i32* @G
-  br i1 false, label %inner, label %latch
-
-latch:
-  store i32 %iv, i32* @G
-  %iv.inc = add i32 %iv, 1
-  %cnd = icmp ult i32 %iv.inc, 200
-  br i1 %cnd, label %loop, label %exit
-
-exit:
-  ret void
-}


        


More information about the llvm-commits mailing list