X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FDwarfEHPrepare.cpp;h=d1261a3565b93417b536e59898b40e1befcaa944;hb=23eaf26fa3510526b11230c76ea39221277dd2ea;hp=5da3171518774f03d1ab596c953f623612fb56ce;hpb=43de15f8a356293dd1b1c4dd321f90802fff5ce3;p=oota-llvm.git diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp index 5da31715187..d1261a3565b 100644 --- a/lib/CodeGen/DwarfEHPrepare.cpp +++ b/lib/CodeGen/DwarfEHPrepare.cpp @@ -84,10 +84,16 @@ namespace { } /// CleanupSelectors - Any remaining eh.selector intrinsic calls which still - /// use the ".llvm.eh.catch.all.value" call need to convert to using it's + /// use the ".llvm.eh.catch.all.value" call need to convert to using its /// initializer instead. bool CleanupSelectors(); + /// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups. + void FindAllCleanupSelectors(SmallPtrSet &Sels); + + /// FindAllURoRInvokes - Find all URoR invokes in the function. + void FindAllURoRInvokes(SmallPtrSet &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 @@ -178,6 +184,69 @@ FunctionPass *llvm::createDwarfEHPass(const TargetLowering *tli, bool fast) { return new DwarfEHPrepare(tli, fast); } +/// FindAllCleanupSelectors - Find all eh.selector calls that are clean-ups. +void DwarfEHPrepare:: +FindAllCleanupSelectors(SmallPtrSet &Sels) { + for (Value::use_iterator + I = SelectorIntrinsic->use_begin(), + E = SelectorIntrinsic->use_end(); I != E; ++I) { + IntrinsicInst *SI = cast(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(SI->getOperand(3))) + IsCleanUp = (CI->getZExtValue() == 0); + + if (IsCleanUp) + Sels.insert(SI); + } +} + +/// FindAllURoRInvokes - Find all URoR invokes in the function. +void DwarfEHPrepare:: +FindAllURoRInvokes(SmallPtrSet &URoRInvokes) { + for (Value::use_iterator + I = URoR->use_begin(), + E = URoR->use_end(); I != E; ++I) { + if (InvokeInst *II = dyn_cast(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 its +/// 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(), + E = SelectorIntrinsic->use_end(); I != E; ++I) { + IntrinsicInst *Sel = dyn_cast(I); + if (!Sel || Sel->getParent()->getParent() != F) continue; + + // Index of the ".llvm.eh.catch.all.value" variable. + unsigned OpIdx = Sel->getNumOperands() - 1; + GlobalVariable *GV = dyn_cast(Sel->getOperand(OpIdx)); + if (GV != EHCatchAllValue) continue; + Sel->setOperand(OpIdx, EHCatchAllValue->getInitializer()); + Changed = true; + } + + return Changed; +} + /// 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 @@ -217,33 +286,13 @@ DwarfEHPrepare::FindSelectorAndURoR(Instruction *Inst, bool &URoRInvoke, return Changed; } -/// 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() { - bool Changed = false; - for (Value::use_iterator - I = SelectorIntrinsic->use_begin(), - E = SelectorIntrinsic->use_end(); I != E; ++I) { - IntrinsicInst *Sel = dyn_cast(I); - if (!Sel || Sel->getParent()->getParent() != F) continue; - - // Index of the ".llvm.eh.catch.all.value" variable. - unsigned OpIdx = Sel->getNumOperands() - 1; - GlobalVariable *GV = dyn_cast(Sel->getOperand(OpIdx)); - if (GV != EHCatchAllValue) continue; - Sel->setOperand(OpIdx, EHCatchAllValue->getInitializer()); - Changed = true; - } - - return Changed; -} - /// 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 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,45 +310,68 @@ bool DwarfEHPrepare::HandleURoRInvokes() { if (!URoR) return CleanupSelectors(); } - if (!ExceptionValueIntrinsic) { - ExceptionValueIntrinsic = - Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_exception); - if (!ExceptionValueIntrinsic) return CleanupSelectors(); + SmallPtrSet Sels; + SmallPtrSet URoRInvokes; + FindAllCleanupSelectors(Sels); + FindAllURoRInvokes(URoRInvokes); + + SmallPtrSet SelsToConvert; + + for (SmallPtrSet::iterator + SI = Sels.begin(), SE = Sels.end(); SI != SE; ++SI) { + const BasicBlock *SelBB = (*SI)->getParent(); + for (SmallPtrSet::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; - SmallPtrSet SelsToConvert; - for (Value::use_iterator - I = ExceptionValueIntrinsic->use_begin(), - E = ExceptionValueIntrinsic->use_end(); I != E; ++I) { - IntrinsicInst *EHPtr = dyn_cast(I); - if (!EHPtr || EHPtr->getParent()->getParent() != F) continue; - - Changed |= PromoteEHPtrStore(EHPtr); - - bool URoRInvoke = false; - SmallPtrSet 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::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(II->getOperand(3))) - IsCleanUp = (CI->getZExtValue() == 0); - - if (IsCleanUp) - SelsToConvert.insert(II); + if (Sels.size() != SelsToConvert.size()) { + // If we haven't been able to convert all of the clean-up selectors, then + // loop through the slow way to see if they still need to be converted. + if (!ExceptionValueIntrinsic) { + ExceptionValueIntrinsic = + Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_exception); + if (!ExceptionValueIntrinsic) return CleanupSelectors(); + } + + for (Value::use_iterator + I = ExceptionValueIntrinsic->use_begin(), + E = ExceptionValueIntrinsic->use_end(); I != E; ++I) { + IntrinsicInst *EHPtr = dyn_cast(I); + if (!EHPtr || EHPtr->getParent()->getParent() != F) continue; + + Changed |= PromoteEHPtrStore(EHPtr); + + bool URoRInvoke = false; + SmallPtrSet 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::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(II->getOperand(3))) + IsCleanUp = (CI->getZExtValue() == 0); + + if (IsCleanUp) + SelsToConvert.insert(II); + } } } } @@ -589,7 +661,7 @@ bool DwarfEHPrepare::PromoteStackTemporaries() { /// the start of the basic block (unless there already is one, in which case /// the existing call is returned). Instruction *DwarfEHPrepare::CreateExceptionValueCall(BasicBlock *BB) { - Instruction *Start = BB->getFirstNonPHI(); + Instruction *Start = BB->getFirstNonPHIOrDbg(); // Is this a call to eh.exception? if (IntrinsicInst *CI = dyn_cast(Start)) if (CI->getIntrinsicID() == Intrinsic::eh_exception) @@ -609,7 +681,7 @@ Instruction *DwarfEHPrepare::CreateExceptionValueCall(BasicBlock *BB) { /// (creating it if necessary) at the start of the basic block (unless /// there already is a load, in which case the existing load is returned). Instruction *DwarfEHPrepare::CreateValueLoad(BasicBlock *BB) { - Instruction *Start = BB->getFirstNonPHI(); + Instruction *Start = BB->getFirstNonPHIOrDbg(); // Is this a load of the exception temporary? if (ExceptionValueVar) if (LoadInst* LI = dyn_cast(Start))