From 2bf84c15d24bb373987d9dbc6308092eac1b8324 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 28 Jul 2011 00:38:23 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136313 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/InlineFunction.cpp | 108 +++++++++++++++++++++--- 1 file changed, 98 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index b2e603354f1..135455e0812 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -250,21 +250,29 @@ namespace { PHINode *InnerSelectorPHI; SmallVector UnwindDestPHIValues; - public: - InvokeInliningInfo(InvokeInst *II) : - OuterUnwindDest(II->getUnwindDest()), OuterSelector(0), - InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0) { + SmallVector 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(I); ++I) { + BasicBlock::iterator I = OuterUnwindDest->begin(); + for (; isa(I); ++I) { // Save the value to use for this edge. PHINode *phi = cast(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(I)) + CallerLPad = LPI; } /// The outer unwind destination is the target of unwind edges @@ -281,15 +289,39 @@ namespace { 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 @@ bool InvokeInliningInfo::forwardEHResume(CallInst *call, BasicBlock *src) { 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::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(CallerLPad->use_back())) { + PHINode *PN = cast(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 @@ static bool HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB, 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(I)) { + Invoke.addCalleeLandingPad(LPI); + continue; + } // We only need to check for function calls: inlined invoke // instructions require no special handling. @@ -557,6 +640,11 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock, // there is now a new entry in them. Invoke.addIncomingPHIValuesFor(BB); } + + if (ResumeInst *RI = dyn_cast(BB->getTerminator())) { + Invoke.mergeLandingPadClauses(RI); + Invoke.forwardResume(RI); + } } // Now that everything is happy, we have one final detail. The PHI nodes in