forked from OSchip/llvm-project
[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 llvm-svn: 350049
This commit is contained in:
parent
e20bf9ab91
commit
edabb9ae56
|
@ -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()) {
|
||||
|
|
|
@ -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: 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:%.*]] = 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: br label [[DUMMY:%.*]]
|
||||
; CHECK: dummy:
|
||||
; CHECK-NEXT: br label [[EXIT:%.*]]
|
||||
; 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: 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:%.*]] ], [ [[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_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:%.*]] = 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: br label [[DUMMY:%.*]]
|
||||
; CHECK: dummy:
|
||||
; CHECK-NEXT: br label [[EXIT:%.*]]
|
||||
; 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_loop_inverse_2(i32 %end) {
|
|||
; 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_loop_inverse_2(i32 %end) {
|
|||
; 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_loop_inverse_3(i32 %end) {
|
|||
; 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_loop_inverse_3(i32 %end) {
|
|||
; 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_grandparent(i1 %cond1, i1 %cond2, i32 %N)
|
|||
; 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_grandparent(i1 %cond1, i1 %cond2, i32 %N)
|
|||
; 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:%.*]]
|
||||
|
|
Loading…
Reference in New Issue