From: Chris Lattner Date: Thu, 13 Nov 2003 05:05:41 +0000 (+0000) Subject: Implement the CompleteBU pass X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=79390d48d0a7c4c5d4f6d8efd25b3c44535fff08;p=oota-llvm.git Implement the CompleteBU pass git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@9964 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/DataStructure/CompleteBottomUp.cpp b/lib/Analysis/DataStructure/CompleteBottomUp.cpp index 751d5b0ff2b..326a794f7a0 100644 --- a/lib/Analysis/DataStructure/CompleteBottomUp.cpp +++ b/lib/Analysis/DataStructure/CompleteBottomUp.cpp @@ -16,6 +16,8 @@ #include "llvm/Analysis/DataStructure.h" #include "llvm/Module.h" #include "llvm/Analysis/DSGraph.h" +#include "Support/SCCIterator.h" +#include "Support/STLExtras.h" using namespace llvm; namespace { @@ -23,7 +25,6 @@ namespace { X("cbudatastructure", "'Complete' Bottom-up Data Structure Analysis"); } -using namespace DS; // run - Calculate the bottom up data structure graphs for each function in the // program. @@ -62,14 +63,143 @@ bool CompleteBUDataStructures::run(Module &M) { } #endif - // Start by copying all of the BU data structures graphs over, verbatim. + std::vector Stack; + hash_map ValMap; + unsigned NextID = 1; + + if (Function *Main = M.getMainFunction()) { + calculateSCCGraphs(getOrCreateGraph(*Main), Stack, NextID, ValMap); + } else { + std::cerr << "CBU-DSA: No 'main' function found!\n"; + } + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isExternal()) { - DSInfo[I] = new DSGraph(BU.getDSGraph(*I)); - DSInfo[I]->setGlobalsGraph(GlobalsGraph); - DSInfo[I]->setPrintAuxCalls(); + if (!I->isExternal() && !DSInfo.count(I)) + calculateSCCGraphs(getOrCreateGraph(*I), Stack, NextID, ValMap); + + return false; +} + +DSGraph &CompleteBUDataStructures::getOrCreateGraph(Function &F) { + // Has the graph already been created? + DSGraph *&Graph = DSInfo[&F]; + if (Graph) return *Graph; + + // Copy the BU graph... + Graph = new DSGraph(getAnalysis().getDSGraph(F)); + Graph->setGlobalsGraph(GlobalsGraph); + Graph->setPrintAuxCalls(); + + // Make sure to update the DSInfo map for all of the functions currently in + // this graph! + for (DSGraph::ReturnNodesTy::iterator I = Graph->getReturnNodes().begin(); + I != Graph->getReturnNodes().end(); ++I) + DSInfo[I->first] = Graph; + + return *Graph; +} + + + +unsigned CompleteBUDataStructures::calculateSCCGraphs(DSGraph &FG, + std::vector &Stack, + unsigned &NextID, + hash_map &ValMap) { + assert(!ValMap.count(&FG) && "Shouldn't revisit functions!"); + unsigned Min = NextID++, MyID = Min; + ValMap[&FG] = Min; + Stack.push_back(&FG); + + // The edges out of the current node are the call site targets... + for (unsigned i = 0, e = FG.getFunctionCalls().size(); i != e; ++i) { + Instruction *Call = FG.getFunctionCalls()[i].getCallSite().getInstruction(); + + // Loop over all of the actually called functions... + ActualCalleesTy::iterator I, E; + for (tie(I, E) = ActualCallees.equal_range(Call); I != E; ++I) { + DSGraph &Callee = getOrCreateGraph(*I->second); + unsigned M; + // Have we visited the destination function yet? + hash_map::iterator It = ValMap.find(&Callee); + if (It == ValMap.end()) // No, visit it now. + M = calculateSCCGraphs(Callee, Stack, NextID, ValMap); + else // Yes, get it's number. + M = It->second; + if (M < Min) Min = M; } + } + assert(ValMap[&FG] == MyID && "SCC construction assumption wrong!"); + if (Min != MyID) + return Min; // This is part of a larger SCC! - return false; + // If this is a new SCC, process it now. + bool IsMultiNodeSCC = false; + while (Stack.back() != &FG) { + DSGraph *NG = Stack.back(); + ValMap[NG] = ~0U; + + DSGraph::NodeMapTy NodeMap; + FG.cloneInto(*NG, FG.getScalarMap(), FG.getReturnNodes(), NodeMap, 0); + + // Update the DSInfo map and delete the old graph... + for (DSGraph::ReturnNodesTy::iterator I = NG->getReturnNodes().begin(); + I != NG->getReturnNodes().end(); ++I) + DSInfo[I->first] = &FG; + delete NG; + + Stack.pop_back(); + IsMultiNodeSCC = true; + } + + // Clean up the graph before we start inlining a bunch again... + if (IsMultiNodeSCC) + FG.removeTriviallyDeadNodes(); + + Stack.pop_back(); + processGraph(FG); + ValMap[&FG] = ~0U; + return MyID; +} + + +/// processGraph - Process the BU graphs for the program in bottom-up order on +/// the SCC of the __ACTUAL__ call graph. This builds "complete" BU graphs. +void CompleteBUDataStructures::processGraph(DSGraph &G) { + // The edges out of the current node are the call site targets... + for (unsigned i = 0, e = G.getFunctionCalls().size(); i != e; ++i) { + const DSCallSite &CS = G.getFunctionCalls()[i]; + Instruction *TheCall = CS.getCallSite().getInstruction(); + + // The Normal BU pass will have taken care of direct calls well already, + // don't worry about them. + if (!CS.getCallSite().getCalledFunction()) { + // Loop over all of the actually called functions... + ActualCalleesTy::iterator I, E; + for (tie(I, E) = ActualCallees.equal_range(TheCall); I != E; ++I) { + Function *CalleeFunc = I->second; + if (!CalleeFunc->isExternal()) { + // Merge the callee's graph into this graph. This works for normal + // calls or for self recursion within an SCC. + G.mergeInGraph(CS, *CalleeFunc, getOrCreateGraph(*CalleeFunc), + DSGraph::KeepModRefBits | + DSGraph::StripAllocaBit | + DSGraph::DontCloneCallNodes); + } + } + } + } + + // Re-materialize nodes from the globals graph. + // Do not ignore globals inlined from callees -- they are not up-to-date! + G.getInlinedGlobals().clear(); + G.updateFromGlobalGraph(); + + // Recompute the Incomplete markers + G.maskIncompleteMarkers(); + G.markIncompleteNodes(DSGraph::MarkFormalArgs); + + // Delete dead nodes. Treat globals that are unreachable but that can + // reach live nodes as live. + G.removeDeadNodes(DSGraph::KeepUnreachableGlobals); } diff --git a/lib/Analysis/DataStructure/Printer.cpp b/lib/Analysis/DataStructure/Printer.cpp index ae528aeb345..7e73bb0aee4 100644 --- a/lib/Analysis/DataStructure/Printer.cpp +++ b/lib/Analysis/DataStructure/Printer.cpp @@ -283,3 +283,8 @@ void TDDataStructures::print(std::ostream &O, const Module *M) const { printCollection(*this, O, M, "td."); } +void CompleteBUDataStructures::print(std::ostream &O, const Module *M) const { + printCollection(*this, O, M, "cbu."); +} + +