diff options
-rw-r--r-- | lib/Transforms/Scalar/CodeGenPrepare.cpp | 75 | ||||
-rw-r--r-- | test/CodeGen/ARM/crash.ll | 23 |
2 files changed, 98 insertions, 0 deletions
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<BasicBlock*, 8> WorkList; + SmallPtrSet<BasicBlock*, 8> LPadList; + SmallVector<BasicBlock*, 8> ReturnList; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { SmallVector<BasicBlock*, 2> Successors(succ_begin(BB), succ_end(BB)); + if (BB->isLandingPad()) LPadList.insert(BB); + if (isa<ReturnInst>(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<BasicBlock*, 2> 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<Instruction*, 8> DeadInsts; + for (BasicBlock::iterator I = Entry.begin(), E = Entry.end(); + I != E; ++I) { + if (CallInst *CI = dyn_cast<CallInst>(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<BasicBlock*>::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<CallInst>(&*II)) { + Value *Callee = CI->getCalledValue(); + + if (Callee == UnregisterFn) { + DeadInsts.push_back(CI); + break; + } + } + } + } + + // Kill the dead instructions. + for (SmallVectorImpl<Instruction*>::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) diff --git a/test/CodeGen/ARM/crash.ll b/test/CodeGen/ARM/crash.ll index 0f6f33e044..4e3e2010b0 100644 --- a/test/CodeGen/ARM/crash.ll +++ b/test/CodeGen/ARM/crash.ll @@ -69,3 +69,26 @@ bb: store <4 x float> %tmp154, <4 x float>* undef, align 16 ret void } + +; <rdar://problem/12721258> +%A = type { %B } +%B = type { i32 } + +define void @_Z3Foov() ssp { +entry: + br i1 true, label %exit, label %false + +false: + invoke void undef(%A* undef) + to label %exit unwind label %lpad + +lpad: + %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_sj0 to i8*) + catch i8* null + unreachable + +exit: + ret void +} + +declare i32 @__gxx_personality_sj0(...) |