From 73601160486b14711e1c6fdd86481eda9c319e45 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 29 Nov 2012 19:38:06 +0000 Subject: Handle the situation where CodeGenPrepare removes a reference to a BB that has the last invoke instruction in the function. This also removes the last landing pad in an function. This is fine, but with SjLj EH code, we've already placed a bunch of code in the 'entry' block, which expects the landing pad to stick around. When we get to the situation where CGP has removed the last landing pad, go ahead and nuke the SjLj instructions from the 'entry' block. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168930 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/CodeGenPrepare.cpp | 75 ++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'lib/Transforms/Scalar/CodeGenPrepare.cpp') diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 61adb2dc12..c4df154529 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -22,6 +22,7 @@ #include "llvm/InlineAsm.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" @@ -183,8 +184,12 @@ bool CodeGenPrepare::runOnFunction(Function &F) { if (!DisableBranchOpts) { MadeChange = false; SmallPtrSet WorkList; + SmallPtrSet LPadList; + SmallVector ReturnList; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { SmallVector Successors(succ_begin(BB), succ_end(BB)); + if (BB->isLandingPad()) LPadList.insert(BB); + if (isa(BB->getTerminator())) ReturnList.push_back(BB); MadeChange |= ConstantFoldTerminator(BB, true); if (!MadeChange) continue; @@ -195,9 +200,11 @@ bool CodeGenPrepare::runOnFunction(Function &F) { } // Delete the dead blocks and any of their dead successors. + bool HadLPads = !LPadList.empty(); while (!WorkList.empty()) { BasicBlock *BB = *WorkList.begin(); WorkList.erase(BB); + LPadList.erase(BB); SmallVector Successors(succ_begin(BB), succ_end(BB)); DeleteDeadBlock(BB); @@ -208,6 +215,74 @@ bool CodeGenPrepare::runOnFunction(Function &F) { WorkList.insert(*II); } + if (HadLPads && LPadList.empty()) { + // All of the landing pads were removed. Get rid of the SjLj EH context + // code. + Module *M = F.getParent(); + + // These functions must exist if we have SjLj EH code to clean up. + Constant *RegisterFn = M->getFunction("_Unwind_SjLj_Register"); + Constant *UnregisterFn = M->getFunction("_Unwind_SjLj_Unregister"); + + if (RegisterFn) { + Constant *LSDAAddrFn = + Intrinsic::getDeclaration(M, Intrinsic::eh_sjlj_lsda); + Constant *FrameAddrFn = + Intrinsic::getDeclaration(M, Intrinsic::frameaddress); + Constant *StackAddrFn = + Intrinsic::getDeclaration(M, Intrinsic::stacksave); + Constant *BuiltinSetjmpFn = + Intrinsic::getDeclaration(M, Intrinsic::eh_sjlj_setjmp); + Constant *FuncCtxFn = + Intrinsic::getDeclaration(M, Intrinsic::eh_sjlj_functioncontext); + + BasicBlock &Entry = F.getEntryBlock(); + SmallVector DeadInsts; + for (BasicBlock::iterator I = Entry.begin(), E = Entry.end(); + I != E; ++I) { + if (CallInst *CI = dyn_cast(I)) { + Value *Callee = CI->getCalledValue(); + bool IsDead = true; + if (Callee != LSDAAddrFn && Callee != FrameAddrFn && + Callee != StackAddrFn && Callee != BuiltinSetjmpFn && + Callee != FuncCtxFn && Callee != RegisterFn) + IsDead = false; + + if (IsDead) { + Type *Ty = CI->getType(); + if (!Ty->isVoidTy()) + CI->replaceAllUsesWith(UndefValue::get(Ty)); + DeadInsts.push_back(CI); + } + } + } + + // Find and remove the unregister calls. + for (SmallVectorImpl::iterator I = ReturnList.begin(), + E = ReturnList.end(); I != E; ++I) { + BasicBlock *BB = *I; + typedef BasicBlock::InstListType::reverse_iterator reverse_iterator; + + for (reverse_iterator II = BB->getInstList().rbegin(), + IE = BB->getInstList().rend(); II != IE; ++II) { + if (CallInst *CI = dyn_cast(&*II)) { + Value *Callee = CI->getCalledValue(); + + if (Callee == UnregisterFn) { + DeadInsts.push_back(CI); + break; + } + } + } + } + + // Kill the dead instructions. + for (SmallVectorImpl::iterator I = DeadInsts.begin(), + E = DeadInsts.end(); I != E; ++I) + (*I)->eraseFromParent(); + } + } + // Merge pairs of basic blocks with unconditional branches, connected by // a single edge. if (EverMadeChange || MadeChange) -- cgit v1.2.3