[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