Newer
Older
//===- InlineCommon.cpp - Code common to all inliners ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This file implements the mechanics required to implement inlining without
// missing any calls and updating the call graph. The decisions of which calls
// are profitable to inline are implemented elsewhere.
//
//===----------------------------------------------------------------------===//
#include "Inliner.h"
Chris Lattner
committed
#include "llvm/Constants.h" // ConstantPointerRef should die
#include "llvm/Module.h"
#include "llvm/iOther.h"
#include "llvm/iTerminators.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "Support/CommandLine.h"
#include "Support/Debug.h"
#include "Support/Statistic.h"
#include <set>
namespace {
Statistic<> NumInlined("inline", "Number of functions inlined");
Statistic<> NumDeleted("inline", "Number of functions deleted because all callers found");
cl::opt<unsigned> // FIXME: 200 is VERY conservative
InlineLimit("inline-threshold", cl::Hidden, cl::init(200),
cl::desc("Control the amount of inlining to perform (default = 200)"));
}
Inliner::Inliner() : InlineThreshold(InlineLimit) {}
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// InlineCallIfPossible - If it is possible to inline the specified call site,
// do so and update the CallGraph for this operation.
static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
const std::set<Function*> &SCCFunctions) {
Function *Caller = CS.getInstruction()->getParent()->getParent();
Function *Callee = CS.getCalledFunction();
if (!InlineFunction(CS)) return false;
// Update the call graph by deleting the edge from Callee to Caller
CallGraphNode *CalleeNode = CG[Callee];
CallGraphNode *CallerNode = CG[Caller];
CallerNode->removeCallEdgeTo(CalleeNode);
// Since we inlined all uninlined call sites in the callee into the caller,
// add edges from the caller to all of the callees of the callee.
for (CallGraphNode::iterator I = CalleeNode->begin(),
E = CalleeNode->end(); I != E; ++I)
CallerNode->addCalledFunction(*I);
// If we inlined the last possible call site to the function,
// delete the function body now.
if (Callee->use_empty() && Callee->hasInternalLinkage() &&
!SCCFunctions.count(Callee)) {
DEBUG(std::cerr << " -> Deleting dead function: "
<< Callee->getName() << "\n");
// Remove any call graph edges from the callee to its callees.
while (CalleeNode->begin() != CalleeNode->end())
CalleeNode->removeCallEdgeTo(*(CalleeNode->end()-1));
// Removing the node for callee from the call graph and delete it.
delete CG.removeFunctionFromModule(CalleeNode);
++NumDeleted;
}
return true;
}
bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
CallGraph &CG = getAnalysis<CallGraph>();
std::set<Function*> SCCFunctions;
DEBUG(std::cerr << "Inliner visiting SCC:");
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
if (F) SCCFunctions.insert(F);
DEBUG(std::cerr << " " << (F ? F->getName() : "INDIRECTNODE"));
// 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
// from inlining other functions.
std::vector<CallSite> CallSites;
for (std::set<Function*>::iterator SCCI = SCCFunctions.begin(),
E = SCCFunctions.end(); SCCI != E; ++SCCI)
if (Function *F = *SCCI)
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
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);
}
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
DEBUG(std::cerr << ": " << CallSites.size() << " call sites.\n");
// Now that we have all of the call sites, move the ones to functions in the
// current SCC to the end of the list.
unsigned FirstCallInSCC = CallSites.size();
for (unsigned i = 0; i < FirstCallInSCC; ++i)
if (Function *F = CallSites[i].getCalledFunction())
if (SCCFunctions.count(F))
std::swap(CallSites[i--], CallSites[--FirstCallInSCC]);
// Now that we have all of the call sites, loop over them and inline them if
// it looks profitable to do so.
bool Changed = false;
bool LocalChange;
do {
LocalChange = false;
// Iterate over the outer loop because inlining functions can cause indirect
// calls to become direct calls.
for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi)
if (Function *Callee = CallSites[CSi].getCalledFunction()) {
// Calls to external functions are never inlinable.
if (Callee->isExternal() ||
CallSites[CSi].getInstruction()->getParent()->getParent() ==Callee){
std::swap(CallSites[CSi], CallSites.back());
--CSi;
continue;
}
// If the policy determines that we should inline this function,
// try to do so.
CallSite CS = CallSites[CSi];
int InlineCost = 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();
// Attempt to inline the function...
if (InlineCallIfPossible(CS, CG, SCCFunctions)) {
// Remove this call site from the list.
std::swap(CallSites[CSi], CallSites.back());
CallSites.pop_back();
--CSi;
++NumInlined;
Changed = true;
LocalChange = true;
Chris Lattner
committed
}
} while (LocalChange);
Chris Lattner
committed
return Changed;
Chris Lattner
committed
// doFinalization - Remove now-dead linkonce functions at the end of
// processing to avoid breaking the SCC traversal.
bool Inliner::doFinalization(CallGraph &CG) {
Chris Lattner
committed
std::set<CallGraphNode*> FunctionsToRemove;
// Scan for all of the functions, looking for ones that should now be removed
// from the program. Insert the dead ones in the FunctionsToRemove set.
for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
CallGraphNode *CGN = I->second;
Chris Lattner
committed
Function *F = CGN ? CGN->getFunction() : 0;
Chris Lattner
committed
// If the only remaining use of the function is a dead constant
// pointer ref, remove it.
if (F && F->hasOneUse())
if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(F->use_back()))
if (CPR->use_empty()) {
CPR->destroyConstant();
if (F->hasInternalLinkage()) {
// There *MAY* be an edge from the external call node to this
// function. If so, remove it.
CallGraphNode *EN = CG.getExternalCallingNode();
CallGraphNode::iterator I = std::find(EN->begin(), EN->end(), CGN);
if (I != EN->end()) EN->removeCallEdgeTo(CGN);
}
}
Chris Lattner
committed
if (F && (F->hasLinkOnceLinkage() || F->hasInternalLinkage()) &&
F->use_empty()) {
Chris Lattner
committed
// Remove any call graph edges from the function to its callees.
Chris Lattner
committed
while (CGN->begin() != CGN->end())
CGN->removeCallEdgeTo(*(CGN->end()-1));
Chris Lattner
committed
// If the function has external linkage (basically if it's a linkonce
// function) remove the edge from the external node to the callee node.
Chris Lattner
committed
if (!F->hasInternalLinkage())
CG.getExternalCallingNode()->removeCallEdgeTo(CGN);
// Removing the node for callee from the call graph and delete it.
Chris Lattner
committed
FunctionsToRemove.insert(CGN);
Chris Lattner
committed
}
}
Chris Lattner
committed
// Now that we know which functions to delete, do so. We didn't want to do
// this inline, because that would invalidate our CallGraph::iterator
// objects. :(
bool Changed = false;
for (std::set<CallGraphNode*>::iterator I = FunctionsToRemove.begin(),
E = FunctionsToRemove.end(); I != E; ++I) {
delete CG.removeFunctionFromModule(*I);
++NumDeleted;
Changed = true;
}
Chris Lattner
committed
return Changed;
}