summaryrefslogtreecommitdiff
path: root/lib/CodeGen/DwarfEHPrepare.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-01-28 00:47:18 +0000
committerBill Wendling <isanbard@gmail.com>2012-01-28 00:47:18 +0000
commitb0064c6d8b50b43f56aabaebfd0e0ac274501a59 (patch)
tree346ad20b0237bba2850290287db9cbf8c8b1d024 /lib/CodeGen/DwarfEHPrepare.cpp
parent1d5013992f8ecf5cc670ab8a1a599db4722c2f5d (diff)
downloadllvm-b0064c6d8b50b43f56aabaebfd0e0ac274501a59.tar.gz
llvm-b0064c6d8b50b43f56aabaebfd0e0ac274501a59.tar.bz2
llvm-b0064c6d8b50b43f56aabaebfd0e0ac274501a59.tar.xz
Don't always create a separate block for the call to _Unwind_Resume.
Sometimes there is only one 'resume' instruction per function. In those situations, we don't need a separate block for the call to _Unwind_Resume. In fact, it adds a lot of overhead to code-gen if we do that -- especially at -O0. If we have a single 'resume' instruction, just generate the call within that block. <rdar://problem/10694814> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@149159 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/DwarfEHPrepare.cpp')
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp93
1 files changed, 61 insertions, 32 deletions
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index f2b2977275..22f7b1c6d6 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -39,6 +39,7 @@ namespace {
Constant *RewindFunction;
bool InsertUnwindResumeCalls(Function &Fn);
+ Instruction *GetExceptionObject(ResumeInst *RI);
public:
static char ID; // Pass identification, replacement for typeid.
@@ -64,6 +65,46 @@ FunctionPass *llvm::createDwarfEHPass(const TargetMachine *tm) {
return new DwarfEHPrepare(tm);
}
+/// GetExceptionObject - Return the exception object from the value passed into
+/// the 'resume' instruction (typically an aggregate). Clean up any dead
+/// instructions, including the 'resume' instruction.
+Instruction *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
+ Value *V = RI->getOperand(0);
+ Instruction *ExnObj = 0;
+ InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
+ LoadInst *SelLoad = 0;
+ InsertValueInst *ExcIVI = 0;
+ bool EraseIVIs = false;
+
+ if (SelIVI) {
+ if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
+ ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
+ if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
+ ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
+ ExnObj = cast<Instruction>(ExcIVI->getOperand(1));
+ SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
+ EraseIVIs = true;
+ }
+ }
+ }
+
+ if (!ExnObj)
+ ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
+
+ RI->eraseFromParent();
+
+ if (EraseIVIs) {
+ if (SelIVI->getNumUses() == 0)
+ SelIVI->eraseFromParent();
+ if (ExcIVI->getNumUses() == 0)
+ ExcIVI->eraseFromParent();
+ if (SelLoad && SelLoad->getNumUses() == 0)
+ SelLoad->eraseFromParent();
+ }
+
+ return ExnObj;
+}
+
/// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
/// into calls to the appropriate _Unwind_Resume function.
bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
@@ -91,8 +132,26 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
// Create the basic block where the _Unwind_Resume call will live.
LLVMContext &Ctx = Fn.getContext();
+ unsigned ResumesSize = Resumes.size();
+
+ if (ResumesSize == 1) {
+ // Instead of creating a new BB and PHI node, just append the call to
+ // _Unwind_Resume to the end of the single resume block.
+ ResumeInst *RI = Resumes.front();
+ BasicBlock *UnwindBB = RI->getParent();
+ Instruction *ExnObj = GetExceptionObject(RI);
+
+ // Call the _Unwind_Resume function.
+ CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
+ CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
+
+ // We never expect _Unwind_Resume to return.
+ new UnreachableInst(Ctx, UnwindBB);
+ return true;
+ }
+
BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
- PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), Resumes.size(),
+ PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesSize,
"exn.obj", UnwindBB);
// Extract the exception object from the ResumeInst and add it to the PHI node
@@ -102,38 +161,8 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
ResumeInst *RI = *I;
BranchInst::Create(UnwindBB, RI->getParent());
- Value *V = RI->getOperand(0);
- Instruction *ExnObj = 0;
- InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
- LoadInst *SelLoad = 0;
- InsertValueInst *ExcIVI = 0;
- bool EraseIVIs = false;
- if (SelIVI) {
- if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
- ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
- if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
- ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
- ExnObj = cast<Instruction>(ExcIVI->getOperand(1));
- SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
- EraseIVIs = true;
- }
- }
- }
-
- if (!ExnObj)
- ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
-
+ Instruction *ExnObj = GetExceptionObject(RI);
PN->addIncoming(ExnObj, RI->getParent());
- RI->eraseFromParent();
-
- if (EraseIVIs) {
- if (SelIVI->getNumUses() == 0)
- SelIVI->eraseFromParent();
- if (ExcIVI->getNumUses() == 0)
- ExcIVI->eraseFromParent();
- if (SelLoad && SelLoad->getNumUses() == 0)
- SelLoad->eraseFromParent();
- }
++NumResumesLowered;
}