Fix for PR341
[oota-llvm.git] / lib / Analysis / DataStructure / BottomUpClosure.cpp
index 36a3d1763ac5c34eb58832009ce14f78c9ecf76a..9f2124a1bb57178a78f6459545a3f6fa4b46cf17 100644 (file)
@@ -1,4 +1,11 @@
 //===- BottomUpClosure.cpp - Compute bottom-up interprocedural closure ----===//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
 //
 // This file implements the BUDataStructures class, which represents the
 // Bottom-Up Interprocedural closure of the data structure graph over the
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Analysis/DataStructure.h"
-#include "llvm/Analysis/DSGraph.h"
+#include "llvm/Analysis/DataStructure/DataStructure.h"
 #include "llvm/Module.h"
 #include "Support/Statistic.h"
-using std::map;
-
-static RegisterAnalysis<BUDataStructures>
-X("budatastructure", "Bottom-up Data Structure Analysis Closure");
+#include "Support/Debug.h"
+#include "DSCallSiteIterator.h"
+using namespace llvm;
+
+namespace {
+  Statistic<> MaxSCC("budatastructure", "Maximum SCC Size in Call Graph");
+  Statistic<> NumBUInlines("budatastructures", "Number of graphs inlined");
+  Statistic<> NumCallEdges("budatastructures", "Number of 'actual' call edges");
+  
+  RegisterAnalysis<BUDataStructures>
+  X("budatastructure", "Bottom-up Data Structure Analysis");
+}
 
 using namespace DS;
 
@@ -22,318 +36,298 @@ using namespace DS;
 // program.
 //
 bool BUDataStructures::run(Module &M) {
-  GlobalsGraph = new DSGraph();
+  LocalDataStructures &LocalDSA = getAnalysis<LocalDataStructures>();
+  GlobalsGraph = new DSGraph(LocalDSA.getGlobalsGraph());
+  GlobalsGraph->setPrintAuxCalls();
+
+  Function *MainFunc = M.getMainFunction();
+  if (MainFunc)
+    calculateReachableGraphs(MainFunc);
 
-  // Simply calculate the graphs for each function...
+  // Calculate the graphs for any functions that are unreachable from main...
   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
-    if (!I->isExternal())
-      calculateGraph(*I, 0);
+    if (!I->isExternal() && !DSInfo.count(I)) {
+#ifndef NDEBUG
+      if (MainFunc)
+        std::cerr << "*** Function unreachable from main: "
+                  << I->getName() << "\n";
+#endif
+      calculateReachableGraphs(I);    // Calculate all graphs...
+    }
+
+  NumCallEdges += ActualCallees.size();
+
+  // At the end of the bottom-up pass, the globals graph becomes complete.
+  // FIXME: This is not the right way to do this, but it is sorta better than
+  // nothing!  In particular, externally visible globals and unresolvable call
+  // nodes at the end of the BU phase should make things that they point to
+  // incomplete in the globals graph.
+  // 
+  GlobalsGraph->removeTriviallyDeadNodes();
+  GlobalsGraph->maskIncompleteMarkers();
   return false;
 }
 
