diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp index cd73acbc7c7..1f5f58ff471 100644 --- a/lib/Analysis/DataStructure/DataStructure.cpp +++ b/lib/Analysis/DataStructure/DataStructure.cpp @@ -977,6 +977,7 @@ static inline bool nodeContainsExternalFunction(const DSNode *N) { } 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! @@ -1022,6 +1023,7 @@ static void removeIdenticalCalls(std::vector &Calls) { LastCalleeContainsExternalFunction = LastCalleeFunc->isExternal(); } +#if 0 if (LastCalleeContainsExternalFunction || // This should be more than enough context sensitivity! // FIXME: Evaluate how many times this is tripped! @@ -1035,6 +1037,7 @@ static void removeIdenticalCalls(std::vector &Calls) { else if (CS.getNumPtrArgs() > OCS.getNumPtrArgs()) OCS = CS; } +#endif } else { if (CS.isDirectCall()) { LastCalleeFunc = CS.getCalleeFunc(); diff --git a/lib/Analysis/DataStructure/TopDownClosure.cpp b/lib/Analysis/DataStructure/TopDownClosure.cpp index f1d13b4d53d..b45a2f9e23b 100644 --- a/lib/Analysis/DataStructure/TopDownClosure.cpp +++ b/lib/Analysis/DataStructure/TopDownClosure.cpp @@ -8,10 +8,10 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/DataStructure.h" -#include "llvm/Analysis/DSGraph.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "Support/Statistic.h" +#include "DSCallSiteIterator.h" namespace { RegisterAnalysis // Register the pass @@ -27,14 +27,13 @@ bool TDDataStructures::run(Module &M) { // Calculate top-down from main... if (Function *F = M.getMainFunction()) - calculateGraph(*F); + calculateGraphFrom(*F); // Next calculate the graphs for each function unreachable function... for (Module::reverse_iterator I = M.rbegin(), E = M.rend(); I != E; ++I) - if (!I->isExternal()) - calculateGraph(*I); + if (!I->isExternal() && !DSInfo.count(&*I)) + calculateGraphFrom(*I); - GraphDone.clear(); // Free temporary memory... return false; } @@ -82,130 +81,165 @@ static bool FunctionHasCompleteArguments(Function &F) { return F.hasInternalLinkage(); } +void TDDataStructures::ComputePostOrder(Function &F,hash_set &Visited, + std::vector &PostOrder, + const BUDataStructures::ActualCalleesTy &ActualCallees) { + if (F.isExternal()) return; + DSGraph &G = getOrCreateDSGraph(F); + if (Visited.count(&G)) return; + Visited.insert(&G); + + // Recursively traverse all of the callee graphs. + const std::vector &FunctionCalls = G.getFunctionCalls(); -void TDDataStructures::calculateGraph(Function &F) { - // Make sure this graph has not already been calculated, and that we don't get - // into an infinite loop with mutually recursive functions. - // - if (GraphDone.count(&F)) return; - GraphDone.insert(&F); + for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) { + std::pair + IP = ActualCallees.equal_range(&FunctionCalls[i].getCallInst()); - // Get the current functions graph... - DSGraph &Graph = getOrCreateDSGraph(F); + for (BUDataStructures::ActualCalleesTy::const_iterator I = IP.first; + I != IP.second; ++I) + ComputePostOrder(*I->second, Visited, PostOrder, ActualCallees); + } + PostOrder.push_back(&G); +} + + + +void TDDataStructures::calculateGraphFrom(Function &F) { + // We want to traverse the call graph in reverse post-order. To do this, we + // calculate a post-order traversal, then reverse it. + hash_set VisitedGraph; + std::vector PostOrder; + ComputePostOrder(F, VisitedGraph, PostOrder, + getAnalysis().getActualCallees()); + VisitedGraph.clear(); // Release memory! + + // Visit each of the graphs in reverse post-order now! + while (!PostOrder.empty()) { + inlineGraphIntoCallees(*PostOrder.back()); + PostOrder.pop_back(); + } +} + + +void TDDataStructures::inlineGraphIntoCallees(DSGraph &Graph) { // Recompute the Incomplete markers and eliminate unreachable nodes. Graph.maskIncompleteMarkers(); - unsigned Flags = FunctionHasCompleteArguments(F) ? + unsigned Flags = true /* FIXME!! FunctionHasCompleteArguments(F)*/ ? DSGraph::IgnoreFormalArgs : DSGraph::MarkFormalArgs; Graph.markIncompleteNodes(Flags | DSGraph::IgnoreGlobals); Graph.removeDeadNodes(DSGraph::RemoveUnreachableGlobals); - const std::vector &CallSites = Graph.getFunctionCalls(); - if (CallSites.empty()) { - DEBUG(std::cerr << " [TD] No callees for: " << F.getName() << "\n"); - } else { - // Loop over all of the call sites, building a multi-map from Callees to - // DSCallSite*'s. With this map we can then loop over each callee, cloning - // this graph once into it, then resolving arguments. - // - std::multimap CalleeSites; - for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { - const DSCallSite &CS = CallSites[i]; - if (CS.isDirectCall()) { - if (!CS.getCalleeFunc()->isExternal()) // If it's not external - CalleeSites.insert(std::make_pair(CS.getCalleeFunc(), &CS));// Keep it - } else { - const std::vector &Callees = - CS.getCalleeNode()->getGlobals(); + DSCallSiteIterator CalleeI = DSCallSiteIterator::begin_std(Graph); + DSCallSiteIterator CalleeE = DSCallSiteIterator::end_std(Graph); - // Loop over all of the functions that this call may invoke... - for (unsigned c = 0, e = Callees.size(); c != e; ++c) - if (Function *F = dyn_cast(Callees[c]))// If this is a fn... - if (!F->isExternal()) // If it's not extern - CalleeSites.insert(std::make_pair(F, &CS)); // Keep track of it! + if (CalleeI == CalleeE) { + DEBUG(std::cerr << " [TD] No callees for: " << Graph.getFunctionNames() + << "\n"); + return; + } + + // Loop over all of the call sites, building a multi-map from Callees to + // DSCallSite*'s. With this map we can then loop over each callee, cloning + // this graph once into it, then resolving arguments. + // + std::multimap, const DSCallSite*> CalleeSites; + for (; CalleeI != CalleeE; ++CalleeI) + if (!(*CalleeI)->isExternal()) { + // We should have already created the graph here... + if (!DSInfo.count(*CalleeI)) + std::cerr << "WARNING: TD pass, did not know about callee: '" + << (*CalleeI)->getName() << "'\n"; + + DSGraph &IG = getOrCreateDSGraph(**CalleeI); + if (&IG != &Graph) + CalleeSites.insert(std::make_pair(std::make_pair(&IG, *CalleeI), + &CalleeI.getCallSite())); + } + + // Now that we have information about all of the callees, propagate the + // current graph into the callees. + // + DEBUG(std::cerr << " [TD] Inlining '" << Graph.getFunctionNames() <<"' into " + << CalleeSites.size() << " callees.\n"); + + // Loop over all the callees... + for (std::multimap, + const DSCallSite*>::iterator I = CalleeSites.begin(), + E = CalleeSites.end(); I != E; ) { + DSGraph &CG = *I->first.first; + + DEBUG(std::cerr << " [TD] Inlining graph into callee graph '" + << CG.getFunctionNames() << "'\n"); + + // Clone our current graph into the callee... + 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 + // current function calls this callee multiple times with different + // signatures. + // + for (; I != E && I->first.first == &CG; ++I) { + Function &Callee = *I->first.second; + DEBUG(std::cerr << "\t [TD] Merging args for callee '" + << Callee.getName() << "'\n"); + + // Map call site into callee graph + DSCallSite NewCS(*I->second, OldNodeMap); + + // Resolve the return values... + NewCS.getRetVal().mergeWith(CG.getReturnNodeFor(Callee)); + + // Resolve all of the arguments... + Function::aiterator AI = Callee.abegin(); + for (unsigned i = 0, e = NewCS.getNumPtrArgs(); + i != e && AI != Callee.aend(); ++i, ++AI) { + // Advance the argument iterator to the first pointer argument... + while (AI != Callee.aend() && !DS::isPointerType(AI->getType())) + ++AI; + if (AI == Callee.aend()) break; + + // Add the link from the argument scalar to the provided value + DSNodeHandle &NH = CG.getNodeForValue(AI); + assert(NH.getNode() && "Pointer argument without scalarmap entry?"); + NH.mergeWith(NewCS.getPtrArg(i)); } } - // Now that we have information about all of the callees, propagate the - // current graph into the callees. - // - DEBUG(std::cerr << " [TD] Inlining '" << F.getName() << "' into " - << CalleeSites.size() << " callees.\n"); + // Done with the nodemap... + OldNodeMap.clear(); - // Loop over all the callees... - for (std::multimap::iterator - I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ) - if (I->first == &F) { // Bottom-up pass takes care of self loops! - ++I; - } else { - // For each callee... - Function &Callee = *I->first; - DSGraph &CG = getOrCreateDSGraph(Callee); // Get the callee's graph... - - DEBUG(std::cerr << "\t [TD] Inlining into callee '" << Callee.getName() - << "'\n"); - - // Clone our current graph into the callee... - 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 - // current function calls this callee multiple times with different - // signatures. - // - for (; I != E && I->first == &Callee; ++I) { - // Map call site into callee graph - DSCallSite NewCS(*I->second, OldNodeMap); - - // Resolve the return values... - NewCS.getRetVal().mergeWith(CG.getReturnNodeFor(Callee)); - - // Resolve all of the arguments... - Function::aiterator AI = Callee.abegin(); - for (unsigned i = 0, e = NewCS.getNumPtrArgs(); - i != e && AI != Callee.aend(); ++i, ++AI) { - // Advance the argument iterator to the first pointer argument... - while (AI != Callee.aend() && !DS::isPointerType(AI->getType())) - ++AI; - if (AI == Callee.aend()) break; - - // Add the link from the argument scalar to the provided value - DSNodeHandle &NH = CG.getNodeForValue(AI); - assert(NH.getNode() && "Pointer argument without scalarmap entry?"); - NH.mergeWith(NewCS.getPtrArg(i)); - } - } - - // Done with the nodemap... - OldNodeMap.clear(); - - // Recompute the Incomplete markers and eliminate unreachable nodes. - CG.removeTriviallyDeadNodes(); - CG.maskIncompleteMarkers(); - CG.markIncompleteNodes(DSGraph::MarkFormalArgs |DSGraph::IgnoreGlobals); - CG.removeDeadNodes(DSGraph::RemoveUnreachableGlobals); - } - - DEBUG(std::cerr << " [TD] Done inlining into callees for: " << F.getName() - << " [" << Graph.getGraphSize() << "+" - << Graph.getFunctionCalls().size() << "]\n"); - - // Loop over all the callees... making sure they are all resolved now... - Function *LastFunc = 0; - for (std::multimap::iterator - I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I) - if (I->first != LastFunc) { // Only visit each callee once... - LastFunc = I->first; - calculateGraph(*I->first); - } + // Recompute the Incomplete markers and eliminate unreachable nodes. + CG.removeTriviallyDeadNodes(); + //CG.maskIncompleteMarkers(); + //CG.markIncompleteNodes(DSGraph::MarkFormalArgs | DSGraph::IgnoreGlobals); + //CG.removeDeadNodes(DSGraph::RemoveUnreachableGlobals); } + + DEBUG(std::cerr << " [TD] Done inlining into callees for: " + << Graph.getFunctionNames() << " [" << Graph.getGraphSize() << "+" + << Graph.getFunctionCalls().size() << "]\n"); + +#if 0 + // Loop over all the callees... making sure they are all resolved now... + Function *LastFunc = 0; + for (std::multimap::iterator + I = CalleeSites.begin(), E = CalleeSites.end(); I != E; ++I) + if (I->first != LastFunc) { // Only visit each callee once... + LastFunc = I->first; + calculateGraph(*I->first); + } +#endif }