1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 11:42:57 +01:00

Add inlining for the new EH scheme.

This builds off of the current scheme, but instead of llvm.eh.exception and
llvm.eh.selector, it uses the landingpad instruction. And instead of
llvm.eh.resume, it uses the resume instruction.

Because of the invariants in the landing pad instruction, a lot of code that's
currently needed to find the appropriate intrinsic calls for an invoke
instruction won't be needed once we go to the new EH scheme. The "FIXME"s tell
us what to remove after we switch.

llvm-svn: 137576
This commit is contained in:
Bill Wendling 2011-08-14 08:01:36 +00:00
parent e020632f7e
commit e4ea267524

View File

@ -45,6 +45,9 @@ bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI) {
return InlineFunction(CallSite(II), IFI); return InlineFunction(CallSite(II), IFI);
} }
// FIXME: New EH - Remove the functions marked [LIBUNWIND] when new EH is
// turned on.
/// [LIBUNWIND] Look for an llvm.eh.exception call in the given block. /// [LIBUNWIND] Look for an llvm.eh.exception call in the given block.
static EHExceptionInst *findExceptionInBlock(BasicBlock *bb) { static EHExceptionInst *findExceptionInBlock(BasicBlock *bb) {
for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; i++) { for (BasicBlock::iterator i = bb->begin(), e = bb->end(); i != e; i++) {
@ -250,20 +253,32 @@ namespace {
PHINode *InnerSelectorPHI; PHINode *InnerSelectorPHI;
SmallVector<Value*, 8> UnwindDestPHIValues; SmallVector<Value*, 8> UnwindDestPHIValues;
public: // FIXME: New EH - These will replace the analogous ones above.
InvokeInliningInfo(InvokeInst *II) : BasicBlock *OuterResumeDest; //< Destination of the invoke's unwind.
OuterUnwindDest(II->getUnwindDest()), OuterSelector(0), BasicBlock *InnerResumeDest; //< Destination for the callee's resume.
InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0) { LandingPadInst *CallerLPad; //< LandingPadInst associated with the invoke.
PHINode *InnerEHValuesPHI; //< PHI for EH values from landingpad insts.
// If there are PHI nodes in the unwind destination block, we public:
// need to keep track of which values came into them from the InvokeInliningInfo(InvokeInst *II)
// invoke before removing the edge from this block. : OuterUnwindDest(II->getUnwindDest()), OuterSelector(0),
llvm::BasicBlock *invokeBB = II->getParent(); InnerUnwindDest(0), InnerExceptionPHI(0), InnerSelectorPHI(0),
for (BasicBlock::iterator I = OuterUnwindDest->begin(); OuterResumeDest(II->getUnwindDest()), InnerResumeDest(0),
isa<PHINode>(I); ++I) { CallerLPad(0), InnerEHValuesPHI(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();
BasicBlock::iterator I = OuterUnwindDest->begin();
for (; isa<PHINode>(I); ++I) {
// Save the value to use for this edge. // Save the value to use for this edge.
PHINode *phi = cast<PHINode>(I); PHINode *PHI = cast<PHINode>(I);
UnwindDestPHIValues.push_back(phi->getIncomingValueForBlock(invokeBB)); 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;
} }
} }
@ -281,11 +296,23 @@ namespace {
BasicBlock *getInnerUnwindDest(); BasicBlock *getInnerUnwindDest();
// FIXME: New EH - Rename when new EH is turned on.
BasicBlock *getInnerUnwindDestNewEH();
LandingPadInst *getLandingPadInst() const { return CallerLPad; }
bool forwardEHResume(CallInst *call, BasicBlock *src); bool forwardEHResume(CallInst *call, BasicBlock *src);
/// Add incoming-PHI values to the unwind destination block for /// forwardResume - Forward the 'resume' instruction to the caller's landing
/// the given basic block, using the values for the original /// pad block. When the landing pad block has only one predecessor, this is
/// invoke's source block. /// 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);
/// 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 { void addIncomingPHIValuesFor(BasicBlock *BB) const {
addIncomingPHIValuesForInto(BB, OuterUnwindDest); addIncomingPHIValuesForInto(BB, OuterUnwindDest);
} }
@ -300,7 +327,7 @@ namespace {
}; };
} }
/// Get or create a target for the branch out of rewritten calls to /// [LIBUNWIND] Get or create a target for the branch out of rewritten calls to
/// llvm.eh.resume. /// llvm.eh.resume.
BasicBlock *InvokeInliningInfo::getInnerUnwindDest() { BasicBlock *InvokeInliningInfo::getInnerUnwindDest() {
if (InnerUnwindDest) return InnerUnwindDest; if (InnerUnwindDest) return InnerUnwindDest;
@ -404,6 +431,60 @@ bool InvokeInliningInfo::forwardEHResume(CallInst *call, BasicBlock *src) {
return true; return true;
} }
/// Get or create a target for the branch from ResumeInsts.
BasicBlock *InvokeInliningInfo::getInnerUnwindDestNewEH() {
// FIXME: New EH - rename this function when new EH is turned on.
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 *Dest = getInnerUnwindDestNewEH();
BasicBlock *Src = RI->getParent();
BranchInst::Create(Dest, Src);
// Update the PHIs in the destination. They were inserted in an order which
// makes this work.
addIncomingPHIValuesForInto(Src, Dest);
InnerEHValuesPHI->addIncoming(RI->getOperand(0), Src);
RI->eraseFromParent();
}
/// [LIBUNWIND] Check whether this selector is "only cleanups": /// [LIBUNWIND] Check whether this selector is "only cleanups":
/// call i32 @llvm.eh.selector(blah, blah, i32 0) /// call i32 @llvm.eh.selector(blah, blah, i32 0)
static bool isCleanupOnlySelector(EHSelectorInst *selector) { static bool isCleanupOnlySelector(EHSelectorInst *selector) {
@ -421,9 +502,19 @@ static bool isCleanupOnlySelector(EHSelectorInst *selector) {
/// Returns true to indicate that the next block should be skipped. /// Returns true to indicate that the next block should be skipped.
static bool HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB, static bool HandleCallsInBlockInlinedThroughInvoke(BasicBlock *BB,
InvokeInliningInfo &Invoke) { InvokeInliningInfo &Invoke) {
LandingPadInst *LPI = Invoke.getLandingPadInst();
for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) { for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E; ) {
Instruction *I = BBI++; Instruction *I = BBI++;
if (LPI) // FIXME: New EH - This won't be NULL in the new EH.
if (LandingPadInst *L = dyn_cast<LandingPadInst>(I)) {
unsigned NumClauses = LPI->getNumClauses();
L->reserveClauses(NumClauses);
for (unsigned i = 0; i != NumClauses; ++i)
L->addClause(LPI->getClause(i));
}
// We only need to check for function calls: inlined invoke // We only need to check for function calls: inlined invoke
// instructions require no special handling. // instructions require no special handling.
CallInst *CI = dyn_cast<CallInst>(I); CallInst *CI = dyn_cast<CallInst>(I);
@ -557,6 +648,10 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
// there is now a new entry in them. // there is now a new entry in them.
Invoke.addIncomingPHIValuesFor(BB); Invoke.addIncomingPHIValuesFor(BB);
} }
if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator())) {
Invoke.forwardResume(RI);
}
} }
// Now that everything is happy, we have one final detail. The PHI nodes in // Now that everything is happy, we have one final detail. The PHI nodes in
@ -829,6 +924,40 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI) {
return false; return false;
} }
// Find the personality function used by the landing pads of the caller. If it
// exists, then check to see that it matches the personality function used in
// the callee.
for (Function::const_iterator
I = Caller->begin(), E = Caller->end(); I != E; ++I)
if (const InvokeInst *II = dyn_cast<InvokeInst>(I->getTerminator())) {
const BasicBlock *BB = II->getUnwindDest();
// FIXME: This 'isa' here should become go away once the new EH system is
// in place.
if (!isa<LandingPadInst>(BB->getFirstNonPHI()))
continue;
const LandingPadInst *LP = cast<LandingPadInst>(BB->getFirstNonPHI());
const Value *CallerPersFn = LP->getPersonalityFn();
// If the personality functions match, then we can perform the
// inlining. Otherwise, we can't inline.
// TODO: This isn't 100% true. Some personality functions are proper
// supersets of others and can be used in place of the other.
for (Function::const_iterator
I = CalledFunc->begin(), E = CalledFunc->end(); I != E; ++I)
if (const InvokeInst *II = dyn_cast<InvokeInst>(I->getTerminator())) {
const BasicBlock *BB = II->getUnwindDest();
// FIXME: This 'if/dyn_cast' here should become a normal 'cast' once
// the new EH system is in place.
if (const LandingPadInst *LP =
dyn_cast<LandingPadInst>(BB->getFirstNonPHI()))
if (CallerPersFn != LP->getPersonalityFn())
return false;
break;
}
break;
}
// Get an iterator to the last basic block in the function, which will have // Get an iterator to the last basic block in the function, which will have
// the new function inlined after it. // the new function inlined after it.
// //