-// releaseMemory - If the pass pipeline is done with this pass, we can release
-// our memory... here...
-//
-void BUDataStructures::releaseMemory() {
-  for (map<const Function*, DSGraph*>::iterator I = DSInfo.begin(),
-         E = DSInfo.end(); I != E; ++I)
-    delete I->second;
+void BUDataStructures::calculateReachableGraphs(Function *F) {
+  std::vector<Function*> Stack;
+  hash_map<Function*, unsigned> ValMap;
+  unsigned NextID = 1;
+  calculateGraphs(F, Stack, NextID, ValMap);
+}
 
-  // Empty map so next time memory is released, data structures are not
-  // re-deleted.
-  DSInfo.clear();
-  delete GlobalsGraph;
-  GlobalsGraph = 0;
+DSGraph &BUDataStructures::getOrCreateGraph(Function *F) {
+  // Has the graph already been created?
+  DSGraph *&Graph = DSInfo[F];
+  if (Graph) return *Graph;
+
+  // Copy the local version into DSInfo...
+  Graph = new DSGraph(getAnalysis<LocalDataStructures>().getDSGraph(*F));
+
+  Graph->setGlobalsGraph(GlobalsGraph);
+  Graph->setPrintAuxCalls();
+
+  // Start with a copy of the original call sites...
+  Graph->getAuxFunctionCalls() = Graph->getFunctionCalls();
+  return *Graph;
 }
 
+unsigned BUDataStructures::calculateGraphs(Function *F,
+                                           std::vector<Function*> &Stack,
+                                           unsigned &NextID, 
+                                     hash_map<Function*, unsigned> &ValMap) {
+  assert(!ValMap.count(F) && "Shouldn't revisit functions!");
+  unsigned Min = NextID++, MyID = Min;
+  ValMap[F] = Min;
+  Stack.push_back(F);
+
+  // FIXME!  This test should be generalized to be any function that we have
+  // already processed, in the case when there isn't a main or there are
+  // unreachable functions!
+  if (F->isExternal()) {   // sprintf, fprintf, sscanf, etc...
+    // No callees!
+    Stack.pop_back();
+    ValMap[F] = ~0;
+    return Min;
+  }
 
-// Return true if a graph was inlined
-// Can not modify the part of the AuxCallList < FirstResolvableCall.
-//
-bool BUDataStructures::ResolveFunctionCalls(DSGraph &G,
-                                            unsigned &FirstResolvableCall,
-                                   std::map<Function*, DSCallSite> &InProcess,
-                                            unsigned Indent) {
-  std::vector<DSCallSite> &FCs = G.getAuxFunctionCalls();
-  bool Changed = false;
-
-  // Loop while there are call sites that we can resolve!
-  while (FirstResolvableCall != FCs.size()) {
-    DSCallSite Call = FCs[FirstResolvableCall];
-
-    // If the function list is incomplete...
-    if (Call.getCallee().getNode()->NodeType & DSNode::Incomplete) {
-      // If incomplete, we cannot resolve it, so leave it at the beginning of
-      // the call list with the other unresolvable calls...
-      ++FirstResolvableCall;
+  DSGraph &Graph = getOrCreateGraph(F);
+
+  // The edges out of the current node are the call site targets...
+  for (DSCallSiteIterator I = DSCallSiteIterator::begin_aux(Graph),
+         E = DSCallSiteIterator::end_aux(Graph); I != E; ++I) {
+    Function *Callee = *I;
+    unsigned M;
+    // Have we visited the destination function yet?
+    hash_map<Function*, unsigned>::iterator It = ValMap.find(Callee);
+    if (It == ValMap.end())  // No, visit it now.
+      M = calculateGraphs(Callee, Stack, NextID, ValMap);
+    else                    // Yes, get it's number.
+      M = It->second;
+    if (M < Min) Min = M;
+  }
+
+  assert(ValMap[F] == MyID && "SCC construction assumption wrong!");
+  if (Min != MyID)
+    return Min;         // This is part of a larger SCC!
+
+  // If this is a new SCC, process it now.
+  if (Stack.back() == F) {           // Special case the single "SCC" case here.
+    DEBUG(std::cerr << "Visiting single node SCC #: " << MyID << " fn: "
+                    << F->getName() << "\n");
+    Stack.pop_back();
+    DSGraph &G = getDSGraph(*F);
+    DEBUG(std::cerr << "  [BU] Calculating graph for: " << F->getName()<< "\n");
+    calculateGraph(G);
+    DEBUG(std::cerr << "  [BU] Done inlining: " << F->getName() << " ["
+                    << G.getGraphSize() << "+" << G.getAuxFunctionCalls().size()
+                    << "]\n");
+
+    if (MaxSCC < 1) MaxSCC = 1;
+
+    // Should we revisit the graph?
+    if (DSCallSiteIterator::begin_aux(G) != DSCallSiteIterator::end_aux(G)) {
+      ValMap.erase(F);
+      return calculateGraphs(F, Stack, NextID, ValMap);
     } else {
-      // Start inlining all of the functions we can... some may not be
-      // inlinable if they are external...
-      //
-      const std::vector<GlobalValue*> &Callees =
-        Call.getCallee().getNode()->getGlobals();
-
-      bool hasExternalTarget = false;
-      
-      // Loop over the functions, inlining whatever we can...
-      for (unsigned c = 0, e = Callees.size(); c != e; ++c) {
-        // Must be a function type, so this cast should succeed unless something
-        // really wierd is happening.
-        Function &FI = cast<Function>(*Callees[c]);
-
-        if (FI.getName() == "printf" || FI.getName() == "sscanf" ||
-            FI.getName() == "fprintf" || FI.getName() == "open" ||
-            FI.getName() == "sprintf" || FI.getName() == "fputs") {
-          // Ignore
-        } else if (FI.isExternal()) {
-          // If the function is external, then we cannot resolve this call site!
-          hasExternalTarget = true;
-          break;
-        } else {
-          std::map<Function*, DSCallSite>::iterator I =
-            InProcess.lower_bound(&FI);
-
-          if (I != InProcess.end() && I->first == &FI) {  // Recursion detected?
-            // Merge two call sites to eliminate recursion...
-            Call.mergeWith(I->second);
-
-            DEBUG(std::cerr << std::string(Indent*2, ' ')
-                  << "* Recursion detected for function " << FI.getName()<<"\n");
-          } else {
-            DEBUG(std::cerr << std::string(Indent*2, ' ')
-                  << "Inlining: " << FI.getName() << "\n");
-            
-            // Get the data structure graph for the called function, closing it
-            // if possible...
-            //
-            DSGraph &GI = calculateGraph(FI, Indent+1);  // Graph to inline
-
-            DEBUG(std::cerr << std::string(Indent*2, ' ')
-                  << "Got graph for: " << FI.getName() << "["
-                  << GI.getGraphSize() << "+"
-                  << GI.getAuxFunctionCalls().size() << "] "
-                  << " in: " << G.getFunction().getName() << "["
-                  << G.getGraphSize() << "+"
-                  << G.getAuxFunctionCalls().size() << "]\n");
-
-            // Keep track of how many call sites are added by the inlining...
-            unsigned NumCalls = FCs.size();
-
-            // Resolve the arguments and return value
-            G.mergeInGraph(Call, GI, DSGraph::StripAllocaBit |
-                           DSGraph::DontCloneCallNodes);
-
-            // Added a call site?
-            if (FCs.size() != NumCalls) {
-              // Otherwise we need to inline the graph.  Temporarily add the
-              // current function to the InProcess map to be able to handle
-              // recursion successfully.
-              //
-              I = InProcess.insert(I, std::make_pair(&FI, Call));
-
-              // ResolveFunctionCalls - Resolve the function calls that just got
-              // inlined...
-              //
-              Changed |= ResolveFunctionCalls(G, NumCalls, InProcess, Indent+1);
-              
-              // Now that we are done processing the inlined graph, remove our
-              // cycle detector record...
-              //
-              //InProcess.erase(I);
-            }
-          }
+      ValMap[F] = ~0U;
+    }
+    return MyID;
+
+  } else {
+    // SCCFunctions - Keep track of the functions in the current SCC
+    //
+    hash_set<DSGraph*> SCCGraphs;
+
+    Function *NF;
+    std::vector<Function*>::iterator FirstInSCC = Stack.end();
+    DSGraph *SCCGraph = 0;
+    do {
+      NF = *--FirstInSCC;
+      ValMap[NF] = ~0U;
+
+      // Figure out which graph is the largest one, in order to speed things up
+      // a bit in situations where functions in the SCC have widely different
+      // graph sizes.
+      DSGraph &NFGraph = getDSGraph(*NF);
+      SCCGraphs.insert(&NFGraph);
+      // FIXME: If we used a better way of cloning graphs (ie, just splice all
+      // of the nodes into the new graph), this would be completely unneeded!
+      if (!SCCGraph || SCCGraph->getGraphSize() < NFGraph.getGraphSize())
+        SCCGraph = &NFGraph;
+    } while (NF != F);
+
+    std::cerr << "Calculating graph for SCC #: " << MyID << " of size: "
+              << SCCGraphs.size() << "\n";
+
+    // Compute the Max SCC Size...
+    if (MaxSCC < SCCGraphs.size())
+      MaxSCC = SCCGraphs.size();
+
+    // First thing first, collapse all of the DSGraphs into a single graph for
+    // the entire SCC.  We computed the largest graph, so clone all of the other
+    // (smaller) graphs into it.  Discard all of the old graphs.
+    //
+    for (hash_set<DSGraph*>::iterator I = SCCGraphs.begin(),
+           E = SCCGraphs.end(); I != E; ++I) {
+      DSGraph &G = **I;
+      if (&G != SCCGraph) {
+        {
+          DSGraph::NodeMapTy NodeMap;
+          SCCGraph->cloneInto(G, SCCGraph->getScalarMap(),
+                              SCCGraph->getReturnNodes(), NodeMap);
         }
-      }
-
-      if (hasExternalTarget) {
-        // If we cannot resolve this call site...
-        ++FirstResolvableCall;
-      } else {
-        Changed = true;
-        FCs.erase(FCs.begin()+FirstResolvableCall);
+        // Update the DSInfo map and delete the old graph...
+        for (DSGraph::ReturnNodesTy::iterator I = G.getReturnNodes().begin(),
+               E = G.getReturnNodes().end(); I != E; ++I)
+          DSInfo[I->first] = SCCGraph;
+        delete &G;
       }
     }
+
+    // Clean up the graph before we start inlining a bunch again...
+    SCCGraph->removeDeadNodes(DSGraph::RemoveUnreachableGlobals);
+
+    // Now that we have one big happy family, resolve all of the call sites in
+    // the graph...
+    calculateGraph(*SCCGraph);
+    DEBUG(std::cerr << "  [BU] Done inlining SCC  [" << SCCGraph->getGraphSize()
+                    << "+" << SCCGraph->getAuxFunctionCalls().size() << "]\n");
+
+    std::cerr << "DONE with SCC #: " << MyID << "\n";
+
+    // We never have to revisit "SCC" processed functions...
+    
+    // Drop the stuff we don't need from the end of the stack
+    Stack.erase(FirstInSCC, Stack.end());
+    return MyID;
   }
 
-  return Changed;
+  return MyID;  // == Min
 }
 
-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.
-  //
-  DSGraph *&GraphPtr = DSInfo[&F];
-  if (GraphPtr) return *GraphPtr;
 
-  // Copy the local version into DSInfo...
-  GraphPtr = new DSGraph(getAnalysis<LocalDataStructures>().getDSGraph(F));
-  DSGraph &Graph = *GraphPtr;
+// releaseMemory - If the pass pipeline is done with this pass, we can release
+// our memory... here...
+//
+void BUDataStructures::releaseMemory() {
+  for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
+         E = DSInfo.end(); I != E; ++I) {
+    I->second->getReturnNodes().erase(I->first);
+    if (I->second->getReturnNodes().empty())
+      delete I->second;
+  }
 
-  Graph.setGlobalsGraph(GlobalsGraph);
-  Graph.setPrintAuxCalls();
+  // Empty map so next time memory is released, data structures are not
+  // re-deleted.
+  DSInfo.clear();
+  delete GlobalsGraph;
+  GlobalsGraph = 0;
+}
 
-  // Start resolving calls...
-  std::vector<DSCallSite> &FCs = Graph.getAuxFunctionCalls();
+void BUDataStructures::calculateGraph(DSGraph &Graph) {
+  // Move our call site list into TempFCs so that inline call sites go into the
+  // new call site list and doesn't invalidate our iterators!
+  std::vector<DSCallSite> TempFCs;
+  std::vector<DSCallSite> &AuxCallsList = Graph.getAuxFunctionCalls();
+  TempFCs.swap(AuxCallsList);
+
+  DSGraph::ReturnNodesTy &ReturnNodes = Graph.getReturnNodes();
+
+  // Loop over all of the resolvable call sites
+  unsigned LastCallSiteIdx = ~0U;
+  for (DSCallSiteIterator I = DSCallSiteIterator::begin(TempFCs),
+         E = DSCallSiteIterator::end(TempFCs); I != E; ++I) {
+    // If we skipped over any call sites, they must be unresolvable, copy them
+    // to the real call site list.
+    LastCallSiteIdx++;
+    for (; LastCallSiteIdx < I.getCallSiteIdx(); ++LastCallSiteIdx)
+      AuxCallsList.push_back(TempFCs[LastCallSiteIdx]);
+    LastCallSiteIdx = I.getCallSiteIdx();
+    
+    // Resolve the current call...
+    Function *Callee = *I;
+    DSCallSite CS = I.getCallSite();
 
-  // Start with a copy of the original call sites...
-  FCs = Graph.getFunctionCalls();
-
-  DEBUG(std::cerr << std::string(Indent*2, ' ')
-                  << "[BU] Calculating graph for: " << F.getName() << "\n");
-
-  bool Changed;
-  while (1) {
-    unsigned FirstResolvableCall = 0;
-    std::map<Function *, DSCallSite> InProcess;
-
-    // Insert a call site for self to handle self recursion...
-    std::vector<DSNodeHandle> Args;
-    Args.reserve(F.asize());
-    for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I)
-      if (isPointerType(I->getType()))
-        Args.push_back(Graph.getNodeForValue(I));
-
-    InProcess.insert(std::make_pair(&F, 
-           DSCallSite(*(CallInst*)0, Graph.getRetNode(),(DSNode*)0,Args)));
-
-    Changed = ResolveFunctionCalls(Graph, FirstResolvableCall, InProcess,
-                                   Indent);
-
-    if (Changed) {
-      Graph.maskIncompleteMarkers();
-      Graph.markIncompleteNodes();
-      Graph.removeDeadNodes();
-      break;
-    } else {
-      break;
-    }
-  }
+    if (Callee->isExternal()) {
+      // Ignore this case, simple varargs functions we cannot stub out!
+    } else if (ReturnNodes.count(Callee)) {
+      // Self recursion... simply link up the formal arguments with the
+      // actual arguments...
+      DEBUG(std::cerr << "    Self Inlining: " << Callee->getName() << "\n");
 
-#if 0  
-  bool Inlined;
-  do {
-    Inlined = false;
-
-    for (unsigned i = 0; i != FCs.size(); ++i) {
-      // Copy the call, because inlining graphs may invalidate the FCs vector.
-      DSCallSite Call = FCs[i];
-
-      // If the function list is complete...
-      if ((Call.getCallee().getNode()->NodeType & DSNode::Incomplete)==0) {
-        // Start inlining all of the functions we can... some may not be
-        // inlinable if they are external...
-        //
-        std::vector<GlobalValue*> 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.
-          Function &FI = cast<Function>(*Callees[c]);
-
-          if (&FI == &F) {
-            // Self recursion... simply link up the formal arguments with the
-            // actual arguments...
-            DEBUG(std::cerr << std::string(Indent*2, ' ')
-                  << "[BU] Self Inlining: " << F.getName() << "\n");
-
-            // Handle self recursion by resolving the arguments and return value
-            Graph.mergeInGraph(Call, Graph, DSGraph::StripAllocaBit);
-
-            // Erase the entry in the callees vector
-            Callees.erase(Callees.begin()+c--);
-
-          } else if (!FI.isExternal()) {
-            DEBUG(std::cerr << std::string(Indent*2, ' ')
-                  << "[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, Indent+1);  // Graph to inline
-
-            DEBUG(std::cerr << std::string(Indent*2, ' ')
-                  << "[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 |
-                                DSGraph::DontCloneCallNodes);
-
-            // Erase the entry in the Callees vector
-            Callees.erase(Callees.begin()+c--);
-
-          } else if (FI.getName() == "printf" || FI.getName() == "sscanf" ||
-                     FI.getName() == "fprintf" || FI.getName() == "open" ||
-                     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.
-
-            // FIXME: at the very least, this should update mod/ref info
-            // Erase the entry in the globals vector
-            Callees.erase(Callees.begin()+c--);
-          }
-        }
+      // Handle self recursion by resolving the arguments and return value
+      Graph.mergeInGraph(CS, *Callee, Graph, 0);
 
-        if (Callees.empty()) {         // Inlined all of the function calls?
-          // Erase the call if it is resolvable...
-          FCs.erase(FCs.begin()+i--);  // Don't skip a the next call...
-          Inlined = true;
-        } else if (Callees.size() !=
-                   Call.getCallee().getNode()->getGlobals().size()) {
-          // Was able to inline SOME, but not all of the functions.  Construct a
-          // new global node here.
-          //
-          assert(0 && "Unimpl!");
-          Inlined = true;
-        }
+    } else {
+      ActualCallees.insert(std::make_pair(CS.getCallSite().getInstruction(),
+                                          Callee));
 
+      // Get the data structure graph for the called function.
+      //
+      DSGraph &GI = getDSGraph(*Callee);  // Graph to inline
+
+      DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
+            << "[" << GI.getGraphSize() << "+"
+            << GI.getAuxFunctionCalls().size() << "] into '"
+            << Graph.getFunctionNames() << "' [" << Graph.getGraphSize() << "+"
+            << Graph.getAuxFunctionCalls().size() << "]\n");
+      Graph.mergeInGraph(CS, *Callee, GI,
+                         DSGraph::KeepModRefBits | 
+                         DSGraph::StripAllocaBit | DSGraph::DontCloneCallNodes);
+      ++NumBUInlines;
 
 #if 0
-        // 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();
+      Graph.writeGraphToFile(std::cerr, "bu_" + F.getName() + "_after_" +
+                             Callee->getName());
 #endif
-      }
+    }
+  }
 
-      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;
-      }
+  // Make sure to catch any leftover unresolvable calls...
+  for (++LastCallSiteIdx; LastCallSiteIdx < TempFCs.size(); ++LastCallSiteIdx)
+    AuxCallsList.push_back(TempFCs[LastCallSiteIdx]);
 
-    }
+  TempFCs.clear();
 
-    // Recompute the Incomplete markers.  If there are any function calls left
-    // now that are complete, we must loop!
-    if (Inlined) {
-      Graph.maskIncompleteMarkers();
-      Graph.markIncompleteNodes();
-      Graph.removeDeadNodes();
-    }
-    
-  } while (Inlined && !FCs.empty());
-#endif
+  // Recompute the Incomplete markers
+  assert(Graph.getInlinedGlobals().empty());
+  Graph.maskIncompleteMarkers();
+  Graph.markIncompleteNodes(DSGraph::MarkFormalArgs);
+
+  // Delete dead nodes.  Treat globals that are unreachable but that can
+  // reach live nodes as live.
+  Graph.removeDeadNodes(DSGraph::KeepUnreachableGlobals);
 
-  DEBUG(std::cerr << std::string(Indent*2, ' ')
-        << "[BU] Done inlining: " << F.getName() << " ["
-        << Graph.getGraphSize() << "+" << Graph.getAuxFunctionCalls().size()
-        << "]\n");
+  // When this graph is finalized, clone the globals in the graph into the
+  // globals graph to make sure it has everything, from all graphs.
+  DSScalarMap &MainSM = Graph.getScalarMap();
+  ReachabilityCloner RC(*GlobalsGraph, Graph, DSGraph::StripAllocaBit);
 
-  Graph.writeGraphToFile(std::cerr, "bu_" + F.getName());
+  // Clone everything reachable from globals in the "main" graph into the
+  // globals graph.
+  for (DSScalarMap::global_iterator I = MainSM.global_begin(),
+         E = MainSM.global_end(); I != E; ++I) 
+    RC.getClonedNH(MainSM[*I]);
 
-  return Graph;
+  //Graph.writeGraphToFile(std::cerr, "bu_" + F.getName());
 }