Revamp DSGraphs so that they can support multiple functions in the same

DSGraph at one time


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6994 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2003-06-30 03:15:25 +00:00
parent a321b04d60
commit 5a54063303
6 changed files with 120 additions and 93 deletions

View File

@ -342,7 +342,7 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
DEBUG(std::cerr << " Self Inlining: " << F.getName() << "\n");
// Handle self recursion by resolving the arguments and return value
Graph.mergeInGraph(CS, Graph, 0);
Graph.mergeInGraph(CS, F, Graph, 0);
} else {
// Get the data structure graph for the called function.
@ -360,7 +360,7 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) {
#endif
// Handle self recursion by resolving the arguments and return value
Graph.mergeInGraph(CS, GI,
Graph.mergeInGraph(CS, *Callee, GI,
DSGraph::KeepModRefBits |
DSGraph::StripAllocaBit | DSGraph::DontCloneCallNodes);
@ -423,28 +423,28 @@ DSGraph &BUDataStructures::inlineNonSCCGraphs(Function &F,
LastCallSiteIdx = I.getCallSiteIdx();
// Resolve the current call...
Function *Callee = *I;
Function &Callee = **I;
DSCallSite &CS = I.getCallSite();
if (Callee->isExternal()) {
if (Callee.isExternal()) {
// Ignore this case, simple varargs functions we cannot stub out!
} else if (SCCFunctions.count(Callee)) {
} else if (SCCFunctions.count(&Callee)) {
// Calling a function in the SCC, ignore it for now!
DEBUG(std::cerr << " SCC CallSite for: " << Callee->getName() << "\n");
DEBUG(std::cerr << " SCC CallSite for: " << Callee.getName() << "\n");
AuxCallsList.push_back(CS);
} else {
// Get the data structure graph for the called function.
//
DSGraph &GI = getDSGraph(*Callee); // Graph to inline
DSGraph &GI = getDSGraph(Callee); // Graph to inline
DEBUG(std::cerr << " Inlining graph for " << Callee->getName()
DEBUG(std::cerr << " Inlining graph for " << Callee.getName()
<< "[" << GI.getGraphSize() << "+"
<< GI.getAuxFunctionCalls().size() << "] into: " << F.getName()
<< "[" << Graph.getGraphSize() << "+"
<< Graph.getAuxFunctionCalls().size() << "]\n");
// Handle self recursion by resolving the arguments and return value
Graph.mergeInGraph(CS, GI,
Graph.mergeInGraph(CS, Callee, GI,
DSGraph::KeepModRefBits | DSGraph::StripAllocaBit |
DSGraph::DontCloneCallNodes);
}
@ -514,7 +514,7 @@ DSGraph &BUDataStructures::calculateSCCGraph(Function &F,
DEBUG(std::cerr << " Self Inlining: " << F.getName() << "\n");
// Handle self recursion by resolving the arguments and return value
Graph.mergeInGraph(CS, Graph, 0);
Graph.mergeInGraph(CS, *Callee, Graph, 0);
} else if (SCCCallSiteMap.count(Callee)) {
// We have already seen a call site in the SCC for this function, just
// merge the two call sites together and we are done.
@ -530,7 +530,7 @@ DSGraph &BUDataStructures::calculateSCCGraph(Function &F,
<< Graph.getAuxFunctionCalls().size() << "]\n");
// Handle self recursion by resolving the arguments and return value
Graph.mergeInGraph(CS, GI,
Graph.mergeInGraph(CS, *Callee, GI,
DSGraph::KeepModRefBits | DSGraph::StripAllocaBit |
DSGraph::DontCloneCallNodes);

View File

@ -703,24 +703,23 @@ Function &DSCallSite::getCaller() const {
// DSGraph Implementation
//===----------------------------------------------------------------------===//
DSGraph::DSGraph(const DSGraph &G) : Func(G.Func), GlobalsGraph(0) {
DSGraph::DSGraph(const DSGraph &G) : GlobalsGraph(0) {
PrintAuxCalls = false;
hash_map<const DSNode*, DSNodeHandle> NodeMap;
RetNode = cloneInto(G, ScalarMap, NodeMap);
NodeMapTy NodeMap;
cloneInto(G, ScalarMap, ReturnNodes, NodeMap);
}
DSGraph::DSGraph(const DSGraph &G,
hash_map<const DSNode*, DSNodeHandle> &NodeMap)
: Func(G.Func), GlobalsGraph(0) {
DSGraph::DSGraph(const DSGraph &G, NodeMapTy &NodeMap)
: GlobalsGraph(0) {
PrintAuxCalls = false;
RetNode = cloneInto(G, ScalarMap, NodeMap);
cloneInto(G, ScalarMap, ReturnNodes, NodeMap);
}
DSGraph::~DSGraph() {
FunctionCalls.clear();
AuxFunctionCalls.clear();
ScalarMap.clear();
RetNode.setNode(0);
ReturnNodes.clear();
// Drop all intra-node references, so that assertions don't fail...
std::for_each(Nodes.begin(), Nodes.end(),
@ -746,16 +745,15 @@ void DSNode::remapLinks(hash_map<const DSNode*, DSNodeHandle> &OldNodeMap) {
}
// cloneInto - Clone the specified DSGraph into the current graph, returning the
// Return node of the graph. The translated ScalarMap for the old function is
// filled into the OldValMap member. If StripAllocas is set to true, Alloca
// markers are removed from the graph, as the graph is being cloned into a
// calling function's graph.
//
DSNodeHandle DSGraph::cloneInto(const DSGraph &G,
hash_map<Value*, DSNodeHandle> &OldValMap,
hash_map<const DSNode*, DSNodeHandle> &OldNodeMap,
unsigned CloneFlags) {
/// cloneInto - Clone the specified DSGraph into the current graph. The
/// translated ScalarMap for the old function is filled into the OldValMap
/// member, and the translated ReturnNodes map is returned into ReturnNodes.
///
/// The CloneFlags member controls various aspects of the cloning process.
///
void DSGraph::cloneInto(const DSGraph &G, ScalarMapTy &OldValMap,
ReturnNodesTy &OldReturnNodes, NodeMapTy &OldNodeMap,
unsigned CloneFlags) {
assert(OldNodeMap.empty() && "Returned OldNodeMap should be empty!");
assert(&G != this && "Cannot clone graph into itself!");
@ -816,10 +814,15 @@ DSNodeHandle DSGraph::cloneInto(const DSGraph &G,
AuxFunctionCalls.push_back(DSCallSite(G.AuxFunctionCalls[i], OldNodeMap));
}
// Return the returned node pointer...
DSNodeHandle &MappedRet = OldNodeMap[G.RetNode.getNode()];
return DSNodeHandle(MappedRet.getNode(),
MappedRet.getOffset()+G.RetNode.getOffset());
// Map the return node pointers over...
for (ReturnNodesTy::const_iterator I = G.getReturnNodes().begin(),
E = G.getReturnNodes().end(); I != E; ++I) {
const DSNodeHandle &Ret = I->second;
DSNodeHandle &MappedRet = OldNodeMap[Ret.getNode()];
OldReturnNodes.insert(std::make_pair(I->first,
DSNodeHandle(MappedRet.getNode(),
MappedRet.getOffset()+Ret.getOffset())));
}
}
/// mergeInGraph - The method is used for merging graphs together. If the
@ -827,25 +830,27 @@ DSNodeHandle DSGraph::cloneInto(const DSGraph &G,
/// merges the nodes specified in the call site with the formal arguments in the
/// graph.
///
void DSGraph::mergeInGraph(DSCallSite &CS, const DSGraph &Graph,
void DSGraph::mergeInGraph(DSCallSite &CS, Function &F, const DSGraph &Graph,
unsigned CloneFlags) {
hash_map<Value*, DSNodeHandle> OldValMap;
ScalarMapTy OldValMap;
ScalarMapTy *ScalarMap = &OldValMap;
DSNodeHandle RetVal;
hash_map<Value*, DSNodeHandle> *ScalarMap = &OldValMap;
// If this is not a recursive call, clone the graph into this graph...
if (&Graph != this) {
// Clone the callee's graph into the current graph, keeping
// track of where scalars in the old graph _used_ to point,
// and of the new nodes matching nodes of the old graph.
hash_map<const DSNode*, DSNodeHandle> OldNodeMap;
NodeMapTy OldNodeMap;
// The clone call may invalidate any of the vectors in the data
// structure graph. Strip locals and don't copy the list of callers
RetVal = cloneInto(Graph, OldValMap, OldNodeMap, CloneFlags);
ReturnNodesTy OldRetNodes;
cloneInto(Graph, OldValMap, OldRetNodes, OldNodeMap, CloneFlags);
RetVal = OldRetNodes[&F];
ScalarMap = &OldValMap;
} else {
RetVal = getRetNode();
RetVal = getReturnNodeFor(F);
ScalarMap = &getScalarMap();
}
@ -853,7 +858,6 @@ void DSGraph::mergeInGraph(DSCallSite &CS, const DSGraph &Graph,
RetVal.mergeWith(CS.getRetVal());
// Resolve all of the function arguments...
Function &F = Graph.getFunction();
Function::aiterator AI = F.abegin();
for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i, ++AI) {
@ -916,10 +920,16 @@ static void markIncomplete(DSCallSite &Call) {
//
void DSGraph::markIncompleteNodes(unsigned Flags) {
// Mark any incoming arguments as incomplete...
if ((Flags & DSGraph::MarkFormalArgs) && Func && Func->getName() != "main")
for (Function::aiterator I = Func->abegin(), E = Func->aend(); I != E; ++I)
if (isPointerType(I->getType()) && ScalarMap.find(I) != ScalarMap.end())
markIncompleteNode(ScalarMap[I].getNode());
if (Flags & DSGraph::MarkFormalArgs)
for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E =ReturnNodes.end();
FI != E; ++FI) {
Function &F = *FI->first;
if (F.getName() != "main")
for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
if (isPointerType(I->getType()) &&
ScalarMap.find(I) != ScalarMap.end())
markIncompleteNode(ScalarMap[I].getNode());
}
// Mark stuff passed into functions calls as being incomplete...
if (!shouldPrintAuxCalls())
@ -954,8 +964,7 @@ static inline bool nodeContainsExternalFunction(const DSNode *N) {
return false;
}
static void removeIdenticalCalls(std::vector<DSCallSite> &Calls,
const std::string &where) {
static void removeIdenticalCalls(std::vector<DSCallSite> &Calls) {
// Remove trivially identical function calls
unsigned NumFns = Calls.size();
std::sort(Calls.begin(), Calls.end()); // Sort by callee as primary key!
@ -1034,8 +1043,7 @@ static void removeIdenticalCalls(std::vector<DSCallSite> &Calls,
NumCallNodesMerged += NumFns-Calls.size();
DEBUG(if (NumFns != Calls.size())
std::cerr << "Merged " << (NumFns-Calls.size())
<< " call nodes in " << where << "\n";);
std::cerr << "Merged " << (NumFns-Calls.size()) << " call nodes.\n";);
}
@ -1045,8 +1053,8 @@ static void removeIdenticalCalls(std::vector<DSCallSite> &Calls,
// we don't have to perform any non-trivial analysis here.
//
void DSGraph::removeTriviallyDeadNodes() {
removeIdenticalCalls(FunctionCalls, Func ? Func->getName() : "");
removeIdenticalCalls(AuxFunctionCalls, Func ? Func->getName() : "");
removeIdenticalCalls(FunctionCalls);
removeIdenticalCalls(AuxFunctionCalls);
for (unsigned i = 0; i != Nodes.size(); ++i) {
DSNode *Node = Nodes[i];
@ -1195,7 +1203,9 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
}
// The return value is alive as well...
RetNode.getNode()->markReachableNodes(Alive);
for (ReturnNodesTy::iterator I = ReturnNodes.begin(), E = ReturnNodes.end();
I != E; ++I)
I->second.getNode()->markReachableNodes(Alive);
// Mark any nodes reachable by primary calls as alive...
for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i)

View File

@ -62,25 +62,26 @@ namespace {
/// graph by performing a single pass over the function in question.
///
class GraphBuilder : InstVisitor<GraphBuilder> {
Function &F;
DSGraph &G;
std::vector<DSNode*> &Nodes;
DSNodeHandle &RetNode; // Node that gets returned...
hash_map<Value*, DSNodeHandle> &ScalarMap;
DSGraph::ScalarMapTy &ScalarMap;
std::vector<DSCallSite> &FunctionCalls;
public:
GraphBuilder(DSGraph &g, std::vector<DSNode*> &nodes, DSNodeHandle &retNode,
hash_map<Value*, DSNodeHandle> &SM,
GraphBuilder(Function &f, DSGraph &g, std::vector<DSNode*> &nodes,
DSNodeHandle &retNode, DSGraph::ScalarMapTy &SM,
std::vector<DSCallSite> &fc)
: G(g), Nodes(nodes), RetNode(retNode), ScalarMap(SM), FunctionCalls(fc) {
: F(f), G(g), Nodes(nodes), RetNode(retNode), ScalarMap(SM),
FunctionCalls(fc) {
// Create scalar nodes for all pointer arguments...
for (Function::aiterator I = G.getFunction().abegin(),
E = G.getFunction().aend(); I != E; ++I)
for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
if (isPointerType(I->getType()))
getValueDest(*I);
visit(G.getFunction()); // Single pass over the function
visit(F); // Single pass over the function
}
private:
@ -139,10 +140,10 @@ namespace {
//===----------------------------------------------------------------------===//
// DSGraph constructor - Simply use the GraphBuilder to construct the local
// graph.
DSGraph::DSGraph(Function &F, DSGraph *GG) : Func(&F), GlobalsGraph(GG) {
DSGraph::DSGraph(Function &F, DSGraph *GG) : GlobalsGraph(GG) {
PrintAuxCalls = false;
// Use the graph builder to construct the local version of the graph
GraphBuilder B(*this, Nodes, RetNode, ScalarMap, FunctionCalls);
GraphBuilder B(F, *this, Nodes, ReturnNodes[&F], ScalarMap, FunctionCalls);
#ifndef NDEBUG
Timer::addPeakMemoryMeasurement();
#endif

View File

@ -29,7 +29,10 @@ void DSNode::dump() const { print(std::cerr, 0); }
static std::string getCaption(const DSNode *N, const DSGraph *G) {
std::stringstream OS;
Module *M = G && G->hasFunction() ? G->getFunction().getParent() : 0;
Module *M = 0;
// Get the module from ONE of the functions in the graph it is available.
if (G && !G->getReturnNodes().empty())
M = G->getReturnNodes().begin()->first->getParent();
if (N->isNodeCompletelyFolded())
OS << "FOLDED";
@ -64,10 +67,16 @@ static std::string getCaption(const DSNode *N, const DSGraph *G) {
template<>
struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
static std::string getGraphName(const DSGraph *G) {
if (G->hasFunction())
return "Function " + G->getFunction().getName();
else
return "Global graph";
switch (G->getReturnNodes().size()) {
case 0: return "Global graph";
case 1: return "Function " + G->getReturnNodes().begin()->first->getName();
default:
std::string Return = "Functions: ";
for (DSGraph::ReturnNodesTy::const_iterator I=G->getReturnNodes().begin();
I != G->getReturnNodes().end(); ++I)
Return += I->first->getName() + " ";
return Return;
}
}
static const char *getGraphProperties(const DSGraph *G) {
@ -88,12 +97,13 @@ struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
///
static void addCustomGraphFeatures(const DSGraph *G,
GraphWriter<const DSGraph*> &GW) {
Module *CurMod = G->hasFunction() ? G->getFunction().getParent() : 0;
Module *CurMod = 0;
if (!G->getReturnNodes().empty())
CurMod = G->getReturnNodes().begin()->first->getParent();
// Add scalar nodes to the graph...
const hash_map<Value*, DSNodeHandle> &VM = G->getScalarMap();
for (hash_map<Value*, DSNodeHandle>::const_iterator I = VM.begin();
I != VM.end(); ++I)
const DSGraph::ScalarMapTy &VM = G->getScalarMap();
for (DSGraph::ScalarMapTy::const_iterator I = VM.begin(); I != VM.end();++I)
if (!isa<GlobalValue>(I->first)) {
std::stringstream OS;
WriteAsOperand(OS, I->first, false, true, CurMod);
@ -108,16 +118,24 @@ struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
// Output the returned value pointer...
if (G->getRetNode().getNode() != 0) {
// Output the return node...
GW.emitSimpleNode((void*)1, "plaintext=circle", "returning");
const DSGraph::ReturnNodesTy &RetNodes = G->getReturnNodes();
for (DSGraph::ReturnNodesTy::const_iterator I = RetNodes.begin(),
E = RetNodes.end(); I != E; ++I)
if (I->second.getNode()) {
std::string Label;
if (RetNodes.size() == 1)
Label = "returning";
else
Label = I->first->getName() + " ret node";
// Output the return node...
GW.emitSimpleNode((void*)1, "plaintext=circle", Label);
// Add edge from return node to real destination
int RetEdgeDest = G->getRetNode().getOffset() >> DS::PointerShift;;
if (RetEdgeDest == 0) RetEdgeDest = -1;
GW.emitEdge((void*)1, -1, G->getRetNode().getNode(),
RetEdgeDest, "arrowtail=tee,color=gray63");
}
// Add edge from return node to real destination
int RetEdgeDest = I->second.getOffset() >> DS::PointerShift;;
if (RetEdgeDest == 0) RetEdgeDest = -1;
GW.emitEdge((void*)1, -1, I->second.getNode(),
RetEdgeDest, "arrowtail=tee,color=gray63");
}
// Output all of the call nodes...
const std::vector<DSCallSite> &FCs =

View File

@ -111,7 +111,7 @@ bool Steens::run(Module &M) {
// RetValMap - Keep track of the return values for all functions that return
// valid pointers.
//
hash_map<Function*, DSNodeHandle> RetValMap;
DSGraph::ReturnNodesTy RetValMap;
// Loop over the rest of the module, merging graphs for non-external functions
// into this graph.
@ -119,22 +119,16 @@ bool Steens::run(Module &M) {
unsigned Count = 0;
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (!I->isExternal()) {
hash_map<Value*, DSNodeHandle> ValMap;
DSGraph::ScalarMapTy ValMap;
{ // Scope to free NodeMap memory ASAP
hash_map<const DSNode*, DSNodeHandle> NodeMap;
DSGraph::NodeMapTy NodeMap;
const DSGraph &FDSG = LDS.getDSGraph(*I);
DSNodeHandle RetNode = ResultGraph->cloneInto(FDSG, ValMap, NodeMap);
// Keep track of the return node of the function's graph if it returns a
// value...
//
if (RetNode.getNode())
RetValMap[I] = RetNode;
ResultGraph->cloneInto(FDSG, ValMap, RetValMap, NodeMap);
}
// Incorporate the inlined Function's ScalarMap into the global
// ScalarMap...
hash_map<Value*, DSNodeHandle> &GVM = ResultGraph->getScalarMap();
DSGraph::ScalarMapTy &GVM = ResultGraph->getScalarMap();
for (hash_map<Value*, DSNodeHandle>::iterator I = ValMap.begin(),
E = ValMap.end(); I != E; ++I)
GVM[I->first].mergeWith(I->second);

View File

@ -57,6 +57,7 @@ void TDDataStructures::releaseMyMemory() {
GlobalsGraph = 0;
}
#if 0
/// ResolveCallSite - This method is used to link the actual arguments together
/// with the formal arguments for a function call in the top-down closure. This
/// method assumes that the call site arguments have been mapped into nodes
@ -82,6 +83,7 @@ void TDDataStructures::ResolveCallSite(DSGraph &Graph,
if (CallSite.getRetVal().getNode() && Graph.getRetNode().getNode())
Graph.getRetNode().mergeWith(CallSite.getRetVal());
}
#endif
DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
DSGraph *&G = DSInfo[&F];
@ -169,13 +171,15 @@ void TDDataStructures::calculateGraph(Function &F) {
<< "'\n");
// Clone our current graph into the callee...
hash_map<Value*, DSNodeHandle> OldValMap;
hash_map<const DSNode*, DSNodeHandle> OldNodeMap;
CG.cloneInto(Graph, OldValMap, OldNodeMap,
DSGraph::ScalarMapTy OldValMap;
DSGraph::NodeMapTy OldNodeMap;
DSGraph::ReturnNodesTy ReturnNodes;
CG.cloneInto(Graph, OldValMap, ReturnNodes, OldNodeMap,
DSGraph::StripModRefBits |
DSGraph::KeepAllocaBit | DSGraph::DontCloneCallNodes |
DSGraph::DontCloneAuxCallNodes);
OldValMap.clear(); // We don't care about the ValMap
ReturnNodes.clear(); // We don't care about return values either
// Loop over all of the invocation sites of the callee, resolving
// arguments to our graph. This loop may iterate multiple times if the
@ -187,7 +191,7 @@ void TDDataStructures::calculateGraph(Function &F) {
DSCallSite NewCS(*I->second, OldNodeMap);
// Resolve the return values...
NewCS.getRetVal().mergeWith(CG.getRetNode());
NewCS.getRetVal().mergeWith(CG.getReturnNodeFor(Callee));
// Resolve all of the arguments...
Function::aiterator AI = Callee.abegin();