diff --git a/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp index 031e5b9c1d2..8ab3c2ca118 100644 --- a/lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -366,15 +366,20 @@ private: unsigned DummyIdx = 1; for (BasicBlock *BB : DeadExitBlocks) { - SmallVector DeadPhis; + // Eliminate all Phis and LandingPads from dead exits. + // TODO: Consider removing all instructions in this dead block. + SmallVector DeadInstructions; for (auto &PN : BB->phis()) - DeadPhis.push_back(&PN); + DeadInstructions.push_back(&PN); - // Eliminate all Phis from dead exits. - for (Instruction *PN : DeadPhis) { - PN->replaceAllUsesWith(UndefValue::get(PN->getType())); - PN->eraseFromParent(); + if (auto *LandingPad = dyn_cast(BB->getFirstNonPHI())) + DeadInstructions.emplace_back(LandingPad); + + for (Instruction *I : DeadInstructions) { + I->replaceAllUsesWith(UndefValue::get(I->getType())); + I->eraseFromParent(); } + assert(DummyIdx != 0 && "Too many dead exits!"); DummySwitch->addCase(Builder.getInt32(DummyIdx++), BB); DTUpdates.push_back({DominatorTree::Insert, Preheader, BB}); diff --git a/test/Transforms/LoopSimplifyCFG/handle_dead_exits.ll b/test/Transforms/LoopSimplifyCFG/handle_dead_exits.ll new file mode 100644 index 00000000000..1fb7fb4b133 --- /dev/null +++ b/test/Transforms/LoopSimplifyCFG/handle_dead_exits.ll @@ -0,0 +1,88 @@ +; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -loop-simplifycfg %s | FileCheck %s +; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes='require,loop(simplify-cfg)' %s | FileCheck %s + +declare i32* @fake_personality_function() +declare void @foo() + +define i32 @test_remove_lpad(i1 %exitcond) personality i32* ()* @fake_personality_function { +; CHECK-LABEL: @test_remove_lpad( +entry: + br label %for.body + +for.body: + br i1 0, label %never, label %next + +next: + br label %latch + +latch: + br i1 %exitcond, label %exit, label %for.body + +exit: + ret i32 0 + +never: + invoke void @foo() to label %next unwind label %never-unwind + +never-unwind: +; CHECK: never-unwind: +; CHECK-NEXT: unreachable + %res = landingpad token cleanup + unreachable +} + +define i32 @test_remove_phi_lpad(i1 %exitcond) personality i32* ()* @fake_personality_function { +; CHECK-LABEL: @test_remove_phi_lpad( +entry: + br label %for.body + +for.body: + br i1 0, label %never, label %next + +next: + br label %latch + +latch: + br i1 %exitcond, label %exit, label %for.body + +exit: + ret i32 0 + +never: + invoke void @foo() to label %next unwind label %never-unwind + +never-unwind: +; CHECK: never-unwind: +; CHECK-NEXT: ret i32 undef + %p = phi i32 [1, %never] + %res = landingpad token cleanup + ret i32 %p +} + +define i32 @test_split_remove_phi_lpad_(i1 %exitcond) personality i32* ()* @fake_personality_function { +; CHECK-LABEL: @test_split_remove_phi_lpad_( +entry: + invoke void @foo() to label %for.body unwind label %unwind-bb + +for.body: + br i1 0, label %never, label %next + +next: + br label %latch + +latch: + br i1 %exitcond, label %exit, label %for.body + +exit: + ret i32 0 + +never: + invoke void @foo() to label %next unwind label %unwind-bb + +unwind-bb: +; CHECK: unwind-bb.loopexit: +; CHECK-NEXT: br label %unwind-bb + %p = phi i32 [1, %never], [2, %entry] + %res = landingpad token cleanup + ret i32 %p +}