diff options
-rw-r--r-- | llvm/lib/Transforms/IPO/PruneEH.cpp | 21 | ||||
-rw-r--r-- | llvm/test/Transforms/PruneEH/pr26263.ll | 30 |
2 files changed, 46 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/IPO/PruneEH.cpp b/llvm/lib/Transforms/IPO/PruneEH.cpp index da3bf234d21..c2f55d896ba 100644 --- a/llvm/lib/Transforms/IPO/PruneEH.cpp +++ b/llvm/lib/Transforms/IPO/PruneEH.cpp @@ -228,10 +228,17 @@ void PruneEH::DeleteBasicBlock(BasicBlock *BB) { assert(pred_empty(BB) && "BB is not dead!"); CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); + Instruction *TokenInst = nullptr; + CallGraphNode *CGN = CG[BB->getParent()]; for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) { --I; + if (I->getType()->isTokenTy()) { + TokenInst = &*I; + break; + } + if (auto CS = CallSite (&*I)) { const Function *Callee = CS.getCalledFunction(); if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID())) @@ -244,11 +251,15 @@ void PruneEH::DeleteBasicBlock(BasicBlock *BB) { I->replaceAllUsesWith(UndefValue::get(I->getType())); } - // Get the list of successors of this block. - std::vector<BasicBlock*> Succs(succ_begin(BB), succ_end(BB)); + if (TokenInst) { + changeToUnreachable(TokenInst->getNextNode(), /*UseLLVMTrap=*/false); + } else { + // Get the list of successors of this block. + std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB)); - for (unsigned i = 0, e = Succs.size(); i != e; ++i) - Succs[i]->removePredecessor(BB); + for (unsigned i = 0, e = Succs.size(); i != e; ++i) + Succs[i]->removePredecessor(BB); - BB->eraseFromParent(); + BB->eraseFromParent(); + } } diff --git a/llvm/test/Transforms/PruneEH/pr26263.ll b/llvm/test/Transforms/PruneEH/pr26263.ll new file mode 100644 index 00000000000..3670f00d811 --- /dev/null +++ b/llvm/test/Transforms/PruneEH/pr26263.ll @@ -0,0 +1,30 @@ +; RUN: opt -prune-eh -S < %s | FileCheck %s +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i386-pc-windows-msvc" + +declare void @neverthrows() nounwind + +define void @test1() personality i32 (...)* @__CxxFrameHandler3 { + invoke void @neverthrows() + to label %try.cont unwind label %cleanuppad + +try.cont: + ret void + +cleanuppad: + %cp = cleanuppad within none [] + br label %cleanupret + +cleanupret: + cleanupret from %cp unwind to caller +} + +; CHECK-LABEL: define void @test1( +; CHECK: call void @neverthrows() + +; CHECK: %[[cp:.*]] = cleanuppad within none [] +; CHECK-NEXT: unreachable + +; CHECK: cleanupret from %[[cp]] unwind to caller + +declare i32 @__CxxFrameHandler3(...) |