[llvm] r350049 - [LoopSimplifyCFG] Delete dead exiting edges
Max Kazantsev via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 23 23:41:33 PST 2018
Author: mkazantsev
Date: Sun Dec 23 23:41:33 2018
New Revision: 350049
URL: http://llvm.org/viewvc/llvm-project?rev=350049&view=rev
Log:
[LoopSimplifyCFG] Delete dead exiting edges
This patch teaches LoopSimplifyCFG to remove dead exiting edges
from loops.
Differential Revision: https://reviews.llvm.org/D54025
Reviewed By: fedor.sergeev
Modified:
llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
llvm/trunk/test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll
Modified: llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp?rev=350049&r1=350048&r2=350049&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp Sun Dec 23 23:41:33 2018
@@ -48,6 +48,8 @@ STATISTIC(NumTerminatorsFolded,
"Number of terminators folded to unconditional branches");
STATISTIC(NumLoopBlocksDeleted,
"Number of loop blocks deleted");
+STATISTIC(NumLoopExitsDeleted,
+ "Number of loop exiting edges deleted");
/// If \p BB is a switch or a conditional branch, but only one of its successors
/// can be reached from this block in runtime, return this successor. Otherwise,
@@ -271,6 +273,114 @@ private:
"All blocks that stay in loop should be live!");
}
+ /// We need to preserve static reachibility of all loop exit blocks (this is)
+ /// required by loop pass manager. In order to do it, we make the following
+ /// trick:
+ ///
+ /// preheader:
+ /// <preheader code>
+ /// br label %loop_header
+ ///
+ /// loop_header:
+ /// ...
+ /// br i1 false, label %dead_exit, label %loop_block
+ /// ...
+ ///
+ /// We cannot simply remove edge from the loop to dead exit because in this
+ /// case dead_exit (and its successors) may become unreachable. To avoid that,
+ /// we insert the following fictive preheader:
+ ///
+ /// preheader:
+ /// <preheader code>
+ /// switch i32 0, label %preheader-split,
+ /// [i32 1, label %dead_exit_1],
+ /// [i32 2, label %dead_exit_2],
+ /// ...
+ /// [i32 N, label %dead_exit_N],
+ ///
+ /// preheader-split:
+ /// br label %loop_header
+ ///
+ /// loop_header:
+ /// ...
+ /// br i1 false, label %dead_exit_N, label %loop_block
+ /// ...
+ ///
+ /// Doing so, we preserve static reachibility of all dead exits and can later
+ /// remove edges from the loop to these blocks.
+ void handleDeadExits() {
+ // If no dead exits, nothing to do.
+ if (DeadExitBlocks.empty())
+ return;
+
+ // Construct split preheader and the dummy switch to thread edges from it to
+ // dead exits.
+ DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
+ BasicBlock *Preheader = L.getLoopPreheader();
+ BasicBlock *NewPreheader = Preheader->splitBasicBlock(
+ Preheader->getTerminator(),
+ Twine(Preheader->getName()).concat("-split"));
+ DTU.deleteEdge(Preheader, L.getHeader());
+ DTU.insertEdge(NewPreheader, L.getHeader());
+ DTU.insertEdge(Preheader, NewPreheader);
+ IRBuilder<> Builder(Preheader->getTerminator());
+ SwitchInst *DummySwitch =
+ Builder.CreateSwitch(Builder.getInt32(0), NewPreheader);
+ Preheader->getTerminator()->eraseFromParent();
+
+ unsigned DummyIdx = 1;
+ for (BasicBlock *BB : DeadExitBlocks) {
+ SmallVector<Instruction *, 4> DeadPhis;
+ for (auto &PN : BB->phis())
+ DeadPhis.push_back(&PN);
+
+ // Eliminate all Phis from dead exits.
+ for (Instruction *PN : DeadPhis) {
+ PN->replaceAllUsesWith(UndefValue::get(PN->getType()));
+ PN->eraseFromParent();
+ }
+ assert(DummyIdx != 0 && "Too many dead exits!");
+ DummySwitch->addCase(Builder.getInt32(DummyIdx++), BB);
+ DTU.insertEdge(Preheader, BB);
+ ++NumLoopExitsDeleted;
+ }
+
+ assert(L.getLoopPreheader() == NewPreheader && "Malformed CFG?");
+ if (Loop *OuterLoop = LI.getLoopFor(Preheader)) {
+ OuterLoop->addBasicBlockToLoop(NewPreheader, LI);
+
+ // When we break dead edges, the outer loop may become unreachable from
+ // the current loop. We need to fix loop info accordingly. For this, we
+ // find the most nested loop that still contains L and remove L from all
+ // loops that are inside of it.
+ Loop *StillReachable = nullptr;
+ for (BasicBlock *BB : LiveExitBlocks) {
+ Loop *BBL = LI.getLoopFor(BB);
+ if (BBL && BBL->contains(L.getHeader()))
+ if (!StillReachable ||
+ BBL->getLoopDepth() > StillReachable->getLoopDepth())
+ StillReachable = BBL;
+ }
+
+ // Okay, our loop is no longer in the outer loop (and maybe not in some of
+ // its parents as well). Make the fixup.
+ if (StillReachable != OuterLoop) {
+ LI.changeLoopFor(NewPreheader, StillReachable);
+ for (Loop *NotContaining = OuterLoop; NotContaining != StillReachable;
+ NotContaining = NotContaining->getParentLoop()) {
+ NotContaining->removeBlockFromLoop(NewPreheader);
+ for (auto *BB : L.blocks())
+ NotContaining->removeBlockFromLoop(BB);
+ }
+ OuterLoop->removeChildLoop(&L);
+ if (StillReachable)
+ StillReachable->addChildLoop(&L);
+ else
+ LI.addTopLevelLoop(&L);
+ }
+ }
+ }
+
/// Delete loop blocks that have become unreachable after folding. Make all
/// relevant updates to DT and LI.
void deleteDeadLoopBlocks() {
@@ -381,14 +491,6 @@ public:
return false;
}
- // TODO: Support dead loop exits.
- if (!DeadExitBlocks.empty()) {
- LLVM_DEBUG(dbgs() << "Give up constant terminator folding in loop "
- << L.getHeader()->getName()
- << ": we don't currently support dead loop exits.\n");
- return false;
- }
-
// TODO: Support blocks that are not dead, but also not in loop after the
// folding.
if (BlocksInLoopAfterFolding.size() + DeadLoopBlocks.size() !=
@@ -410,6 +512,7 @@ public:
<< "\n");
// Make the actual transforms.
+ handleDeadExits();
foldTerminators();
if (!DeadLoopBlocks.empty()) {
Modified: llvm/trunk/test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll?rev=350049&r1=350048&r2=350049&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll (original)
+++ llvm/trunk/test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll Sun Dec 23 23:41:33 2018
@@ -236,24 +236,25 @@ exit:
define i32 @dead_exit_test_branch_loop(i32 %end) {
; CHECK-LABEL: @dead_exit_test_branch_loop(
; CHECK-NEXT: preheader:
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[DEAD:%.*]]
+; CHECK-NEXT: ]
+; CHECK: preheader-split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
-; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[DEAD:%.*]]
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
+; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: dead:
-; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[HEADER]] ]
; CHECK-NEXT: br label [[DUMMY:%.*]]
; CHECK: dummy:
; CHECK-NEXT: br label [[EXIT:%.*]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
-; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I_LCSSA]], [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ undef, [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT: ret i32 [[I_1]]
;
preheader:
@@ -284,28 +285,27 @@ exit:
define i32 @dead_exit_test_switch_loop(i32 %end) {
; CHECK-LABEL: @dead_exit_test_switch_loop(
; CHECK-NEXT: preheader:
-; CHECK-NEXT: br label [[HEADER:%.*]]
-; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
-; CHECK-NEXT: switch i32 1, label [[DEAD:%.*]] [
-; CHECK-NEXT: i32 0, label [[DEAD]]
-; CHECK-NEXT: i32 1, label [[BACKEDGE]]
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[DEAD:%.*]]
; CHECK-NEXT: i32 2, label [[DEAD]]
+; CHECK-NEXT: i32 3, label [[DEAD]]
; CHECK-NEXT: ]
+; CHECK: preheader-split:
+; CHECK-NEXT: br label [[HEADER:%.*]]
+; CHECK: header:
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
+; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: dead:
-; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I]], [[HEADER]] ], [ [[I]], [[HEADER]] ]
; CHECK-NEXT: br label [[DUMMY:%.*]]
; CHECK: dummy:
; CHECK-NEXT: br label [[EXIT:%.*]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
-; CHECK-NEXT: br i1 [[CMP]], label [[HEADER]], label [[EXIT_LOOPEXIT:%.*]]
; CHECK: exit.loopexit:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
+; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[HEADER]] ]
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I_LCSSA]], [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
+; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ undef, [[DUMMY]] ], [ [[I_INC_LCSSA]], [[EXIT_LOOPEXIT]] ]
; CHECK-NEXT: ret i32 [[I_1]]
;
preheader:
@@ -553,21 +553,18 @@ exit:
define i32 @inf_loop_test_branch_loop(i32 %end) {
; CHECK-LABEL: @inf_loop_test_branch_loop(
; CHECK-NEXT: preheader:
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[EXIT:%.*]]
+; CHECK-NEXT: ]
+; CHECK: preheader-split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
-; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[DEAD:%.*]]
-; CHECK: dead:
-; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
-; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
-; CHECK-NEXT: br i1 true, label [[HEADER]], label [[EXIT:%.*]]
+; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
-; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
+; CHECK-NEXT: ret i32 undef
;
preheader:
br label %header
@@ -596,25 +593,18 @@ exit:
define i32 @inf_loop_test_switch_loop(i32 %end) {
; CHECK-LABEL: @inf_loop_test_switch_loop(
; CHECK-NEXT: preheader:
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[EXIT:%.*]]
+; CHECK-NEXT: ]
+; CHECK: preheader-split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
-; CHECK-NEXT: switch i32 1, label [[DEAD:%.*]] [
-; CHECK-NEXT: i32 0, label [[DEAD]]
-; CHECK-NEXT: i32 1, label [[BACKEDGE]]
-; CHECK-NEXT: i32 2, label [[DEAD]]
-; CHECK-NEXT: ]
-; CHECK: dead:
-; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
-; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]]
-; CHECK-NEXT: br i1 true, label [[HEADER]], label [[EXIT:%.*]]
+; CHECK-NEXT: br label [[HEADER]]
; CHECK: exit:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
-; CHECK-NEXT: ret i32 [[I_INC_LCSSA]]
+; CHECK-NEXT: ret i32 undef
;
preheader:
br label %header
@@ -1206,25 +1196,23 @@ define i32 @full_sub_loop_test_branch_lo
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
+; CHECK-NEXT: ]
+; CHECK: preheader-split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
-; CHECK-NEXT: br i1 false, label [[BACKEDGE]], label [[DEAD:%.*]]
-; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
-; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
-; CHECK-NEXT: br i1 true, label [[HEADER]], label [[OUTER_BACKEDGE]]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I_2]], 1
+; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
-; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
+; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
@@ -1269,29 +1257,23 @@ define i32 @full_sub_loop_test_switch_lo
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
+; CHECK-NEXT: ]
+; CHECK: preheader-split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
-; CHECK-NEXT: switch i32 1, label [[DEAD:%.*]] [
-; CHECK-NEXT: i32 0, label [[BACKEDGE]]
-; CHECK-NEXT: ]
-; CHECK: dead:
; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
-; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
-; CHECK-NEXT: switch i32 1, label [[HEADER]] [
-; CHECK-NEXT: i32 0, label [[OUTER_BACKEDGE]]
-; CHECK-NEXT: ]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I_2]], 1
+; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
-; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
+; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
@@ -1337,25 +1319,22 @@ define i32 @full_sub_loop_test_branch_lo
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
+; CHECK-NEXT: ]
+; CHECK: preheader-split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
-; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[DEAD:%.*]]
-; CHECK: dead:
-; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
-; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
-; CHECK-NEXT: br i1 true, label [[HEADER]], label [[OUTER_BACKEDGE]]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
+; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
-; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
+; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
@@ -1400,29 +1379,22 @@ define i32 @full_sub_loop_test_switch_lo
; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
; CHECK: outer_header:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ]
+; CHECK-NEXT: switch i32 0, label [[PREHEADER_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[OUTER_BACKEDGE]]
+; CHECK-NEXT: ]
+; CHECK: preheader-split:
; CHECK-NEXT: br label [[HEADER:%.*]]
; CHECK: header:
-; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER_SPLIT]] ], [ [[I_INC:%.*]], [[HEADER]] ]
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]]
-; CHECK-NEXT: switch i32 1, label [[BACKEDGE]] [
-; CHECK-NEXT: i32 0, label [[DEAD:%.*]]
-; CHECK-NEXT: ]
-; CHECK: dead:
-; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1
-; CHECK-NEXT: br label [[BACKEDGE]]
-; CHECK: backedge:
-; CHECK-NEXT: [[I_1:%.*]] = phi i32 [ [[I]], [[HEADER]] ], [ [[I_2]], [[DEAD]] ]
-; CHECK-NEXT: [[I_INC]] = add i32 [[I_1]], 1
-; CHECK-NEXT: switch i32 1, label [[HEADER]] [
-; CHECK-NEXT: i32 0, label [[OUTER_BACKEDGE]]
-; CHECK-NEXT: ]
+; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
+; CHECK-NEXT: br label [[HEADER]]
; CHECK: outer_backedge:
-; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ]
; CHECK-NEXT: [[J_INC]] = add i32 [[J]], 1
; CHECK-NEXT: [[CMP_J:%.*]] = icmp slt i32 [[J_INC]], [[END:%.*]]
; CHECK-NEXT: br i1 [[CMP_J]], label [[OUTER_HEADER]], label [[EXIT:%.*]]
; CHECK: exit:
-; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ [[I_INC_LCSSA]], [[OUTER_BACKEDGE]] ]
+; CHECK-NEXT: [[I_INC_LCSSA_LCSSA:%.*]] = phi i32 [ undef, [[OUTER_BACKEDGE]] ]
; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]]
;
entry:
@@ -1470,13 +1442,17 @@ define i32 @exit_branch_from_inner_to_gr
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
+; CHECK-NEXT: switch i32 0, label [[LOOP_2_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[LOOP_2_BACKEDGE]]
+; CHECK-NEXT: ]
+; CHECK: loop_2-split:
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
-; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2_SPLIT]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
-; CHECK-NEXT: br i1 true, label [[LOOP_3]], label [[LOOP_2_BACKEDGE]]
+; CHECK-NEXT: br label [[LOOP_3]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
@@ -1535,15 +1511,17 @@ define i32 @exit_switch_from_inner_to_gr
; CHECK-NEXT: br label [[LOOP_2:%.*]]
; CHECK: loop_2:
; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[J_NEXT:%.*]], [[LOOP_2_BACKEDGE:%.*]] ]
+; CHECK-NEXT: switch i32 0, label [[LOOP_2_SPLIT:%.*]] [
+; CHECK-NEXT: i32 1, label [[LOOP_2_BACKEDGE]]
+; CHECK-NEXT: ]
+; CHECK: loop_2-split:
; CHECK-NEXT: br label [[LOOP_3:%.*]]
; CHECK: loop_3:
-; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
+; CHECK-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_2_SPLIT]] ], [ [[K_NEXT:%.*]], [[LOOP_3_BACKEDGE:%.*]] ]
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[LOOP_3_BACKEDGE]], label [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]]
; CHECK: loop_3_backedge:
; CHECK-NEXT: [[K_NEXT]] = add i32 [[K]], 1
-; CHECK-NEXT: switch i32 1, label [[LOOP_3]] [
-; CHECK-NEXT: i32 0, label [[LOOP_2_BACKEDGE]]
-; CHECK-NEXT: ]
+; CHECK-NEXT: br label [[LOOP_3]]
; CHECK: loop_2_backedge:
; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1
; CHECK-NEXT: [[C_2:%.*]] = icmp slt i32 [[J_NEXT]], [[N:%.*]]
More information about the llvm-commits
mailing list