Index: lib/Transforms/Scalar/LoopSimplifyCFG.cpp =================================================================== --- lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -84,6 +84,7 @@ Loop &L; LoopInfo &LI; DominatorTree &DT; + ScalarEvolution &SE; LoopBlocksDFS DFS; // Whether or not the current loop will still exist after terminator constant @@ -434,7 +435,8 @@ // now have already been processed by this moment. for (auto *B : BlocksToProcess) for (auto *Succ : successors(B)) - if (!BlocksInLoopAfterFolding.count(Succ) && L.contains(Succ)) + if (!BlocksInLoopAfterFolding.count(Succ) && L.contains(Succ) && + Succ != L.getHeader()) assert(Visited.count(Succ) && "Bad order!"); #endif @@ -480,8 +482,12 @@ } public: - ConstantTerminatorFoldingImpl(Loop &L, LoopInfo &LI, DominatorTree &DT) - : L(L), LI(LI), DT(DT), DFS(&L) {} + ConstantTerminatorFoldingImpl(Loop &L, LoopInfo &LI, DominatorTree &DT, + ScalarEvolution &SE) + : L(L), LI(LI), DT(DT), SE(SE), DFS(&L) {} + + bool isLoopDeleted() const { return DeleteCurrentLoop; } + bool run() { assert(L.getLoopLatch() && "Should be single latch!"); @@ -500,43 +506,42 @@ return false; } - // TODO: Support deletion of the current loop. - if (DeleteCurrentLoop) { - LLVM_DEBUG( - dbgs() - << "Give up constant terminator folding in loop " - << L.getHeader()->getName() - << ": we don't currently support deletion of the current loop.\n"); - return false; - } - // Dump analysis results. + L.getHeader()->getParent()->dump(); LLVM_DEBUG(dump()); - + BasicBlock *Header = L.getHeader(); + (void)Header; LLVM_DEBUG(dbgs() << "Constant-folding " << FoldCandidates.size() - << " terminators in loop " << L.getHeader()->getName() + << " terminators in loop " << Header->getName() << "\n"); // Make the actual transforms. + if (DeleteCurrentLoop) + SE.forgetTopmostLoop(&L); handleDeadExits(); foldTerminators(); bool NewExitsAppeared = updateLoopInfo(); if (!DeadLoopBlocks.empty()) { LLVM_DEBUG(dbgs() << "Deleting " << DeadLoopBlocks.size() - << " dead blocks in loop " << L.getHeader()->getName() + << " dead blocks in loop " << Header->getName() << "\n"); deleteDeadLoopBlocks(); } - // TODO: Is there a smarter way to do it? - if (NewExitsAppeared) + if (DeleteCurrentLoop) { + assert(L.block_begin() == L.block_end() && "Removed loop should contain no blocks!"); + assert(L.begin() == L.end() && "Removed loop should contain no subloops!"); + LI.erase(&L); + } else if (NewExitsAppeared) + // TODO: Is there a smarter way to do it? formLCSSA(L, DT, &LI, nullptr); #ifndef NDEBUG // Make sure that we have preserved all data structures after the transform. DT.verify(); - assert(DT.isReachableFromEntry(L.getHeader())); + if (!DeleteCurrentLoop) + assert(DT.isReachableFromEntry(L.getHeader())); LI.verify(DT); #endif @@ -546,14 +551,17 @@ /// Turn branches and switches with known constant conditions into unconditional /// branches. -static bool constantFoldTerminators(Loop &L, DominatorTree &DT, LoopInfo &LI) { +static bool constantFoldTerminators(Loop &L, DominatorTree &DT, LoopInfo &LI, + ScalarEvolution &SE, bool &IsLoopDeleted) { // To keep things simple, only process loops with single latch. We // canonicalize most loops to this form. We can support multi-latch if needed. if (!L.getLoopLatch()) return false; - ConstantTerminatorFoldingImpl BranchFolder(L, LI, DT); - return BranchFolder.run(); + ConstantTerminatorFoldingImpl BranchFolder(L, LI, DT, SE); + bool Changed = BranchFolder.run(); + IsLoopDeleted = BranchFolder.isLoopDeleted(); + return Changed; } static bool mergeBlocksIntoPredecessors(Loop &L, DominatorTree &DT, @@ -585,11 +593,17 @@ } static bool simplifyLoopCFG(Loop &L, DominatorTree &DT, LoopInfo &LI, - ScalarEvolution &SE, MemorySSAUpdater *MSSAU) { + ScalarEvolution &SE, MemorySSAUpdater *MSSAU, + bool &IsLoopDeleted) { bool Changed = false; // Constant-fold terminators with known constant conditions. - Changed |= constantFoldTerminators(L, DT, LI); + Changed |= constantFoldTerminators(L, DT, LI, SE, IsLoopDeleted); + + if (IsLoopDeleted) { + assert(Changed && "Must be!"); + return true; + } // Eliminate unconditional branches by merging blocks into their predecessors. Changed |= mergeBlocksIntoPredecessors(L, DT, LI, MSSAU); @@ -602,14 +616,19 @@ PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, - LPMUpdater &) { + LPMUpdater &LPMU) { Optional MSSAU; if (EnableMSSALoopDependency && AR.MSSA) MSSAU = MemorySSAUpdater(AR.MSSA); + bool IsLoopDeleted = false; if (!simplifyLoopCFG(L, AR.DT, AR.LI, AR.SE, - MSSAU.hasValue() ? MSSAU.getPointer() : nullptr)) + MSSAU.hasValue() ? MSSAU.getPointer() : nullptr, + IsLoopDeleted)) return PreservedAnalyses::all(); + if (IsLoopDeleted) + LPMU.markLoopAsDeleted(L, "loop-simplifycfg"); + return getLoopPassPreservedAnalyses(); } @@ -621,7 +640,7 @@ initializeLoopSimplifyCFGLegacyPassPass(*PassRegistry::getPassRegistry()); } - bool runOnLoop(Loop *L, LPPassManager &) override { + bool runOnLoop(Loop *L, LPPassManager &LPM) override { if (skipLoop(L)) return false; @@ -635,8 +654,13 @@ if (VerifyMemorySSA) MSSA->verifyMemorySSA(); } - return simplifyLoopCFG(*L, DT, LI, SE, - MSSAU.hasValue() ? MSSAU.getPointer() : nullptr); + bool IsLoopDeleted = false; + bool Changed = simplifyLoopCFG(*L, DT, LI, SE, + MSSAU.hasValue() ? MSSAU.getPointer() : nullptr, + IsLoopDeleted); + if (IsLoopDeleted) + LPM.markLoopAsDeleted(*L); + return Changed; } void getAnalysisUsage(AnalysisUsage &AU) const override { Index: test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll =================================================================== --- test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll +++ test/Transforms/LoopSimplifyCFG/constant-fold-branch.ll @@ -335,16 +335,11 @@ ; CHECK-NEXT: preheader: ; 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-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_INC:%.*]] = add i32 0, 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]] -; CHECK-NEXT: br i1 false, label [[HEADER]], label [[EXIT:%.*]] +; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ] ; CHECK-NEXT: ret i32 [[I_INC_LCSSA]] @@ -379,20 +374,11 @@ ; 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: i32 2, label [[DEAD]] -; CHECK-NEXT: ] -; CHECK: dead: -; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1 -; CHECK-NEXT: br label [[BACKEDGE]] +; 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_INC:%.*]] = add i32 0, 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_INC]], [[END:%.*]] -; CHECK-NEXT: br i1 false, label [[HEADER]], label [[EXIT:%.*]] +; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ] ; CHECK-NEXT: ret i32 [[I_INC_LCSSA]] @@ -930,26 +916,15 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] ; CHECK: outer_header: -; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ] -; CHECK-NEXT: br label [[HEADER:%.*]] -; CHECK: header: -; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ] -; 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 false, label [[HEADER]], label [[OUTER_BACKEDGE]] -; CHECK: outer_backedge: -; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ] +; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_HEADER]] ] +; CHECK-NEXT: [[MUL:%.*]] = mul i32 0, 0 +; CHECK-NEXT: [[I_2:%.*]] = add i32 0, 1 +; CHECK-NEXT: [[I_INC:%.*]] = add i32 [[I_2]], 1 ; 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 [ [[I_INC]], [[OUTER_HEADER]] ] ; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] ; entry: @@ -993,30 +968,15 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] ; CHECK: outer_header: -; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ] -; CHECK-NEXT: br label [[HEADER:%.*]] -; CHECK: header: -; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ] -; 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 [[OUTER_BACKEDGE]] [ -; CHECK-NEXT: i32 0, label [[HEADER]] -; CHECK-NEXT: ] -; CHECK: outer_backedge: -; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ] +; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_HEADER]] ] +; CHECK-NEXT: [[MUL:%.*]] = mul i32 0, 0 +; CHECK-NEXT: [[I_2:%.*]] = add i32 0, 1 +; CHECK-NEXT: [[I_INC:%.*]] = add i32 [[I_2]], 1 ; 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 [ [[I_INC]], [[OUTER_HEADER]] ] ; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] ; entry: @@ -1061,26 +1021,14 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] ; CHECK: outer_header: -; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ] -; CHECK-NEXT: br label [[HEADER:%.*]] -; CHECK: header: -; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ] -; 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 false, label [[HEADER]], label [[OUTER_BACKEDGE]] -; CHECK: outer_backedge: -; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ] +; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_HEADER]] ] +; CHECK-NEXT: [[MUL:%.*]] = mul i32 0, 0 +; CHECK-NEXT: [[I_INC:%.*]] = add i32 0, 1 ; 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 [ [[I_INC]], [[OUTER_HEADER]] ] ; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] ; entry: @@ -1124,30 +1072,14 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] ; CHECK: outer_header: -; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_BACKEDGE:%.*]] ] -; CHECK-NEXT: br label [[HEADER:%.*]] -; CHECK: header: -; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[OUTER_HEADER]] ], [ [[I_INC:%.*]], [[BACKEDGE:%.*]] ] -; 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 [[OUTER_BACKEDGE]] [ -; CHECK-NEXT: i32 0, label [[HEADER]] -; CHECK-NEXT: ] -; CHECK: outer_backedge: -; CHECK-NEXT: [[I_INC_LCSSA:%.*]] = phi i32 [ [[I_INC]], [[BACKEDGE]] ] +; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[J_INC:%.*]], [[OUTER_HEADER]] ] +; CHECK-NEXT: [[MUL:%.*]] = mul i32 0, 0 +; CHECK-NEXT: [[I_INC:%.*]] = add i32 0, 1 ; 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 [ [[I_INC]], [[OUTER_HEADER]] ] ; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] ; entry: @@ -1189,12 +1121,15 @@ define i32 @full_sub_loop_test_branch_loop_inverse_2(i32 %end) { ; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_2( ; CHECK-NEXT: entry: +; CHECK-NEXT: switch i32 0, label [[ENTRY_SPLIT:%.*]] [ +; CHECK-NEXT: i32 1, label [[EXIT:%.*]] +; CHECK-NEXT: ] +; CHECK: entry-split: ; 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-NEXT: br label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[PREHEADER_SPLIT:%.*]] ; CHECK: preheader-split: ; CHECK-NEXT: br label [[HEADER:%.*]] ; CHECK: header: @@ -1203,13 +1138,8 @@ ; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1 ; CHECK-NEXT: [[I_INC]] = add i32 [[I_2]], 1 ; CHECK-NEXT: br label [[HEADER]] -; CHECK: outer_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 [ undef, [[OUTER_BACKEDGE]] ] -; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] +; CHECK-NEXT: ret i32 undef ; entry: br label %outer_header @@ -1250,12 +1180,15 @@ define i32 @full_sub_loop_test_switch_loop_inverse_2(i32 %end) { ; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_2( ; CHECK-NEXT: entry: +; CHECK-NEXT: switch i32 0, label [[ENTRY_SPLIT:%.*]] [ +; CHECK-NEXT: i32 1, label [[EXIT:%.*]] +; CHECK-NEXT: ] +; CHECK: entry-split: ; 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-NEXT: br label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[PREHEADER_SPLIT:%.*]] ; CHECK: preheader-split: ; CHECK-NEXT: br label [[HEADER:%.*]] ; CHECK: header: @@ -1264,13 +1197,8 @@ ; CHECK-NEXT: [[I_2:%.*]] = add i32 [[I]], 1 ; CHECK-NEXT: [[I_INC]] = add i32 [[I_2]], 1 ; CHECK-NEXT: br label [[HEADER]] -; CHECK: outer_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 [ undef, [[OUTER_BACKEDGE]] ] -; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] +; CHECK-NEXT: ret i32 undef ; entry: br label %outer_header @@ -1312,12 +1240,15 @@ define i32 @full_sub_loop_test_branch_loop_inverse_3(i32 %end) { ; CHECK-LABEL: @full_sub_loop_test_branch_loop_inverse_3( ; CHECK-NEXT: entry: +; CHECK-NEXT: switch i32 0, label [[ENTRY_SPLIT:%.*]] [ +; CHECK-NEXT: i32 1, label [[EXIT:%.*]] +; CHECK-NEXT: ] +; CHECK: entry-split: ; 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-NEXT: br label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[PREHEADER_SPLIT:%.*]] ; CHECK: preheader-split: ; CHECK-NEXT: br label [[HEADER:%.*]] ; CHECK: header: @@ -1325,13 +1256,8 @@ ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]] ; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1 ; CHECK-NEXT: br label [[HEADER]] -; CHECK: outer_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 [ undef, [[OUTER_BACKEDGE]] ] -; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] +; CHECK-NEXT: ret i32 undef ; entry: br label %outer_header @@ -1372,12 +1298,15 @@ define i32 @full_sub_loop_test_switch_loop_inverse_3(i32 %end) { ; CHECK-LABEL: @full_sub_loop_test_switch_loop_inverse_3( ; CHECK-NEXT: entry: +; CHECK-NEXT: switch i32 0, label [[ENTRY_SPLIT:%.*]] [ +; CHECK-NEXT: i32 1, label [[EXIT:%.*]] +; CHECK-NEXT: ] +; CHECK: entry-split: ; 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-NEXT: br label [[PREHEADER:%.*]] +; CHECK: preheader: +; CHECK-NEXT: br label [[PREHEADER_SPLIT:%.*]] ; CHECK: preheader-split: ; CHECK-NEXT: br label [[HEADER:%.*]] ; CHECK: header: @@ -1385,13 +1314,8 @@ ; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[I]], [[I]] ; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1 ; CHECK-NEXT: br label [[HEADER]] -; CHECK: outer_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 [ undef, [[OUTER_BACKEDGE]] ] -; CHECK-NEXT: ret i32 [[I_INC_LCSSA_LCSSA]] +; CHECK-NEXT: ret i32 undef ; entry: br label %outer_header @@ -1434,35 +1358,20 @@ ; CHECK-NEXT: preheader: ; CHECK-NEXT: br label [[LOOP_1:%.*]] ; CHECK: loop_1: -; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ] -; 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: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] ] ; CHECK-NEXT: br label [[LOOP_3:%.*]] ; CHECK: loop_3: -; 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-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[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 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:%.*]] -; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]] ; CHECK: loop_1_backedge.loopexit: -; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]] -; CHECK: loop_1_backedge.loopexit1: -; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]] -; CHECK: loop_1_backedge: ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 -; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ] +; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE_LOOPEXIT]] ] ; CHECK-NEXT: ret i32 [[I_LCSSA]] ; preheader: @@ -1503,35 +1412,20 @@ ; CHECK-NEXT: preheader: ; CHECK-NEXT: br label [[LOOP_1:%.*]] ; CHECK: loop_1: -; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE:%.*]] ] -; 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: [[I:%.*]] = phi i32 [ 0, [[PREHEADER:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_1_BACKEDGE_LOOPEXIT:%.*]] ] ; CHECK-NEXT: br label [[LOOP_3:%.*]] ; CHECK: loop_3: -; 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-NEXT: [[K:%.*]] = phi i32 [ 0, [[LOOP_1]] ], [ [[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 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:%.*]] -; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[LOOP_1_BACKEDGE_LOOPEXIT1:%.*]] ; CHECK: loop_1_backedge.loopexit: -; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]] -; CHECK: loop_1_backedge.loopexit1: -; CHECK-NEXT: br label [[LOOP_1_BACKEDGE]] -; CHECK: loop_1_backedge: ; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 -; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] +; CHECK-NEXT: [[C_1:%.*]] = icmp slt i32 [[I_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE]] ] +; CHECK-NEXT: [[I_LCSSA:%.*]] = phi i32 [ [[I]], [[LOOP_1_BACKEDGE_LOOPEXIT]] ] ; CHECK-NEXT: ret i32 [[I_LCSSA]] ; preheader: