Revert the aggressive inlining for now, it doesn't handle external correctly

llvm-svn: 31135
This commit is contained in:
Andrew Lenharth 2006-10-23 19:53:37 +00:00
parent 1de8fc671e
commit 0c3211eff0
1 changed files with 78 additions and 112 deletions

View File

@ -41,7 +41,7 @@ namespace {
X("budatastructure", "Bottom-up Data Structure Analysis");
}
static bool GetAllCallees(const DSCallSite &CS,
static bool GetAllCalleesN(const DSCallSite &CS,
std::vector<Function*> &Callees);
/// BuildGlobalECs - Look at all of the nodes in the globals graph. If any node
@ -164,7 +164,6 @@ bool BUDataStructures::runOnModule(Module &M) {
unsigned NextID = 1;
Function *MainFunc = M.getMainFunction();
if (MainFunc)
calculateGraphs(MainFunc, Stack, NextID, ValMap);
@ -216,8 +215,9 @@ bool BUDataStructures::runOnModule(Module &M) {
if (MainFunc && !MainFunc->isExternal()) {
DSGraph &MainGraph = getOrCreateGraph(MainFunc);
const DSGraph &GG = *MainGraph.getGlobalsGraph();
ReachabilityCloner RC(MainGraph, GG, DSGraph::DontCloneCallNodes |
DSGraph::DontCloneAuxCallNodes);
ReachabilityCloner RC(MainGraph, GG,
DSGraph::DontCloneCallNodes |
DSGraph::DontCloneAuxCallNodes);
// Clone the global nodes into this graph.
for (DSScalarMap::global_iterator I = GG.getScalarMap().global_begin(),
@ -232,16 +232,16 @@ bool BUDataStructures::runOnModule(Module &M) {
//Debug messages if along the way we didn't resolve a call site
//also update the call graph and callsites we did find.
for(DSGraph::afc_iterator ii = MainGraph.afc_begin(),
ee = MainGraph.afc_end(); ii != ee; ++ii) {
ee = MainGraph.afc_end(); ii != ee; ++ii) {
std::vector<Function*> Funcs;
GetAllCallees(*ii, Funcs);
GetAllCalleesN(*ii, Funcs);
DEBUG(std::cerr << "Lost site\n");
DEBUG(ii->getCallSite().getInstruction()->dump());
for (std::vector<Function*>::iterator iif = Funcs.begin(), eef = Funcs.end();
iif != eef; ++iif) {
AddGlobalToNode(this, *ii, *iif);
DEBUG(std::cerr << "Adding\n");
ActualCallees.insert(std::make_pair(ii->getCallSite().getInstruction(), *iif));
iif != eef; ++iif) {
AddGlobalToNode(this, *ii, *iif);
DEBUG(std::cerr << "Adding\n");
ActualCallees.insert(std::make_pair(ii->getCallSite().getInstruction(), *iif));
}
}
@ -283,8 +283,27 @@ static bool isResolvableFunc(const Function* callee) {
return !callee->isExternal() || isVAHackFn(callee);
}
static void GetAllCallees(const DSCallSite &CS,
std::vector<Function*> &Callees) {
if (CS.isDirectCall()) {
if (isResolvableFunc(CS.getCalleeFunc()))
Callees.push_back(CS.getCalleeFunc());
} else if (!CS.getCalleeNode()->isIncomplete()) {
// Get all callees.
unsigned OldSize = Callees.size();
CS.getCalleeNode()->addFullFunctionList(Callees);
// If any of the callees are unresolvable, remove the whole batch!
for (unsigned i = OldSize, e = Callees.size(); i != e; ++i)
if (!isResolvableFunc(Callees[i])) {
Callees.erase(Callees.begin()+OldSize, Callees.end());
return;
}
}
}
//returns true if all callees were resolved
static bool GetAllCallees(const DSCallSite &CS,
static bool GetAllCalleesN(const DSCallSite &CS,
std::vector<Function*> &Callees) {
if (CS.isDirectCall()) {
if (isResolvableFunc(CS.getCalleeFunc())) {
@ -321,7 +340,7 @@ static void GetAllAuxCallees(DSGraph &G, std::vector<Function*> &Callees) {
unsigned BUDataStructures::calculateGraphs(Function *F,
std::vector<Function*> &Stack,
unsigned &NextID,
hash_map<Function*, unsigned> &ValMap) {
hash_map<Function*, unsigned> &ValMap) {
assert(!ValMap.count(F) && "Shouldn't revisit functions!");
unsigned Min = NextID++, MyID = Min;
ValMap[F] = Min;
@ -369,7 +388,7 @@ unsigned BUDataStructures::calculateGraphs(Function *F,
Stack.pop_back();
DSGraph &G = getDSGraph(*F);
DEBUG(std::cerr << " [BU] Calculating graph for: " << F->getName()<< "\n");
bool redo = calculateGraph(G);
calculateGraph(G);
DEBUG(std::cerr << " [BU] Done inlining: " << F->getName() << " ["
<< G.getGraphSize() << "+" << G.getAuxFunctionCalls().size()
<< "]\n");
@ -378,7 +397,8 @@ unsigned BUDataStructures::calculateGraphs(Function *F,
// Should we revisit the graph? Only do it if there are now new resolvable
// callees.
if (redo) {
GetAllAuxCallees(Graph, CalleeFunctions);
if (!CalleeFunctions.empty()) {
DEBUG(std::cerr << "Recalculating " << F->getName() << " due to new knowledge\n");
ValMap.erase(F);
return calculateGraphs(F, Stack, NextID, ValMap);
@ -421,7 +441,7 @@ unsigned BUDataStructures::calculateGraphs(Function *F,
Stack.pop_back();
DEBUG(std::cerr << "Calculating graph for SCC #: " << MyID << " of size: "
<< SCCSize << "\n");
<< SCCSize << "\n");
// Compute the Max SCC Size.
if (MaxSCC < SCCSize)
@ -432,14 +452,10 @@ unsigned BUDataStructures::calculateGraphs(Function *F,
// Now that we have one big happy family, resolve all of the call sites in
// the graph...
bool redo = calculateGraph(SCCGraph);
calculateGraph(SCCGraph);
DEBUG(std::cerr << " [BU] Done inlining SCC [" << SCCGraph.getGraphSize()
<< "+" << SCCGraph.getAuxFunctionCalls().size() << "]\n");
if (redo) {
DEBUG(std::cerr << "MISSING REDO\n");
}
DEBUG(std::cerr << "DONE with SCC #: " << MyID << "\n");
// We never have to revisit "SCC" processed functions...
@ -493,8 +509,7 @@ DSGraph &BUDataStructures::CreateGraphForExternalFunction(const Function &Fn) {
return *DSG;
}
bool BUDataStructures::calculateGraph(DSGraph &Graph) {
void BUDataStructures::calculateGraph(DSGraph &Graph) {
// If this graph contains the main function, clone the globals graph into this
// graph before we inline callees and other fun stuff.
bool ContainsMain = false;
@ -530,27 +545,42 @@ bool BUDataStructures::calculateGraph(DSGraph &Graph) {
std::list<DSCallSite> TempFCs;
std::list<DSCallSite> &AuxCallsList = Graph.getAuxFunctionCalls();
TempFCs.swap(AuxCallsList);
//remember what we've seen (or will see)
unsigned oldSize = TempFCs.size();
bool Printed = false;
bool missingNode = false;
std::vector<Function*> CalledFuncs;
while (!TempFCs.empty()) {
DSCallSite &CS = *TempFCs.begin();
Instruction *TheCall = CS.getCallSite().getInstruction();
DSGraph *GI;
CalledFuncs.clear();
// Fast path for noop calls. Note that we don't care about merging globals
// in the callee with nodes in the caller here.
if (CS.isDirectCall()) {
if (!isVAHackFn(CS.getCalleeFunc()) && isResolvableFunc(CS.getCalleeFunc())) {
Function* Callee = CS.getCalleeFunc();
if (CS.getRetVal().isNull() && CS.getNumPtrArgs() == 0) {
TempFCs.erase(TempFCs.begin());
continue;
} else if (CS.isDirectCall() && isVAHackFn(CS.getCalleeFunc())) {
TempFCs.erase(TempFCs.begin());
continue;
}
GetAllCallees(CS, CalledFuncs);
if (CalledFuncs.empty()) {
// Remember that we could not resolve this yet!
AuxCallsList.splice(AuxCallsList.end(), TempFCs, TempFCs.begin());
continue;
} else {
DSGraph *GI;
Instruction *TheCall = CS.getCallSite().getInstruction();
if (CalledFuncs.size() == 1) {
Function *Callee = CalledFuncs[0];
ActualCallees.insert(std::make_pair(TheCall, Callee));
assert(doneDSGraph(Callee) && "Direct calls should always be precomputed");
// Get the data structure graph for the called function.
GI = &getDSGraph(*Callee); // Graph to inline
DEBUG(std::cerr << " Inlining graph for " << Callee->getName());
DEBUG(std::cerr << "[" << GI->getGraphSize() << "+"
<< GI->getAuxFunctionCalls().size() << "] into '"
<< Graph.getFunctionNames() << "' [" << Graph.getGraphSize() <<"+"
@ -559,38 +589,22 @@ bool BUDataStructures::calculateGraph(DSGraph &Graph) {
DSGraph::StripAllocaBit|DSGraph::DontCloneCallNodes);
++NumBUInlines;
} else {
DEBUG(std::cerr << "Graph " << Graph.getFunctionNames() << " Call Site " <<
CS.getCallSite().getInstruction() << " never resolvable\n");
}
--oldSize;
TempFCs.pop_front();
continue;
} else {
std::vector<Function*> CalledFuncs;
bool resolved = GetAllCallees(CS, CalledFuncs);
if (CalledFuncs.empty()) {
DEBUG(std::cerr << "Graph " << Graph.getFunctionNames() << " Call Site " <<
CS.getCallSite().getInstruction() << " delayed\n");
} else {
DEBUG(
if (!Printed)
std::cerr << "In Fns: " << Graph.getFunctionNames() << "\n";
std::cerr << " calls " << CalledFuncs.size()
<< " fns from site: " << CS.getCallSite().getInstruction()
<< " " << *CS.getCallSite().getInstruction();
std::cerr << " Fns =";
);
unsigned NumPrinted = 0;
for (std::vector<Function*>::iterator I = CalledFuncs.begin(),
E = CalledFuncs.end(); I != E; ++I) {
DEBUG(if (NumPrinted++ < 8) std::cerr << " " << (*I)->getName(););
if (NumPrinted++ < 8) std::cerr << " " << (*I)->getName();
// Add the call edges to the call graph.
ActualCallees.insert(std::make_pair(TheCall, *I));
}
DEBUG(std::cerr << "\n");
std::cerr << "\n";
// See if we already computed a graph for this set of callees.
std::sort(CalledFuncs.begin(), CalledFuncs.end());
@ -602,14 +616,6 @@ bool BUDataStructures::calculateGraph(DSGraph &Graph) {
E = CalledFuncs.end();
// Start with a copy of the first graph.
if (!doneDSGraph(*I)) {
AuxCallsList.splice(AuxCallsList.end(), TempFCs, TempFCs.begin());
missingNode = true;
continue;
}
AddGlobalToNode(this, CS, *I);
GI = IndCallGraph.first = new DSGraph(getDSGraph(**I), GlobalECs);
GI->setGlobalsGraph(Graph.getGlobalsGraph());
std::vector<DSNodeHandle> &Args = IndCallGraph.second;
@ -619,17 +625,10 @@ bool BUDataStructures::calculateGraph(DSGraph &Graph) {
GI->getFunctionArgumentsForCall(*I, Args);
// Merge all of the other callees into this graph.
bool locMissing = false;
for (++I; I != E && !locMissing; ++I) {
AddGlobalToNode(this, CS, *I);
for (++I; I != E; ++I) {
// If the graph already contains the nodes for the function, don't
// bother merging it in again.
if (!GI->containsFunction(*I)) {
if (!doneDSGraph(*I)) {
locMissing = true;
break;
}
GI->cloneInto(getDSGraph(**I));
++NumBUInlines;
}
@ -644,44 +643,29 @@ bool BUDataStructures::calculateGraph(DSGraph &Graph) {
for (e = NextArgs.size(); i != e; ++i)
Args.push_back(NextArgs[i]);
}
if (locMissing) {
AuxCallsList.splice(AuxCallsList.end(), TempFCs, TempFCs.begin());
missingNode = true;
continue;
}
// Clean up the final graph!
GI->removeDeadNodes(DSGraph::KeepUnreachableGlobals);
} else {
DEBUG(std::cerr << "***\n*** RECYCLED GRAPH ***\n***\n");
for (std::vector<Function*>::iterator I = CalledFuncs.begin(), E = CalledFuncs.end(); I != E; ++I) {
AddGlobalToNode(this, CS, *I);
}
std::cerr << "***\n*** RECYCLED GRAPH ***\n***\n";
}
GI = IndCallGraph.first;
if (AlreadyInlined[CS.getCallSite()] != CalledFuncs) {
AlreadyInlined[CS.getCallSite()].swap(CalledFuncs);
// Merge the unified graph into this graph now.
DEBUG(std::cerr << " Inlining multi callee graph "
<< "[" << GI->getGraphSize() << "+"
<< GI->getAuxFunctionCalls().size() << "] into '"
<< Graph.getFunctionNames() << "' [" << Graph.getGraphSize() <<"+"
<< Graph.getAuxFunctionCalls().size() << "]\n");
// Merge the unified graph into this graph now.
DEBUG(std::cerr << " Inlining multi callee graph "
<< "[" << GI->getGraphSize() << "+"
<< GI->getAuxFunctionCalls().size() << "] into '"
<< Graph.getFunctionNames() << "' [" << Graph.getGraphSize() <<"+"
<< Graph.getAuxFunctionCalls().size() << "]\n");
Graph.mergeInGraph(CS, IndCallGraph.second, *GI,
DSGraph::StripAllocaBit |
DSGraph::DontCloneCallNodes);
++NumBUInlines;
} else {
DEBUG(std::cerr << " Skipping already inlined graph\n");
}
Graph.mergeInGraph(CS, IndCallGraph.second, *GI,
DSGraph::StripAllocaBit |
DSGraph::DontCloneCallNodes);
++NumBUInlines;
}
AuxCallsList.splice(AuxCallsList.end(), TempFCs, TempFCs.begin());
}
TempFCs.erase(TempFCs.begin());
}
// Recompute the Incomplete markers
@ -704,24 +688,6 @@ bool BUDataStructures::calculateGraph(DSGraph &Graph) {
RC.getClonedNH(MainSM[*I]);
//Graph.writeGraphToFile(std::cerr, "bu_" + F.getName());
AuxCallsList.sort();
AuxCallsList.unique();
//conditionally prune the call list keeping only one copy of each actual
//CallSite
if (AuxCallsList.size() > 100) {
DEBUG(std::cerr << "Reducing Aux from " << AuxCallsList.size());
std::map<CallSite, std::list<DSCallSite>::iterator> keepers;
TempFCs.swap(AuxCallsList);
for( std::list<DSCallSite>::iterator ii = TempFCs.begin(), ee = TempFCs.end();
ii != ee; ++ii)
keepers[ii->getCallSite()] = ii;
for (std::map<CallSite, std::list<DSCallSite>::iterator>::iterator
ii = keepers.begin(), ee = keepers.end();
ii != ee; ++ii)
AuxCallsList.splice(AuxCallsList.end(), TempFCs, ii->second);
DEBUG(std::cerr << " to " << AuxCallsList.size() << "\n");
}
return missingNode || oldSize != AuxCallsList.size();
}
static const Function *getFnForValue(const Value *V) {