aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp88
1 files changed, 56 insertions, 32 deletions
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index 8eda3e0b0d..5cba7ee823 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -250,24 +250,29 @@ namespace {
PHINode *InnerSelectorPHI;
SmallVector<Value*, 8> UnwindDestPHIValues;
- PHINode *InnerEHValuesPHI;
+ // New EH:
+ BasicBlock *OuterResumeDest;
+ BasicBlock *InnerResumeDest;
LandingPadInst *CallerLPad;
+ PHINode *InnerEHValuesPHI;
BasicBlock *SplitLPad;
public:
InvokeInliningInfo(InvokeInst *II)
: OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0),
- InnerEHValuesPHI(0), CallerLPad(0), SplitLPad(0) {
+
+ OuterResumeDest(II->getUnwindDest()), InnerResumeDest(0),
+ CallerLPad(0), InnerEHValuesPHI(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();
+ llvm::BasicBlock *InvokeBB = II->getParent();
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));
+ PHINode *PHI = cast<PHINode>(I);
+ UnwindDestPHIValues.push_back(PHI->getIncomingValueForBlock(InvokeBB));
}
// FIXME: With the new EH, this if/dyn_cast should be a 'cast'.
@@ -288,6 +293,7 @@ namespace {
}
BasicBlock *getInnerUnwindDest();
+ BasicBlock *getInnerUnwindDest_new();
LandingPadInst *getLandingPadInst() const { return CallerLPad; }
BasicBlock *getSplitLandingPad() {
@@ -316,8 +322,8 @@ namespace {
void addIncomingPHIValuesForInto(BasicBlock *src, BasicBlock *dest) const {
BasicBlock::iterator I = dest->begin();
for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
- PHINode *phi = cast<PHINode>(I);
- phi->addIncoming(UnwindDestPHIValues[i], src);
+ PHINode *PHI = cast<PHINode>(I);
+ PHI->addIncoming(UnwindDestPHIValues[i], src);
}
}
};
@@ -427,38 +433,56 @@ bool InvokeInliningInfo::forwardEHResume(CallInst *call, BasicBlock *src) {
return true;
}
+/// Get or create a target for the branch from ResumeInsts.
+BasicBlock *InvokeInliningInfo::getInnerUnwindDest_new() {
+ if (InnerResumeDest) return InnerResumeDest;
+
+ // Split the landing pad.
+ BasicBlock::iterator SplitPoint = CallerLPad; ++SplitPoint;
+ InnerResumeDest =
+ OuterResumeDest->splitBasicBlock(SplitPoint,
+ OuterResumeDest->getName() + ".body");
+
+ // The number of incoming edges we expect to the inner landing pad.
+ const unsigned PHICapacity = 2;
+
+ // Create corresponding new PHIs for all the PHIs in the outer landing pad.
+ BasicBlock::iterator InsertPoint = InnerResumeDest->begin();
+ BasicBlock::iterator I = OuterResumeDest->begin();
+ for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
+ PHINode *OuterPHI = cast<PHINode>(I);
+ PHINode *InnerPHI = PHINode::Create(OuterPHI->getType(), PHICapacity,
+ OuterPHI->getName() + ".lpad-body",
+ InsertPoint);
+ OuterPHI->replaceAllUsesWith(InnerPHI);
+ InnerPHI->addIncoming(OuterPHI, OuterResumeDest);
+ }
+
+ // Create a PHI for the exception values.
+ InnerEHValuesPHI = PHINode::Create(CallerLPad->getType(), PHICapacity,
+ "eh.lpad-body", InsertPoint);
+ CallerLPad->replaceAllUsesWith(InnerEHValuesPHI);
+ InnerEHValuesPHI->addIncoming(CallerLPad, OuterResumeDest);
+
+ // All done.
+ return InnerResumeDest;
+}
+
/// 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);
- }
+ BasicBlock *Dest = getInnerUnwindDest_new();
+ BasicBlock *Src = RI->getParent();
- RI->eraseFromParent();
- return;
- }
+ BranchInst::Create(Dest, Src);
+
+ // Update the PHIs in the destination. They were inserted in an order which
+ // makes this work.
+ addIncomingPHIValuesForInto(Src, Dest);
- BranchInst::Create(LPadBB, RI->getParent());
- CallerLPad->replaceAllUsesWith(ResumeOp);
- CallerLPad->eraseFromParent();
+ InnerEHValuesPHI->addIncoming(RI->getOperand(0), Src);
RI->eraseFromParent();
}