summaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/IPO')
-rw-r--r--lib/Transforms/IPO/InlineSimple.cpp8
-rw-r--r--lib/Transforms/IPO/Inliner.cpp125
-rw-r--r--lib/Transforms/IPO/Inliner.h6
3 files changed, 55 insertions, 84 deletions
diff --git a/lib/Transforms/IPO/InlineSimple.cpp b/lib/Transforms/IPO/InlineSimple.cpp
index 0c950c7ba3..c0d97c5515 100644
--- a/lib/Transforms/IPO/InlineSimple.cpp
+++ b/lib/Transforms/IPO/InlineSimple.cpp
@@ -217,13 +217,7 @@ int SimpleInliner::getInlineCost(CallSite CS) {
// Don't inline into something too big, which would make it bigger. Here, we
// count each basic block as a single unit.
//
- // FIXME: THIS IS A TOTAL HACK. The problem is that we don't keep track of
- // which call sites are the result of an inlining operation. Because of this,
- // if we inline a recursive function into a callee, we will see a new call to
- // the recursive function. Every time we inline we get a new callsite for the
- // function, which only stops when the caller reaches its inlining limit.
- // Until the real problem is fixed, we apply this gnasty hack.
- InlineCost += Caller->size();
+ InlineCost += Caller->size()/20;
// Look at the size of the callee. Each basic block counts as 20 units, and
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index c0861f1b67..325631a792 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -58,84 +58,67 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
if (F == 0 || F->isExternal()) continue;
DEBUG(std::cerr << " Inspecting function: " << F->getName() << "\n");
+ // Scan through and identify all call sites ahead of time so that we only
+ // inline call sites in the original functions, not call sites that result
+ // in inlining other functions.
+ std::vector<CallSite> CallSites;
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
- for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ) {
- bool ShouldInc = true;
- // Found a call or invoke instruction?
- if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
- CallSite CS = CallSite::get(I);
- if (Function *Callee = CS.getCalledFunction())
- if (!Callee->isExternal() && !IsRecursiveFunction.count(Callee)) {
- // Determine whether this is a function IN the SCC...
- bool inSCC = SCCFunctions.count(Callee);
+ for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
+ CallSite CS = CallSite::get(I);
+ if (CS.getInstruction() && CS.getCalledFunction() &&
+ !CS.getCalledFunction()->isExternal())
+ CallSites.push_back(CS);
+ }
- // Keep track of whether this is a directly recursive function.
- if (Callee == F) IsRecursiveFunction.insert(F);
+ // Now that we have all of the call sites, loop over them and inline them if
+ // it looks profitable to do so.
+ for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
+ CallSite CS = CallSites[i];
+ Function *Callee = CS.getCalledFunction();
+ // Determine whether this is a function IN the SCC...
+ bool inSCC = SCCFunctions.count(Callee);
+
+ // If the policy determines that we should inline this function,
+ // try to do so...
+ int InlineCost = inSCC ? getRecursiveInlineCost(CS) : getInlineCost(CS);
+ if (InlineCost >= (int)InlineThreshold) {
+ DEBUG(std::cerr << " NOT Inlining: cost=" << InlineCost
+ << ", Call: " << *CS.getInstruction());
+ } else {
+ DEBUG(std::cerr << " Inlining: cost=" << InlineCost
+ << ", Call: " << *CS.getInstruction());
+
+ Function *Caller = CS.getInstruction()->getParent()->getParent();
- // If the policy determines that we should inline this function,
- // try to do so...
- int InlineCost = inSCC ? getRecursiveInlineCost(CS) :
- getInlineCost(CS);
- if (InlineCost >= (int)InlineThreshold) {
- DEBUG(std::cerr << " NOT Inlining: cost=" << InlineCost
- << ", Call: " << *CS.getInstruction());
- } else {
- DEBUG(std::cerr << " Inlining: cost=" << InlineCost
- << ", Call: " << *CS.getInstruction());
+ // Attempt to inline the function...
+ if (InlineFunction(CS)) {
+ ++NumInlined;
+
+ if (Callee->hasOneUse())
+ if (ConstantPointerRef *CPR =
+ dyn_cast<ConstantPointerRef>(Callee->use_back()))
+ if (CPR->use_empty())
+ CPR->destroyConstant();
+
+ // If we inlined the last possible call site to the function,
+ // delete the function body now.
+ if (Callee->use_empty() && Callee != Caller &&
+ (Callee->hasInternalLinkage() || Callee->hasLinkOnceLinkage())) {
+ DEBUG(std::cerr << " -> Deleting dead function: "
+ << (void*)Callee << Callee->getName() << "\n");
+ std::set<Function*>::iterator I = SCCFunctions.find(Callee);
+ if (I != SCCFunctions.end()) // Remove function from this SCC.
+ SCCFunctions.erase(I);
- // Save an iterator to the instruction before the call if it
- // exists, otherwise get an iterator at the end of the
- // block... because the call will be destroyed.
- //
- BasicBlock::iterator SI;
- if (I != BB->begin()) {
- SI = I; --SI; // Instruction before the call...
- } else {
- SI = BB->end();
- }
-
- if (performInlining(CS, SCCFunctions)) {
- // Move to instruction before the call...
- I = (SI == BB->end()) ? BB->begin() : SI;
- ShouldInc = false; // Don't increment iterator until next time
- Changed = true;
- }
- }
- }
+ Callee->getParent()->getFunctionList().erase(Callee);
+ ++NumDeleted;
+ }
+ Changed = true;
}
- if (ShouldInc) ++I;
}
+ }
}
- return Changed;
-}
-
-bool Inliner::performInlining(CallSite CS, std::set<Function*> &SCC) {
- Function *Callee = CS.getCalledFunction();
- Function *Caller = CS.getInstruction()->getParent()->getParent();
- // Attempt to inline the function...
- if (!InlineFunction(CS)) return false;
- ++NumInlined;
-
- if (Callee->hasOneUse())
- if (ConstantPointerRef *CPR =
- dyn_cast<ConstantPointerRef>(Callee->use_back()))
- if (CPR->use_empty())
- CPR->destroyConstant();
-
- // If we inlined the last possible call site to the function,
- // delete the function body now.
- if (Callee->use_empty() && Callee != Caller &&
- (Callee->hasInternalLinkage() || Callee->hasLinkOnceLinkage())) {
- DEBUG(std::cerr << " -> Deleting dead function: " << (void*)Callee
- << Callee->getName() << "\n");
- std::set<Function*>::iterator I = SCC.find(Callee);
- if (I != SCC.end()) // Remove function from this SCC...
- SCC.erase(I);
-
- Callee->getParent()->getFunctionList().erase(Callee);
- ++NumDeleted;
- }
- return true;
+ return Changed;
}
diff --git a/lib/Transforms/IPO/Inliner.h b/lib/Transforms/IPO/Inliner.h
index 805876c54d..b63fe2ac05 100644
--- a/lib/Transforms/IPO/Inliner.h
+++ b/lib/Transforms/IPO/Inliner.h
@@ -56,12 +56,6 @@ struct Inliner : public CallGraphSCCPass {
private:
// InlineThreshold - Cache the value here for easy access.
unsigned InlineThreshold;
-
- // IsRecursiveFunction - This contains all functions which are directly
- // recursive, which we do NOT want to inline into other functions.
- std::set<Function*> IsRecursiveFunction;
-
- bool performInlining(CallSite CS, std::set<Function*> &SCC);
};
} // End llvm namespace