diff --git a/lib/Analysis/DataStructure/BottomUpClosure.cpp b/lib/Analysis/DataStructure/BottomUpClosure.cpp index c03e1c20e71..a19155dbefd 100644 --- a/lib/Analysis/DataStructure/BottomUpClosure.cpp +++ b/lib/Analysis/DataStructure/BottomUpClosure.cpp @@ -27,7 +27,7 @@ bool BUDataStructures::run(Module &M) { // Simply calculate the graphs for each function... for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isExternal()) - calculateGraph(*I); + calculateGraph(*I, 0); return false; } @@ -46,7 +46,7 @@ void BUDataStructures::releaseMemory() { GlobalsGraph = 0; } -DSGraph &BUDataStructures::calculateGraph(Function &F) { +DSGraph &BUDataStructures::calculateGraph(Function &F, unsigned Indent) { // Make sure this graph has not already been calculated, or that we don't get // into an infinite loop with mutually recursive functions. // @@ -56,11 +56,7 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { // Copy the local version into DSInfo... Graph = new DSGraph(getAnalysis().getDSGraph(F)); Graph->setGlobalsGraph(GlobalsGraph); - -#if 0 - // Populate the GlobalsGraph with globals from this one. - Graph->GlobalsGraph->cloneGlobals(*Graph, /*cloneCalls*/ false); -#endif + Graph->setPrintAuxCalls(); // Start resolving calls... std::vector &FCs = Graph->getAuxFunctionCalls(); @@ -68,7 +64,8 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { // Start with a copy of the original call sites... FCs = Graph->getFunctionCalls(); - DEBUG(std::cerr << " [BU] Inlining: " << F.getName() << "\n"); + DEBUG(std::cerr << std::string(Indent*4, ' ') + << "[BU] Calculating graph for: " << F.getName() << "\n"); bool Inlined; do { @@ -86,6 +83,8 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { std::vector Callees = Call.getCallee().getNode()->getGlobals(); + unsigned OldNumCalls = FCs.size(); + // Loop over the functions, inlining whatever we can... for (unsigned c = 0; c != Callees.size(); ++c) { // Must be a function type, so this cast MUST succeed. @@ -94,7 +93,8 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { if (&FI == &F) { // Self recursion... simply link up the formal arguments with the // actual arguments... - DEBUG(std::cerr << "\t[BU] Self Inlining: " << F.getName() << "\n"); + DEBUG(std::cerr << std::string(Indent*4, ' ') + << " [BU] Self Inlining: " << F.getName() << "\n"); // Handle self recursion by resolving the arguments and return value Graph->mergeInGraph(Call, *Graph, DSGraph::StripAllocaBit); @@ -103,17 +103,20 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { Callees.erase(Callees.begin()+c--); } else if (!FI.isExternal()) { - DEBUG(std::cerr << "\t[BU] In " << F.getName() << " inlining: " + DEBUG(std::cerr << std::string(Indent*4, ' ') + << " [BU] In " << F.getName() << " inlining: " << FI.getName() << "\n"); // Get the data structure graph for the called function, closing it // if possible (which is only impossible in the case of mutual // recursion... // - DSGraph &GI = calculateGraph(FI); // Graph to inline + DSGraph &GI = calculateGraph(FI, Indent+1); // Graph to inline - DEBUG(std::cerr << "\t\t[BU] Got graph for " << FI.getName() - << " in: " << F.getName() << "\n"); + DEBUG(std::cerr << std::string(Indent*4, ' ') + << " [BU] Got graph for " << FI.getName() + << " in: " << F.getName() << "[" << GI.getGraphSize() << "+" + << GI.getAuxFunctionCalls().size() << "]\n"); // Handle self recursion by resolving the arguments and return value Graph->mergeInGraph(Call, GI, DSGraph::StripAllocaBit | @@ -124,7 +127,7 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { } else if (FI.getName() == "printf" || FI.getName() == "sscanf" || FI.getName() == "fprintf" || FI.getName() == "open" || - FI.getName() == "sprintf") { + FI.getName() == "sprintf" || FI.getName() == "fputs") { // FIXME: These special cases (eg printf) should go away when we can // define functions that take a variable number of arguments. @@ -146,7 +149,26 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { assert(0 && "Unimpl!"); Inlined = true; } + + // If we just inlined a function that had call nodes, chances are that + // the call nodes are redundant with ones we already have. Eliminate + // those call nodes now. + // + if (FCs.size() > OldNumCalls) + Graph->removeTriviallyDeadNodes(); } + + if (FCs.size() > 200) { + std::cerr << "Aborted inlining fn: '" << F.getName() << "'!" + << std::endl; + Graph->maskIncompleteMarkers(); + Graph->markIncompleteNodes(); + Graph->removeDeadNodes(); + Graph->writeGraphToFile(std::cerr, "crap."+F.getName()); + exit(1); + return *Graph; + } + } // Recompute the Incomplete markers. If there are any function calls left @@ -156,11 +178,15 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { Graph->markIncompleteNodes(); Graph->removeDeadNodes(); } + } while (Inlined && !FCs.empty()); - DEBUG(std::cerr << " [BU] Done inlining: " << F.getName() << " [" - << Graph->getGraphSize() << "+" << Graph->getFunctionCalls().size() + DEBUG(std::cerr << std::string(Indent*4, ' ') + << "[BU] Done inlining: " << F.getName() << " [" + << Graph->getGraphSize() << "+" << Graph->getAuxFunctionCalls().size() << "]\n"); + //Graph->writeGraphToFile(std::cerr, "bu_" + F.getName()); + return *Graph; }