summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-11-29 19:38:06 +0000
committerBill Wendling <isanbard@gmail.com>2012-11-29 19:38:06 +0000
commita4a77edf2e27dc8a24ac3323c48a2c7201fccbda (patch)
tree40178446d5976def3a618b7b722eedeb4f64b2fc /llvm
parente95559fc16277e561cdb62fe36ea9de66afde329 (diff)
downloadbcm5719-llvm-a4a77edf2e27dc8a24ac3323c48a2c7201fccbda.tar.gz
bcm5719-llvm-a4a77edf2e27dc8a24ac3323c48a2c7201fccbda.zip
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. <rdar://problem/12721258> llvm-svn: 168930
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp75
-rw-r--r--llvm/test/CodeGen/ARM/crash.ll23
2 files changed, 98 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
index 61adb2dc12b..c4df1545299 100644
--- a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
+++ b/llvm/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/llvm/test/CodeGen/ARM/crash.ll b/llvm/test/CodeGen/ARM/crash.ll
index 0f6f33e0448..4e3e2010b07 100644
--- a/llvm/test/CodeGen/ARM/crash.ll
+++ b/llvm/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(...)
OpenPOWER on IntegriCloud