[llvm-commits] CVS: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp CompleteBottomUp.cpp DataStructure.cpp EquivClassGraphs.cpp Local.cpp Steensgaard.cpp TopDownClosure.cpp

Chris Lattner lattner at cs.uiuc.edu
Sat Mar 19 14:24:01 PST 2005



Changes in directory llvm/lib/Analysis/DataStructure:

BottomUpClosure.cpp updated: 1.98 -> 1.99
CompleteBottomUp.cpp updated: 1.22 -> 1.23
DataStructure.cpp updated: 1.211 -> 1.212
EquivClassGraphs.cpp updated: 1.34 -> 1.35
Local.cpp updated: 1.127 -> 1.128
Steensgaard.cpp updated: 1.46 -> 1.47
TopDownClosure.cpp updated: 1.75 -> 1.76
---
Log message:

Create an equivalence class of global variables that DSA will never be able 
to tell apart anyway, and only track the leader for of these equivalence 
classes in our graphs.

This dramatically reduces the number of GlobalValue*'s that appear in scalar
maps, which A) reduces memory usage, by eliminating many many scalarmap entries
and B) reduces time for operations that need to execute an operation for each 
global in the scalar map.

As an example, this reduces the memory used to analyze 176.gcc from 1GB to
511MB, which (while it's still way too much) is better because it doesn't hit
swap anymore.  On eon, this shrinks the local graphs from 14MB to 6.8MB, 
shrinks the bu+td graphs of povray from 50M to 40M, shrinks the TD graphs of
130.li from 8.8M to 3.6M, etc.

This change also speeds up DSA on large programs where this makes a big 
difference.  For example, 130.li goes from 1.17s -> 0.56s, 134.perl goes
from 2.14 -> 0.93s, povray goes from 15.63s->7.99s (!!!).

This also apparently either fixes the problem that caused DSA to crash on
perlbmk and gcc, or it hides it, because DSA now works on these.  These 
both take entirely too much time in the TD pass (147s for perl, 538s for
gcc, vs 7.67/5.9s in the bu pass for either one), but this is a known 
problem that I'll deal with later.



---
Diffs of the changes:  (+72 -48)

 BottomUpClosure.cpp  |   11 +++++++----
 CompleteBottomUp.cpp |    4 ++--
 DataStructure.cpp    |   42 +++++++++++++++---------------------------
 EquivClassGraphs.cpp |    5 +++--
 Local.cpp            |   43 ++++++++++++++++++++++++++++++++++++-------
 Steensgaard.cpp      |    8 +++++---
 TopDownClosure.cpp   |    7 ++++---
 7 files changed, 72 insertions(+), 48 deletions(-)


Index: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp
diff -u llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.98 llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.99
--- llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.98	Fri Mar 18 17:19:47 2005
+++ llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp	Sat Mar 19 16:23:45 2005
@@ -37,7 +37,9 @@
 //
 bool BUDataStructures::runOnModule(Module &M) {
   LocalDataStructures &LocalDSA = getAnalysis<LocalDataStructures>();
-  GlobalsGraph = new DSGraph(LocalDSA.getGlobalsGraph());
+  GlobalECs = LocalDSA.getGlobalECs();
+
+  GlobalsGraph = new DSGraph(LocalDSA.getGlobalsGraph(), GlobalECs);
   GlobalsGraph->setPrintAuxCalls();
 
   IndCallGraphMap = new std::map<std::vector<Function*>,
@@ -112,7 +114,8 @@
   if (Graph) return *Graph;
 
   // Copy the local version into DSInfo...
-  Graph = new DSGraph(getAnalysis<LocalDataStructures>().getDSGraph(*F));
+  Graph = new DSGraph(getAnalysis<LocalDataStructures>().getDSGraph(*F),
+                      GlobalECs);
 
   Graph->setGlobalsGraph(GlobalsGraph);
   Graph->setPrintAuxCalls();
@@ -379,7 +382,7 @@
             E = CalledFuncs.end();
           
           // Start with a copy of the first graph.
-          GI = IndCallGraph.first = new DSGraph(getDSGraph(**I));
+          GI = IndCallGraph.first = new DSGraph(getDSGraph(**I), GlobalECs);
           GI->setGlobalsGraph(Graph.getGlobalsGraph());
           std::vector<DSNodeHandle> &Args = IndCallGraph.second;
 
@@ -498,7 +501,7 @@
   if (Function *FromF = dyn_cast<Function>(From)) {
     Function *ToF = cast<Function>(To);
     assert(!DSInfo.count(ToF) && "New Function already exists!");
-    DSGraph *NG = new DSGraph(getDSGraph(*FromF));
+    DSGraph *NG = new DSGraph(getDSGraph(*FromF), GlobalECs);
     DSInfo[ToF] = NG;
     assert(NG->getReturnNodes().size() == 1 && "Cannot copy SCC's yet!");
 


Index: llvm/lib/Analysis/DataStructure/CompleteBottomUp.cpp
diff -u llvm/lib/Analysis/DataStructure/CompleteBottomUp.cpp:1.22 llvm/lib/Analysis/DataStructure/CompleteBottomUp.cpp:1.23
--- llvm/lib/Analysis/DataStructure/CompleteBottomUp.cpp:1.22	Fri Mar 18 17:19:47 2005
+++ llvm/lib/Analysis/DataStructure/CompleteBottomUp.cpp	Sat Mar 19 16:23:45 2005
@@ -34,7 +34,7 @@
 //
 bool CompleteBUDataStructures::runOnModule(Module &M) {
   BUDataStructures &BU = getAnalysis<BUDataStructures>();
-  GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
+  GlobalsGraph = new DSGraph(BU.getGlobalsGraph(), GlobalECs);
   GlobalsGraph->setPrintAuxCalls();
 
 #if 1   // REMOVE ME EVENTUALLY
@@ -121,7 +121,7 @@
   if (Graph) return *Graph;
 
   // Copy the BU graph...
-  Graph = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
+  Graph = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F), GlobalECs);
   Graph->setGlobalsGraph(GlobalsGraph);
   Graph->setPrintAuxCalls();
 


Index: llvm/lib/Analysis/DataStructure/DataStructure.cpp
diff -u llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.211 llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.212
--- llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.211	Thu Mar 17 18:23:59 2005
+++ llvm/lib/Analysis/DataStructure/DataStructure.cpp	Sat Mar 19 16:23:45 2005
@@ -115,7 +115,7 @@
   assert(ParentGraph && "Node has no parent?");
   const DSScalarMap &SM = ParentGraph->getScalarMap();
   for (unsigned i = 0, e = Globals.size(); i != e; ++i) {
-    assert(SM.count(Globals[i]));
+    assert(SM.global_count(Globals[i]));
     assert(SM.find(Globals[i])->second.getNode() == this);
   }
 }
@@ -143,6 +143,10 @@
 // marks the node with the 'G' flag if it does not already have it.
 //
 void DSNode::addGlobal(GlobalValue *GV) {
+  // First, check to make sure this is the leader if the global is in an
+  // equivalence class.
+  GV = getParentGraph()->getScalarMap().getLeaderForGlobal(GV);
+
   // Keep the list sorted.
   std::vector<GlobalValue*>::iterator I =
     std::lower_bound(Globals.begin(), Globals.end(), GV);
@@ -1091,14 +1095,16 @@
 }
 
 
-DSGraph::DSGraph(const DSGraph &G) : GlobalsGraph(0), TD(G.TD) {
+DSGraph::DSGraph(const DSGraph &G, EquivalenceClasses<GlobalValue*> &ECs)
+  : GlobalsGraph(0), ScalarMap(ECs), TD(G.TD) {
   PrintAuxCalls = false;
   NodeMapTy NodeMap;
   cloneInto(G, ScalarMap, ReturnNodes, NodeMap);
 }
 
-DSGraph::DSGraph(const DSGraph &G, NodeMapTy &NodeMap)
-  : GlobalsGraph(0), TD(G.TD) {
+DSGraph::DSGraph(const DSGraph &G, NodeMapTy &NodeMap,
+                 EquivalenceClasses<GlobalValue*> &ECs)
+  : GlobalsGraph(0), ScalarMap(ECs), TD(G.TD) {
   PrintAuxCalls = false;
   cloneInto(G, ScalarMap, ReturnNodes, NodeMap);
 }
@@ -1865,8 +1871,9 @@
                               DSGraph::StripIncompleteBit);
 
   // Mark all nodes reachable by (non-global) scalar nodes as alive...
-  { TIME_REGION(Y, "removeDeadNodes:scalarscan");
-  for (DSScalarMap::iterator I = ScalarMap.begin(), E = ScalarMap.end(); I !=E;)
+{ TIME_REGION(Y, "removeDeadNodes:scalarscan");
+  for (DSScalarMap::iterator I = ScalarMap.begin(), E = ScalarMap.end();
+       I != E; ++I)
     if (isa<GlobalValue>(I->first)) {             // Keep track of global nodes
       assert(!I->second.isNull() && "Null global node?");
       assert(I->second.getNode()->isGlobalNode() && "Should be a global node!");
@@ -1881,29 +1888,10 @@
         else
           GGCloner.getClonedNH(I->second);
       }
-      ++I;
     } else {
-      DSNode *N = I->second.getNode();
-#if 0
-      // Check to see if this is a worthless node generated for non-pointer
-      // values, such as integers.  Consider an addition of long types: A+B.
-      // Assuming we can track all uses of the value in this context, and it is
-      // NOT used as a pointer, we can delete the node.  We will be able to
-      // detect this situation if the node pointed to ONLY has Unknown bit set
-      // in the node.  In this case, the node is not incomplete, does not point
-      // to any other nodes (no mod/ref bits set), and is therefore
-      // uninteresting for data structure analysis.  If we run across one of
-      // these, prune the scalar pointing to it.
-      //
-      if (N->getNodeFlags() == DSNode::UnknownNode && !isa<Argument>(I->first))
-        ScalarMap.erase(I++);
-      else {
-#endif
-        N->markReachableNodes(Alive);
-        ++I;
-      //}
+      I->second.getNode()->markReachableNodes(Alive);
     }
-  }
+}
 
   // The return values are alive as well.
   for (ReturnNodesTy::iterator I = ReturnNodes.begin(), E = ReturnNodes.end();


Index: llvm/lib/Analysis/DataStructure/EquivClassGraphs.cpp
diff -u llvm/lib/Analysis/DataStructure/EquivClassGraphs.cpp:1.34 llvm/lib/Analysis/DataStructure/EquivClassGraphs.cpp:1.35
--- llvm/lib/Analysis/DataStructure/EquivClassGraphs.cpp:1.34	Fri Mar 18 23:15:27 2005
+++ llvm/lib/Analysis/DataStructure/EquivClassGraphs.cpp	Sat Mar 19 16:23:45 2005
@@ -72,9 +72,10 @@
 //
 bool EquivClassGraphs::runOnModule(Module &M) {
   CBU = &getAnalysis<CompleteBUDataStructures>();
+  GlobalECs = CBU->getGlobalECs();
   DEBUG(CheckAllGraphs(&M, *CBU));
 
-  GlobalsGraph = new DSGraph(CBU->getGlobalsGraph());
+  GlobalsGraph = new DSGraph(CBU->getGlobalsGraph(), GlobalECs);
   GlobalsGraph->setPrintAuxCalls();
 
   ActualCallees = CBU->getActualCallees();
@@ -305,7 +306,7 @@
   DSGraph &CBUGraph = CBU->getDSGraph(F);
 
   // Copy the CBU graph...
-  Graph = new DSGraph(CBUGraph);           // updates the map via reference
+  Graph = new DSGraph(CBUGraph, GlobalECs);   // updates the map via reference
   Graph->setGlobalsGraph(&getGlobalsGraph());
   Graph->setPrintAuxCalls();
 


Index: llvm/lib/Analysis/DataStructure/Local.cpp
diff -u llvm/lib/Analysis/DataStructure/Local.cpp:1.127 llvm/lib/Analysis/DataStructure/Local.cpp:1.128
--- llvm/lib/Analysis/DataStructure/Local.cpp:1.127	Fri Mar 18 17:18:20 2005
+++ llvm/lib/Analysis/DataStructure/Local.cpp	Sat Mar 19 16:23:45 2005
@@ -164,8 +164,9 @@
 //===----------------------------------------------------------------------===//
 // DSGraph constructor - Simply use the GraphBuilder to construct the local
 // graph.
-DSGraph::DSGraph(const TargetData &td, Function &F, DSGraph *GG)
-  : GlobalsGraph(GG), TD(td) {
+DSGraph::DSGraph(EquivalenceClasses<GlobalValue*> &ECs, const TargetData &td,
+                 Function &F, DSGraph *GG)
+  : GlobalsGraph(GG), ScalarMap(ECs), TD(td) {
   PrintAuxCalls = false;
 
   DEBUG(std::cerr << "  [Loc] Calculating graph for: " << F.getName() << "\n");
@@ -1071,21 +1072,49 @@
 bool LocalDataStructures::runOnModule(Module &M) {
   const TargetData &TD = getAnalysis<TargetData>();
 
-  GlobalsGraph = new DSGraph(TD);
-
+  // First step, build the globals graph.
+  GlobalsGraph = new DSGraph(GlobalECs, TD);
   {
     GraphBuilder GGB(*GlobalsGraph);
     
-    // Add initializers for all of the globals to the globals graph...
-    for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
+    // Add initializers for all of the globals to the globals graph.
+    for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+         I != E; ++I)
       if (!I->isExternal())
         GGB.mergeInGlobalInitializer(I);
   }
 
+  // Next step, iterate through the nodes in the globals graph, unioning
+  // together the globals into equivalence classes.
+  for (DSGraph::node_iterator I = GlobalsGraph->node_begin(),
+         E = GlobalsGraph->node_end(); I != E; ++I)
+    if (I->getGlobals().size() > 1) {
+      // First, build up the equivalence set for this block of globals.
+      const std::vector<GlobalValue*> &GVs = I->getGlobals();
+      GlobalValue *First = GVs[0];
+      for (unsigned i = 1, e = GVs.size(); i != e; ++i)
+        GlobalECs.unionSets(First, GVs[i]);
+
+      // Next, get the leader element.
+      First = GlobalECs.getLeaderValue(First);
+
+      // Next, remove all globals from the scalar map that are not the leader.
+      DSScalarMap &SM = GlobalsGraph->getScalarMap();
+      for (unsigned i = 0, e = GVs.size(); i != e; ++i)
+        if (GVs[i] != First)
+          SM.erase(SM.find(GVs[i]));
+
+      // Finally, change the global node to only contain the leader.
+      I->clearGlobals();
+      I->addGlobal(First);
+    }
+  DEBUG(GlobalsGraph->AssertGraphOK());
+
   // Calculate all of the graphs...
   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
     if (!I->isExternal())
-      DSInfo.insert(std::make_pair(I, new DSGraph(TD, *I, GlobalsGraph)));
+      DSInfo.insert(std::make_pair(I, new DSGraph(GlobalECs, TD, *I,
+                                                  GlobalsGraph)));
 
   GlobalsGraph->removeTriviallyDeadNodes();
   GlobalsGraph->markIncompleteNodes(DSGraph::MarkFormalArgs);


Index: llvm/lib/Analysis/DataStructure/Steensgaard.cpp
diff -u llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.46 llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.47
--- llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.46	Mon Mar 14 22:54:18 2005
+++ llvm/lib/Analysis/DataStructure/Steensgaard.cpp	Sat Mar 19 16:23:45 2005
@@ -26,6 +26,8 @@
   class Steens : public ModulePass, public AliasAnalysis {
     DSGraph *ResultGraph;
     DSGraph *GlobalsGraph;  // FIXME: Eliminate globals graph stuff from DNE
+
+    EquivalenceClasses<GlobalValue*> GlobalECs;  // Always empty
   public:
     Steens() : ResultGraph(0), GlobalsGraph(0) {}
     ~Steens() {
@@ -112,8 +114,8 @@
   LocalDataStructures &LDS = getAnalysis<LocalDataStructures>();
 
   // Create a new, empty, graph...
-  ResultGraph = new DSGraph(getTargetData());
-  GlobalsGraph = new DSGraph(getTargetData());
+  ResultGraph = new DSGraph(GlobalECs, getTargetData());
+  GlobalsGraph = new DSGraph(GlobalECs, getTargetData());
   ResultGraph->setGlobalsGraph(GlobalsGraph);
   ResultGraph->setPrintAuxCalls();
 
@@ -128,7 +130,7 @@
   unsigned Count = 0;
   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
     if (!I->isExternal()) {
-      DSGraph::ScalarMapTy ValMap;
+      DSGraph::ScalarMapTy ValMap(GlobalECs);
       {  // Scope to free NodeMap memory ASAP
         DSGraph::NodeMapTy NodeMap;
         const DSGraph &FDSG = LDS.getDSGraph(*I);


Index: llvm/lib/Analysis/DataStructure/TopDownClosure.cpp
diff -u llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.75 llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.76
--- llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.75	Tue Mar 15 10:55:04 2005
+++ llvm/lib/Analysis/DataStructure/TopDownClosure.cpp	Sat Mar 19 16:23:45 2005
@@ -53,7 +53,8 @@
 //
 bool TDDataStructures::runOnModule(Module &M) {
   BUDataStructures &BU = getAnalysis<BUDataStructures>();
-  GlobalsGraph = new DSGraph(BU.getGlobalsGraph());
+  GlobalECs = BU.getGlobalECs();
+  GlobalsGraph = new DSGraph(BU.getGlobalsGraph(), GlobalECs);
   GlobalsGraph->setPrintAuxCalls();
 
   // Figure out which functions must not mark their arguments complete because
@@ -115,7 +116,7 @@
 DSGraph &TDDataStructures::getOrCreateDSGraph(Function &F) {
   DSGraph *&G = DSInfo[&F];
   if (G == 0) { // Not created yet?  Clone BU graph...
-    G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F));
+    G = new DSGraph(getAnalysis<BUDataStructures>().getDSGraph(F), GlobalECs);
     G->getAuxFunctionCalls().clear();
     G->setPrintAuxCalls();
     G->setGlobalsGraph(GlobalsGraph);
@@ -324,7 +325,7 @@
   if (Function *FromF = dyn_cast<Function>(From)) {
     Function *ToF = cast<Function>(To);
     assert(!DSInfo.count(ToF) && "New Function already exists!");
-    DSGraph *NG = new DSGraph(getDSGraph(*FromF));
+    DSGraph *NG = new DSGraph(getDSGraph(*FromF), GlobalECs);
     DSInfo[ToF] = NG;
     assert(NG->getReturnNodes().size() == 1 && "Cannot copy SCC's yet!");
 






More information about the llvm-commits mailing list