[llvm-commits] [llvm] r136313 - /llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp

Bill Wendling isanbard at gmail.com
Wed Jul 27 17:38:23 PDT 2011


Author: void
Date: Wed Jul 27 19:38:23 2011
New Revision: 136313

URL: http://llvm.org/viewvc/llvm-project?rev=136313&view=rev
Log:
Initial stab at getting inlining working with the EH rewrite.

This takes the new 'resume' instruction and turns it into a direct jump to the
caller's landing pad code. The caller's landingpad instruction is merged with
the landingpad instructions of the callee. This is a bit rough and makes some
assumptions in how the code works. But it passes a simple test.

Modified:
    llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp

Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=136313&r1=136312&r2=136313&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Wed Jul 27 19:38:23 2011
@@ -250,21 +250,29 @@
     PHINode *InnerSelectorPHI;
     SmallVector<Value*, 8> UnwindDestPHIValues;
 
-  public:
-    InvokeInliningInfo(InvokeInst *II) :
-      OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
-      InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0) {
+    SmallVector<LandingPadInst*, 16> CalleeLPads;
+    LandingPadInst *CallerLPad;
+    BasicBlock *SplitLPad;
 
+  public:
+    InvokeInliningInfo(InvokeInst *II)
+      : OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
+        InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0),
+        CallerLPad(0), SplitLPad(0) {
       // If there are PHI nodes in the unwind destination block, we
       // need to keep track of which values came into them from the
       // invoke before removing the edge from this block.
       llvm::BasicBlock *invokeBB = II->getParent();
-      for (BasicBlock::iterator I = OuterUnwindDest->begin();
-             isa<PHINode>(I); ++I) {
+      BasicBlock::iterator I = OuterUnwindDest->begin();
+      for (; isa<PHINode>(I); ++I) {
         // Save the value to use for this edge.
         PHINode *phi = cast<PHINode>(I);
         UnwindDestPHIValues.push_back(phi->getIncomingValueForBlock(invokeBB));
       }
+
+      // FIXME: With the new EH, this if/dyn_cast should be a 'cast'.
+      if (LandingPadInst *LPI = dyn_cast<LandingPadInst>(I))
+        CallerLPad = LPI;
     }
 
     /// The outer unwind destination is the target of unwind edges
@@ -281,15 +289,39 @@
 
     BasicBlock *getInnerUnwindDest();
 
+    void addCalleeLandingPad(LandingPadInst *LPI) {
+      CalleeLPads.push_back(LPI);
+    }
+
+    LandingPadInst *getLandingPadInst() const { return CallerLPad; }
+    BasicBlock *getSplitLandingPad() {
+      if (SplitLPad) return SplitLPad;
+      assert(CallerLPad && "Trying to split a block that isn't a landing pad!");
+      BasicBlock::iterator I = CallerLPad; ++I;
+      SplitLPad = CallerLPad->getParent()->splitBasicBlock(I, "split.lpad");
+      return SplitLPad;
+    }
+
     bool forwardEHResume(CallInst *call, BasicBlock *src);
 
-    /// Add incoming-PHI values to the unwind destination block for
-    /// the given basic block, using the values for the original
-    /// invoke's source block.
+    /// forwardResume - Forward the 'resume' instruction to the caller's landing
+    /// pad block. When the landing pad block has only one predecessor, this is
+    /// a simple branch. When there is more than one predecessor, we need to
+    /// split the landing pad block after the landingpad instruction and jump
+    /// to there.
+    void forwardResume(ResumeInst *RI);
+
+    /// mergeLandingPadClauses - Visit all of the landing pad instructions which
+    /// supply the value for the ResumeInst, and merge the clauses from the new
+    /// destination (the caller's landing pad).
+    void mergeLandingPadClauses(ResumeInst *RI);
+
+    /// addIncomingPHIValuesFor - Add incoming-PHI values to the unwind
+    /// destination block for the given basic block, using the values for the
+    /// original invoke's source block.
     void addIncomingPHIValuesFor(BasicBlock *BB) const {
       addIncomingPHIValuesForInto(BB, OuterUnwindDest);
     }
-
     void addIncomingPHIValuesForInto(BasicBlock *src, BasicBlock *dest) const {
       BasicBlock::iterator I = dest->begin();
       for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
@@ -404,6 +436,51 @@
   return true;
 }
 
+/// mergeLandingPadClauses - Visit all of the landing pad instructions merge the
+/// clauses from the new destination (the caller's landing pad).
+void InvokeInliningInfo::mergeLandingPadClauses(ResumeInst *RI) {
+  for (SmallVectorImpl<LandingPadInst*>::iterator
+         I = CalleeLPads.begin(), E = CalleeLPads.end(); I != E; ++I)
+    for (unsigned i = 0, e = CallerLPad->getNumClauses(); i != e; ++i)
+      (*I)->addClause(CallerLPad->getClauseType(i),
+                      CallerLPad->getClauseValue(i));
+}
+
+/// forwardResume - Forward the 'resume' instruction to the caller's landing pad
+/// block. When the landing pad block has only one predecessor, this is a simple
+/// branch. When there is more than one predecessor, we need to split the
+/// landing pad block after the landingpad instruction and jump to there.
+void InvokeInliningInfo::forwardResume(ResumeInst *RI) {
+  BasicBlock *LPadBB = CallerLPad->getParent();
+  Value *ResumeOp = RI->getOperand(0);
+
+  if (!LPadBB->getSinglePredecessor()) {
+    // There are multiple predecessors to this landing pad block. Split this
+    // landing pad block and jump to the new BB.
+    BasicBlock *SplitLPad = getSplitLandingPad();
+    BranchInst::Create(SplitLPad, RI->getParent());
+
+    if (CallerLPad->hasOneUse() && isa<PHINode>(CallerLPad->use_back())) {
+      PHINode *PN = cast<PHINode>(CallerLPad->use_back());
+      PN->addIncoming(ResumeOp, RI->getParent());
+    } else {
+      PHINode *PN = PHINode::Create(ResumeOp->getType(), 0, "lpad.phi",
+                                    &SplitLPad->front());
+      CallerLPad->replaceAllUsesWith(PN);
+      PN->addIncoming(ResumeOp, RI->getParent());
+      PN->addIncoming(CallerLPad, LPadBB);
+    }
+
+    RI->eraseFromParent();
+    return;
+  }
+
+  BranchInst::Create(LPadBB, RI->getParent());
+  CallerLPad->replaceAllUsesWith(ResumeOp);
+  CallerLPad->eraseFromParent();
+  RI->eraseFromParent();
+}
+
 /// [LIBUNWIND] Check whether this selector is "only cleanups":
 ///   call i32 @llvm.eh.selector(blah, blah, i32 0)
 static bool isCleanupOnlySelector(EHSelectorInst *selector) {
@@ -423,6 +500,12 @@
                                                    InvokeInliningInfo &Invoke) {
   for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
     Instruction *I = BBI++;
+
+    // Collect the callee's landingpad instructions.
+    if (LandingPadInst *LPI = dyn_cast<LandingPadInst>(I)) {
+      Invoke.addCalleeLandingPad(LPI);
+      continue;
+    }
     
     // We only need to check for function calls: inlined invoke
     // instructions require no special handling.
@@ -557,6 +640,11 @@
       // there is now a new entry in them.
       Invoke.addIncomingPHIValuesFor(BB);
     }
+
+    if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator())) {
+      Invoke.mergeLandingPadClauses(RI);
+      Invoke.forwardResume(RI);
+    }
   }
 
   // Now that everything is happy, we have one final detail.  The PHI nodes in





More information about the llvm-commits mailing list