Graphs that are part of equivalence sets can be multi-function SCC's
[oota-llvm.git] / lib / Analysis / DataStructure / CompleteBottomUp.cpp
index 8695537af5e29a322bd1f0a6211b8da413a200f2..3cd2bb0eef5f7b46e5c8510da0c074664b5aeadc 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Analysis/DataStructure.h"
+#include "llvm/Analysis/DataStructure/DataStructure.h"
 #include "llvm/Module.h"
-#include "llvm/Analysis/DSGraph.h"
-#include "Support/SCCIterator.h"
-#include "Support/STLExtras.h"
+#include "llvm/Analysis/DataStructure/DSGraph.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/SCCIterator.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/STLExtras.h"
 using namespace llvm;
 
 namespace {
   RegisterAnalysis<CompleteBUDataStructures>
   X("cbudatastructure", "'Complete' Bottom-up Data Structure Analysis");
+  Statistic<> NumCBUInlines("cbudatastructures", "Number of graphs inlined");
 }
 
 
 // run - Calculate the bottom up data structure graphs for each function in the
 // program.
 //
-bool CompleteBUDataStructures::run(Module &M) {
+bool CompleteBUDataStructures::runOnModule(Module &M) {
   BUDataStructures &BU = getAnalysis<BUDataStructures>();
   GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
   GlobalsGraph->setPrintAuxCalls();
 
-  // Our call graph is the same as the BU data structures call graph
-  ActualCallees = BU.getActualCallees();
-
 #if 1   // REMOVE ME EVENTUALLY
   // FIXME: TEMPORARY (remove once finalization of indirect call sites in the
   // globals graph has been implemented in the BU pass)
   TDDataStructures &TD = getAnalysis<TDDataStructures>();
 
+  ActualCallees.clear();
+
   // The call graph extractable from the TD pass is _much more complete_ and
   // trustable than that generated by the BU pass so far.  Until this is fixed,
   // we hack it like this:
@@ -50,17 +52,23 @@ bool CompleteBUDataStructures::run(Module &M) {
     const std::vector<DSCallSite> &CSs = TD.getDSGraph(*MI).getFunctionCalls();
 
     for (unsigned CSi = 0, e = CSs.size(); CSi != e; ++CSi) {
-      if (CSs[CSi].isIndirectCall()) {
-        Instruction *TheCall = CSs[CSi].getCallSite().getInstruction();
+      Instruction *TheCall = CSs[CSi].getCallSite().getInstruction();
 
+      if (CSs[CSi].isIndirectCall()) { // indirect call: insert all callees
         const std::vector<GlobalValue*> &Callees =
           CSs[CSi].getCalleeNode()->getGlobals();
         for (unsigned i = 0, e = Callees.size(); i != e; ++i)
           if (Function *F = dyn_cast<Function>(Callees[i]))
             ActualCallees.insert(std::make_pair(TheCall, F));
+      } else {        // direct call: insert the single callee directly
+        ActualCallees.insert(std::make_pair(TheCall,
+                                            CSs[CSi].getCalleeFunc()));
       }
     }
   }
+#else
+  // Our call graph is the same as the BU data structures call graph
+  ActualCallees = BU.getActualCallees();
 #endif
 
   std::vector<DSGraph*> Stack;
@@ -68,7 +76,8 @@ bool CompleteBUDataStructures::run(Module &M) {
   unsigned NextID = 1;
 
   if (Function *Main = M.getMainFunction()) {
-    calculateSCCGraphs(getOrCreateGraph(*Main), Stack, NextID, ValMap);
+    if (!Main->isExternal())
+      calculateSCCGraphs(getOrCreateGraph(*Main), Stack, NextID, ValMap);
   } else {
     std::cerr << "CBU-DSA: No 'main' function found!\n";
   }
@@ -77,6 +86,7 @@ bool CompleteBUDataStructures::run(Module &M) {
     if (!I->isExternal() && !DSInfo.count(I))
       calculateSCCGraphs(getOrCreateGraph(*I), Stack, NextID, ValMap);
 
+  GlobalsGraph->removeTriviallyDeadNodes();
   return false;
 }
 
@@ -141,12 +151,15 @@ unsigned CompleteBUDataStructures::calculateSCCGraphs(DSGraph &FG,
     ValMap[NG] = ~0U;
 
     DSGraph::NodeMapTy NodeMap;
-    FG.cloneInto(*NG, FG.getScalarMap(), FG.getReturnNodes(), NodeMap, 0);
+    FG.cloneInto(*NG, FG.getScalarMap(), FG.getReturnNodes(), NodeMap);
 
     // 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;
+
+    // Remove NG from the ValMap since the pointer may get recycled.
+    ValMap.erase(NG);
     delete NG;
     
     Stack.pop_back();
@@ -167,36 +180,47 @@ unsigned CompleteBUDataStructures::calculateSCCGraphs(DSGraph &FG,
 /// 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) {
+  hash_set<Instruction*> calls;
+
   // 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);
-        }
+    assert(calls.insert(TheCall).second &&
+           "Call instruction occurs multiple times in graph??");
+      
+
+    // Loop over all of the potentially called functions...
+    // Inline direct calls as well as indirect calls because the direct
+    // callee may have indirect callees and so may have changed.
+    // 
+    ActualCalleesTy::iterator I, E;
+    tie(I, E) = ActualCallees.equal_range(TheCall);
+    unsigned TNum = 0, Num = std::distance(I, E);
+    for (; I != E; ++I, ++TNum) {
+      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.
+        DSGraph &GI = getOrCreateGraph(*CalleeFunc);
+        ++NumCBUInlines;
+        G.mergeInGraph(CS, *CalleeFunc, GI, DSGraph::KeepModRefBits |
+                       DSGraph::StripAllocaBit | DSGraph::DontCloneCallNodes |
+                       DSGraph::DontCloneAuxCallNodes);
+        DEBUG(std::cerr << "    Inlining graph [" << i << "/" << e-1
+              << ":" << TNum << "/" << Num-1 << "] for "
+              << CalleeFunc->getName() << "["
+              << GI.getGraphSize() << "+" << GI.getAuxFunctionCalls().size()
+              << "] into '" /*<< G.getFunctionNames()*/ << "' ["
+              << G.getGraphSize() << "+" << G.getAuxFunctionCalls().size()
+              << "]\n");
       }
     }
   }
 
-  // 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
+  assert(G.getInlinedGlobals().empty());
   G.maskIncompleteMarkers();
   G.markIncompleteNodes(DSGraph::MarkFormalArgs);