From: Chris Lattner Date: Mon, 30 Jun 2003 03:15:25 +0000 (+0000) Subject: Revamp DSGraphs so that they can support multiple functions in the same X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5a540633036ccd7482bd8e83913304a4ed3fc11c;p=oota-llvm.git 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 --- diff --git a/lib/Analysis/DataStructure/BottomUpClosure.cpp b/lib/Analysis/DataStructure/BottomUpClosure.cpp index 4592867a4d8..591cefb15b9 100644 --- a/lib/Analysis/DataStructure/BottomUpClosure.cpp +++ b/lib/Analysis/DataStructure/BottomUpClosure.cpp @@ -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); diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp index ea593de2f56..e48568314bb 100644 --- a/lib/Analysis/DataStructure/DataStructure.cpp +++ b/lib/Analysis/DataStructure/DataStructure.cpp @@ -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 NodeMap; - RetNode = cloneInto(G, ScalarMap, NodeMap); + NodeMapTy NodeMap; + cloneInto(G, ScalarMap, ReturnNodes, NodeMap); } -DSGraph::DSGraph(const DSGraph &G, - hash_map &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 &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 &OldValMap, - hash_map &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 OldValMap; + ScalarMapTy OldValMap; + ScalarMapTy *ScalarMap = &OldValMap; DSNodeHandle RetVal; - hash_map *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 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 &Calls, - const std::string &where) { +static void removeIdenticalCalls(std::vector &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 &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 &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) diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp index a7751f23f7c..2b81d1423ce 100644 --- a/lib/Analysis/DataStructure/Local.cpp +++ b/lib/Analysis/DataStructure/Local.cpp @@ -62,25 +62,26 @@ namespace { /// graph by performing a single pass over the function in question. /// class GraphBuilder : InstVisitor { + Function &F; DSGraph &G; std::vector &Nodes; DSNodeHandle &RetNode; // Node that gets returned... - hash_map &ScalarMap; + DSGraph::ScalarMapTy &ScalarMap; std::vector &FunctionCalls; public: - GraphBuilder(DSGraph &g, std::vector &nodes, DSNodeHandle &retNode, - hash_map &SM, + GraphBuilder(Function &f, DSGraph &g, std::vector &nodes, + DSNodeHandle &retNode, DSGraph::ScalarMapTy &SM, std::vector &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 diff --git a/lib/Analysis/DataStructure/Printer.cpp b/lib/Analysis/DataStructure/Printer.cpp index 50d893366b7..f568c8d9671 100644 --- a/lib/Analysis/DataStructure/Printer.cpp +++ b/lib/Analysis/DataStructure/Printer.cpp @@ -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 : 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 : public DefaultDOTGraphTraits { /// static void addCustomGraphFeatures(const DSGraph *G, GraphWriter &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 &VM = G->getScalarMap(); - for (hash_map::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(I->first)) { std::stringstream OS; WriteAsOperand(OS, I->first, false, true, CurMod); @@ -108,16 +118,24 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { // Output the returned value pointer... - if (G->getRetNode().getNode() != 0) { - // Output the return node... - GW.emitSimpleNode((void*)1, "plaintext=circle", "returning"); - - // 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"); - } + 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 = 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 &FCs = diff --git a/lib/Analysis/DataStructure/Steensgaard.cpp b/lib/Analysis/DataStructure/Steensgaard.cpp index 2f370258ff7..5db619dd59e 100644 --- a/lib/Analysis/DataStructure/Steensgaard.cpp +++ b/lib/Analysis/DataStructure/Steensgaard.cpp @@ -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 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 ValMap; + DSGraph::ScalarMapTy ValMap; { // Scope to free NodeMap memory ASAP - hash_map 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 &GVM = ResultGraph->getScalarMap(); + DSGraph::ScalarMapTy &GVM = ResultGraph->getScalarMap(); for (hash_map::iterator I = ValMap.begin(), E = ValMap.end(); I != E; ++I) GVM[I->first].mergeWith(I->second); diff --git a/lib/Analysis/DataStructure/TopDownClosure.cpp b/lib/Analysis/DataStructure/TopDownClosure.cpp index 06de437d0ca..85a79d1076a 100644 --- a/lib/Analysis/DataStructure/TopDownClosure.cpp +++ b/lib/Analysis/DataStructure/TopDownClosure.cpp @@ -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 OldValMap; - hash_map 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();