aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/DwarfEHPrepare.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/DwarfEHPrepare.cpp')
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp181
1 files changed, 59 insertions, 122 deletions
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index 5da3171..1416f5b 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -88,6 +88,12 @@ namespace {
/// initializer instead.
bool CleanupSelectors();
+ /// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups.
+ void FindAllCleanupSelectors(SmallPtrSet<IntrinsicInst*, 32> &Sels);
+
+ /// FindAllURoRInvokes - Find all URoR invokes in the function.
+ void FindAllURoRInvokes(SmallPtrSet<InvokeInst*, 32> &URoRInvokes);
+
/// HandleURoRInvokes - Handle invokes of "_Unwind_Resume_or_Rethrow"
/// calls. The "unwind" part of these invokes jump to a landing pad within
/// the current function. This is a candidate to merge the selector
@@ -95,57 +101,6 @@ namespace {
/// pad.
bool HandleURoRInvokes();
- /// FindSelectorAndURoR - Find the eh.selector call and URoR call associated
- /// with the eh.exception call. This recursively looks past instructions
- /// which don't change the EH pointer value, like casts or PHI nodes.
- bool FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke,
- SmallPtrSet<IntrinsicInst*, 8> &SelCalls);
-
- /// DoMem2RegPromotion - Take an alloca call and promote it from memory to a
- /// register.
- bool DoMem2RegPromotion(Value *V) {
- AllocaInst *AI = dyn_cast<AllocaInst>(V);
- if (!AI || !isAllocaPromotable(AI)) return false;
-
- // Turn the alloca into a register.
- std::vector<AllocaInst*> Allocas(1, AI);
- PromoteMemToReg(Allocas, *DT, *DF);
- return true;
- }
-
- /// PromoteStoreInst - Perform Mem2Reg on a StoreInst.
- bool PromoteStoreInst(StoreInst *SI) {
- if (!SI || !DT || !DF) return false;
- if (DoMem2RegPromotion(SI->getOperand(1)))
- return true;
- return false;
- }
-
- /// PromoteEHPtrStore - Promote the storing of an EH pointer into a
- /// register. This should get rid of the store and subsequent loads.
- bool PromoteEHPtrStore(IntrinsicInst *II) {
- if (!DT || !DF) return false;
-
- bool Changed = false;
- StoreInst *SI;
-
- while (1) {
- SI = 0;
- for (Value::use_iterator
- I = II->use_begin(), E = II->use_end(); I != E; ++I) {
- SI = dyn_cast<StoreInst>(I);
- if (SI) break;
- }
-
- if (!PromoteStoreInst(SI))
- break;
-
- Changed = true;
- }
-
- return false;
- }
-
public:
static char ID; // Pass identification, replacement for typeid.
DwarfEHPrepare(const TargetLowering *tli, bool fast) :
@@ -178,49 +133,51 @@ FunctionPass *llvm::createDwarfEHPass(const TargetLowering *tli, bool fast) {
return new DwarfEHPrepare(tli, fast);
}
-/// FindSelectorAndURoR - Find the eh.selector call associated with the
-/// eh.exception call. And indicate if there is a URoR "invoke" associated with
-/// the eh.exception call. This recursively looks past instructions which don't
-/// change the EH pointer value, like casts or PHI nodes.
-bool
-DwarfEHPrepare::FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke,
- SmallPtrSet<IntrinsicInst*, 8> &SelCalls) {
- SmallPtrSet<PHINode*, 32> SeenPHIs;
- bool Changed = false;
-
- restart:
+/// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups.
+void DwarfEHPrepare::
+FindAllCleanupSelectors(SmallPtrSet<IntrinsicInst*, 32> &Sels) {
for (Value::use_iterator
- I = Inst->use_begin(), E = Inst->use_end(); I != E; ++I) {
- Instruction *II = dyn_cast<Instruction>(I);
- if (!II || II->getParent()->getParent() != F) continue;
-
- if (IntrinsicInst *Sel = dyn_cast<IntrinsicInst>(II)) {
- if (Sel->getIntrinsicID() == Intrinsic::eh_selector)
- SelCalls.insert(Sel);
- } else if (InvokeInst *Invoke = dyn_cast<InvokeInst>(II)) {
- if (Invoke->getCalledFunction() == URoR)
- URoRInvoke = true;
- } else if (CastInst *CI = dyn_cast<CastInst>(II)) {
- Changed |= FindSelectorAndURoR(CI, URoRInvoke, SelCalls);
- } else if (StoreInst *SI = dyn_cast<StoreInst>(II)) {
- if (!PromoteStoreInst(SI)) continue;
- Changed = true;
- SeenPHIs.clear();
- goto restart; // Uses may have changed, restart loop.
- } else if (PHINode *PN = dyn_cast<PHINode>(II)) {
- if (SeenPHIs.insert(PN))
- // Don't process a PHI node more than once.
- Changed |= FindSelectorAndURoR(PN, URoRInvoke, SelCalls);
- }
+ I = SelectorIntrinsic->use_begin(),
+ E = SelectorIntrinsic->use_end(); I != E; ++I) {
+ IntrinsicInst *SI = cast<IntrinsicInst>(I);
+ if (!SI || SI->getParent()->getParent() != F) continue;
+
+ unsigned NumOps = SI->getNumOperands();
+ if (NumOps > 4) continue;
+ bool IsCleanUp = (NumOps == 3);
+
+ if (!IsCleanUp)
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(SI->getOperand(3)))
+ IsCleanUp = (CI->getZExtValue() == 0);
+
+ if (IsCleanUp)
+ Sels.insert(SI);
}
+}
- return Changed;
+/// FindAllURoRInvokes - Find all URoR invokes in the function.
+void DwarfEHPrepare::
+FindAllURoRInvokes(SmallPtrSet<InvokeInst*, 32> &URoRInvokes) {
+ for (Value::use_iterator
+ I = URoR->use_begin(),
+ E = URoR->use_end(); I != E; ++I) {
+ if (InvokeInst *II = dyn_cast<InvokeInst>(I))
+ URoRInvokes.insert(II);
+ }
}
/// CleanupSelectors - Any remaining eh.selector intrinsic calls which still use
/// the ".llvm.eh.catch.all.value" call need to convert to using it's
/// initializer instead.
bool DwarfEHPrepare::CleanupSelectors() {
+ if (!EHCatchAllValue) return false;
+
+ if (!SelectorIntrinsic) {
+ SelectorIntrinsic =
+ Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_selector);
+ if (!SelectorIntrinsic) return false;
+ }
+
bool Changed = false;
for (Value::use_iterator
I = SelectorIntrinsic->use_begin(),
@@ -244,6 +201,8 @@ bool DwarfEHPrepare::CleanupSelectors() {
/// function. This is a candidate to merge the selector associated with the URoR
/// invoke with the one from the URoR's landing pad.
bool DwarfEHPrepare::HandleURoRInvokes() {
+ if (!DT) return CleanupSelectors(); // We require DominatorTree information.
+
if (!EHCatchAllValue) {
EHCatchAllValue =
F->getParent()->getNamedGlobal(".llvm.eh.catch.all.value");
@@ -261,50 +220,28 @@ bool DwarfEHPrepare::HandleURoRInvokes() {
if (!URoR) return CleanupSelectors();
}
- if (!ExceptionValueIntrinsic) {
- ExceptionValueIntrinsic =
- Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_exception);
- if (!ExceptionValueIntrinsic) return CleanupSelectors();
- }
+ SmallPtrSet<IntrinsicInst*, 32> Sels;
+ SmallPtrSet<InvokeInst*, 32> URoRInvokes;
+ FindAllCleanupSelectors(Sels);
+ FindAllURoRInvokes(URoRInvokes);
- bool Changed = false;
SmallPtrSet<IntrinsicInst*, 32> SelsToConvert;
- for (Value::use_iterator
- I = ExceptionValueIntrinsic->use_begin(),
- E = ExceptionValueIntrinsic->use_end(); I != E; ++I) {
- IntrinsicInst *EHPtr = dyn_cast<IntrinsicInst>(I);
- if (!EHPtr || EHPtr->getParent()->getParent() != F) continue;
-
- Changed |= PromoteEHPtrStore(EHPtr);
-
- bool URoRInvoke = false;
- SmallPtrSet<IntrinsicInst*, 8> SelCalls;
- Changed |= FindSelectorAndURoR(EHPtr, URoRInvoke, SelCalls);
-
- if (URoRInvoke) {
- // This EH pointer is being used by an invoke of an URoR instruction and
- // an eh.selector intrinsic call. If the eh.selector is a 'clean-up', we
- // need to convert it to a 'catch-all'.
- for (SmallPtrSet<IntrinsicInst*, 8>::iterator
- SI = SelCalls.begin(), SE = SelCalls.end(); SI != SE; ++SI) {
- IntrinsicInst *II = *SI;
- unsigned NumOps = II->getNumOperands();
-
- if (NumOps <= 4) {
- bool IsCleanUp = (NumOps == 3);
-
- if (!IsCleanUp)
- if (ConstantInt *CI = dyn_cast<ConstantInt>(II->getOperand(3)))
- IsCleanUp = (CI->getZExtValue() == 0);
-
- if (IsCleanUp)
- SelsToConvert.insert(II);
- }
+ for (SmallPtrSet<IntrinsicInst*, 32>::iterator
+ SI = Sels.begin(), SE = Sels.end(); SI != SE; ++SI) {
+ const BasicBlock *SelBB = (*SI)->getParent();
+ for (SmallPtrSet<InvokeInst*, 32>::iterator
+ UI = URoRInvokes.begin(), UE = URoRInvokes.end(); UI != UE; ++UI) {
+ const BasicBlock *URoRBB = (*UI)->getParent();
+ if (SelBB == URoRBB || DT->dominates(SelBB, URoRBB)) {
+ SelsToConvert.insert(*SI);
+ break;
}
}
}
+ bool Changed = false;
+
if (!SelsToConvert.empty()) {
// Convert all clean-up eh.selectors, which are associated with "invokes" of
// URoR calls, into catch-all eh.selectors.