A more general (and simpler!) implementation of r99671. It performs a similar
authorBill Wendling <isanbard@gmail.com>
Mon, 29 Mar 2010 23:02:46 +0000 (23:02 +0000)
committerBill Wendling <isanbard@gmail.com>
Mon, 29 Mar 2010 23:02:46 +0000 (23:02 +0000)
transform. I.e., if a clean-up eh.selector call dominates the invoke of an
_Unwind_Resume_or_Rethrow, then we convert the eh.selector into a
catch-all. This patch, however, uses the DominatorTree information, and doesn't
go through the whole rigmarole of starting at the eh.exception call, finding the
corresponding URoR and eh.selector calls, and trying to trace through any number
of instruction types to get to them.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99846 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/DwarfEHPrepare.cpp

index 5da3171518774f03d1ab596c953f623612fb56ce..1416f5b73719e85f2b055745dd0aa99b3307211c 100644 (file)
@@ -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.