aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2013-03-21 23:30:12 +0000
committerBill Wendling <isanbard@gmail.com>2013-03-21 23:30:12 +0000
commitd9ff8c83d137586d8c06f98bdf8adbf0d1fa79ca (patch)
tree9eb3d25e40b034c95a8d90282c7be11e010510e7
parent3ea1b064a0b9c3d161b0f77a9e957970f98907ab (diff)
Always forward 'resume' instructions to the outter landing pad.
How did this ever work? Basically, if you have a function that's inlined into the caller, it may not have any 'call' instructions, but any 'resume' instructions it may have should still be forwarded to the outer (caller's) landing pad. This requires that all of the 'landingpad' instructions in the callee have their clauses merged with the caller's outer 'landingpad' instruction (hence the bit of ugly code in the `forwardResume' method). Testcase in a follow commit to the test-suite repository. <rdar://problem/13360379> & PR15555 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177680 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp55
1 files changed, 39 insertions, 16 deletions
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index 0d2598a221..3e1022ef8c 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -82,7 +82,7 @@ namespace {
/// 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);
+ void forwardResume(ResumeInst *RI, BasicBlock *FirstNewBlock);
/// addIncomingPHIValuesFor - Add incoming-PHI values to the unwind
/// destination block for the given basic block, using the values for the
@@ -140,8 +140,10 @@ BasicBlock *InvokeInliningInfo::getInnerResumeDest() {
/// 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) {
+void InvokeInliningInfo::forwardResume(ResumeInst *RI,
+ BasicBlock *FirstNewBlock) {
BasicBlock *Dest = getInnerResumeDest();
+ LandingPadInst *OuterLPad = getLandingPadInst();
BasicBlock *Src = RI->getParent();
BranchInst::Create(Dest, Src);
@@ -152,6 +154,36 @@ void InvokeInliningInfo::forwardResume(ResumeInst *RI) {
InnerEHValuesPHI->addIncoming(RI->getOperand(0), Src);
RI->eraseFromParent();
+
+ // Get all of the inlined landing pad instructions.
+ SmallPtrSet<LandingPadInst*, 16> InlinedLPads;
+ Function *Caller = FirstNewBlock->getParent();
+ for (Function::iterator I = FirstNewBlock, E = Caller->end(); I != E; ++I)
+ if (InvokeInst *II = dyn_cast<InvokeInst>(I->getTerminator())) {
+ LandingPadInst *LPI = II->getLandingPadInst();
+ if (!LPI->hasCatchAll())
+ InlinedLPads.insert(LPI);
+ }
+
+ // Merge the catch clauses from the outer landing pad instruction into the
+ // inlined landing pad instructions.
+ for (SmallPtrSet<LandingPadInst*, 16>::iterator I = InlinedLPads.begin(),
+ E = InlinedLPads.end(); I != E; ++I) {
+ LandingPadInst *InlinedLPad = *I;
+ for (unsigned OuterIdx = 0, OuterNum = OuterLPad->getNumClauses();
+ OuterIdx != OuterNum; ++OuterIdx) {
+ bool hasClause = false;
+ if (OuterLPad->isFilter(OuterIdx)) continue;
+ Value *OuterClause = OuterLPad->getClause(OuterIdx);
+ for (unsigned Idx = 0, N = InlinedLPad->getNumClauses(); Idx != N; ++Idx)
+ if (OuterClause == InlinedLPad->getClause(Idx)) {
+ hasClause = true;
+ break;
+ }
+ if (!hasClause)
+ InlinedLPad->addClause(OuterClause);
+ }
+ }
}
/// HandleCallsInBlockInlinedThroughInvoke - When we inline a basic block into
@@ -229,19 +261,9 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
// The inlined code is currently at the end of the function, scan from the
// start of the inlined code to its end, checking for stuff we need to
- // rewrite. If the code doesn't have calls or unwinds, we know there is
- // nothing to rewrite.
- if (!InlinedCodeInfo.ContainsCalls) {
- // Now that everything is happy, we have one final detail. The PHI nodes in
- // the exception destination block still have entries due to the original
- // invoke instruction. Eliminate these entries (which might even delete the
- // PHI node) now.
- InvokeDest->removePredecessor(II->getParent());
- return;
- }
-
+ // rewrite.
InvokeInliningInfo Invoke(II);
-
+
for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB){
if (InlinedCodeInfo.ContainsCalls)
if (HandleCallsInBlockInlinedThroughInvoke(BB, Invoke)) {
@@ -250,13 +272,14 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
continue;
}
+ // Forward any resumes that are remaining here.
if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator()))
- Invoke.forwardResume(RI);
+ Invoke.forwardResume(RI, FirstNewBlock);
}
// Now that everything is happy, we have one final detail. The PHI nodes in
// the exception destination block still have entries due to the original
- // invoke instruction. Eliminate these entries (which might even delete the
+ // invoke instruction. Eliminate these entries (which might even delete the
// PHI node) now.
InvokeDest->removePredecessor(II->getParent());
}