[llvm-commits] [poolalloc] r114971 - in /poolalloc/trunk: include/poolalloc/Heuristic.h lib/PoolAllocate/Heuristic.cpp lib/PoolAllocate/PoolAllocate.cpp

John Criswell criswell at uiuc.edu
Tue Sep 28 11:17:13 PDT 2010


Author: criswell
Date: Tue Sep 28 13:17:13 2010
New Revision: 114971

URL: http://llvm.org/viewvc/llvm-project?rev=114971&view=rev
Log:
Moved the code that decides which DSNodes get global pools into the Heuristic
passes (the findGlobalPoolNodes() method).
Fixed a bug in the constructor of the AllNodes intrinsic.
Made poolalloc preserve the heuristic pass for good measure.

Modified:
    poolalloc/trunk/include/poolalloc/Heuristic.h
    poolalloc/trunk/lib/PoolAllocate/Heuristic.cpp
    poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp

Modified: poolalloc/trunk/include/poolalloc/Heuristic.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/poolalloc/Heuristic.h?rev=114971&r1=114970&r2=114971&view=diff
==============================================================================
--- poolalloc/trunk/include/poolalloc/Heuristic.h (original)
+++ poolalloc/trunk/include/poolalloc/Heuristic.h Tue Sep 28 13:17:13 2010
@@ -48,6 +48,7 @@
   protected:
     Module *M;
     PoolAllocate *PA;
+    DataStructures *Graphs;
 
   public:
     // Virtual Destructor
@@ -93,6 +94,9 @@
       }
     };
 
+    /// Find globally reachable DSNodes that need a pool
+    virtual void findGlobalPoolNodes (std::vector<const DSNode *> & Nodes);
+
     /// AssignToPools - Partition NodesToPA into a set of disjoint pools,
     /// returning the result in ResultPools.  If this is a function being pool
     /// allocated, F will not be null.
@@ -139,9 +143,12 @@
         return this;
       }
 
-      AllNodesHeuristic (intptr_t IDp = (intptr_t) (&ID)): ModulePass (&IDp) { }
+      AllNodesHeuristic (intptr_t IDp = (intptr_t) (&ID)): ModulePass (IDp) { }
       virtual ~AllNodesHeuristic () {return;}
       virtual bool runOnModule (Module & M);
+      virtual const char * getPassName () const {
+        return "All Nodes Pool Allocation Heurisitic";
+      }
 
       virtual void getAnalysisUsage(AnalysisUsage &AU) const {
         // We require DSA while this pass is still responding to queries

Modified: poolalloc/trunk/lib/PoolAllocate/Heuristic.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/Heuristic.cpp?rev=114971&r1=114970&r2=114971&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/Heuristic.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/Heuristic.cpp Tue Sep 28 13:17:13 2010
@@ -205,7 +205,164 @@
 
   return 4;
 }
- 
+
+//
+// Function: GetNodesReachableFromGlobals()
+//
+// Description:
+//  This function finds all DSNodes which are reachable from globals.  It finds
+//  DSNodes both within the local DSGraph as well as in the Globals graph that
+//  are reachable from globals.
+//
+// Inputs:
+//  G - The DSGraph for which to find DSNodes which are reachable by globals.
+//      This DSGraph can either by a DSGraph associated with a function *or*
+//      it can be the globals graph itself.
+//
+// Outputs:
+//  NodesFromGlobals - A reference to a container object in which to record
+//                     DSNodes reachable from globals.  DSNodes are *added* to
+//                     this container; it is not cleared by this function.
+//                     DSNodes from both the local and globals graph are added.
+static void
+GetNodesReachableFromGlobals (DSGraph* G,
+                              DenseSet<const DSNode*> &NodesFromGlobals) {
+  //
+  // Get the globals graph associated with this DSGraph.  If the globals graph
+  // is NULL, then the graph that was passed in *is* the globals graph.
+  //
+  DSGraph * GlobalsGraph = G->getGlobalsGraph();
+  if (!GlobalsGraph)
+    GlobalsGraph = G;
+
+  //
+  // Find all DSNodes which are reachable in the globals graph.
+  //
+  for (DSGraph::node_iterator NI = GlobalsGraph->node_begin();
+       NI != GlobalsGraph->node_end();
+       ++NI) {
+    NI->markReachableNodes(NodesFromGlobals);
+  }
+
+  //
+  // Now the fun part.  Find DSNodes in the local graph that correspond to
+  // those nodes reachable in the globals graph.  Add them to the set of
+  // reachable nodes, too.
+  //
+  if (G->getGlobalsGraph()) {
+    //
+    // Compute a mapping between local DSNodes and DSNodes in the globals
+    // graph.
+    //
+    DSGraph::NodeMapTy NodeMap;
+    G->computeGToGGMapping (NodeMap);
+
+    //
+    // Scan through all DSNodes in the local graph.  If a local DSNode has a
+    // corresponding DSNode in the globals graph that is reachable from a 
+    // global, then add the local DSNode to the set of DSNodes reachable from a
+    // global.
+    //
+    // FIXME: A node's existance within the global DSGraph is probably
+    //        sufficient evidence that it is reachable from a global.
+    //
+    DSGraph::node_iterator ni = G->node_begin();
+    for (; ni != G->node_end(); ++ni) {
+      DSNode * N = ni;
+      if (NodesFromGlobals.count (NodeMap[N].getNode()))
+        NodesFromGlobals.insert (N);
+    }
+  }
+}
+
+//
+// Method: findGlobalPoolNodes()
+//
+// Description:
+//  This method finds DSNodes that are reachable from globals and that need a
+//  pool.  The Automatic Pool Allocation transform will use the returned
+//  information to build global pools for the DSNodes in question.
+//
+//  Note that this method does not assign DSNodes to pools; it merely decides
+//  which DSNodes are reachable from globals and will need a pool of global
+//  scope.
+//
+// Outputs:
+//  Nodes - The DSNodes that are both reachable from globals and which should
+//          have global pools will be *added* to this container.
+//
+void
+Heuristic::findGlobalPoolNodes (std::vector<const DSNode *> & Nodes) {
+  // Get the globals graph for the program.
+  DSGraph* GG = Graphs->getGlobalsGraph();
+
+  // Get all of the nodes reachable from globals.
+  DenseSet<const DSNode*> GlobalHeapNodes;
+  GetNodesReachableFromGlobals (GG, GlobalHeapNodes);
+
+  //
+  // We do not want to create pools for all memory objects reachable from
+  // globals.  We only want those that are or could be heap objects.
+  //
+  std::vector<const DSNode *> toRemove;
+  for (DenseSet<const DSNode*>::iterator I = GlobalHeapNodes.begin(),
+         E = GlobalHeapNodes.end(); I != E; ) {
+    DenseSet<const DSNode*>::iterator Last = I; ++I;
+
+    //
+    // Nodes that escape to external code could be reachable from globals.
+    // Nodes that are incomplete could be heap nodes.
+    // Unknown nodes could be anything.
+    //
+    const DSNode *tmp = *Last;
+    if (!(tmp->isHeapNode() ||
+          tmp->isExternalNode() ||
+          tmp->isIncompleteNode() ||
+          tmp->isUnknownNode()))
+      toRemove.push_back (tmp);
+  }
+  
+  //
+  // Remove all globally reachable DSNodes which do not require pools.
+  //
+  for (unsigned index = 0; index < toRemove.size(); ++index) {
+    GlobalHeapNodes.erase(toRemove[index]);
+  }
+
+  //
+  // Scan through all the local graphs looking for DSNodes which may be
+  // reachable by a global.  These nodes may not end up in the globals graph 
+  // because of the fact that DSA doesn't actually know what is happening to
+  // them.
+  //
+  for (Module::iterator F = M->begin(); F != M->end(); ++F) {
+    if (F->isDeclaration()) continue;
+    DSGraph* G = Graphs->getDSGraph(*F);
+    for (DSGraph::node_iterator I = G->node_begin(), E = G->node_end();
+         I != E;
+         ++I) {
+      DSNode * Node = I;
+      if (Node->isExternalNode() || Node->isIncompleteNode() ||
+          Node->isUnknownNode()) {
+        GlobalHeapNodes.insert (Node);
+      }
+    }
+  }
+
+  //
+  // Copy the values into the output container.  Note that DenseSet has no
+  // iterator traits (or whatever allows us to treat DenseSet has a generic
+  // container), so we have to use a loop to copy values from the DenseSet into
+  // the output container.
+  //
+  for (DenseSet<const DSNode*>::iterator I = GlobalHeapNodes.begin(),
+         E = GlobalHeapNodes.end(); I != E; ++I) {
+    Nodes.push_back (*I);
+  }
+
+  return;
+}
+
 //===-- AllNodes Heuristic ------------------------------------------------===//
 //
 // This heuristic pool allocates everything possible into separate pools.
@@ -218,6 +375,13 @@
   //
   M = &Module;
 
+  //
+  // Get the reference to the DSA Graph.
+  //
+  Graphs = &getAnalysis<EQTDDataStructures>();   
+  assert (Graphs && "No DSGraphs!\n");
+  std::cerr << "JTC: Ran on Module: " << this << std::endl;
+
   // We never modify anything in this pass
   return false;
 }
@@ -244,6 +408,11 @@
   //
   M = &Module;
 
+  //
+  // Get the reference to the DSA Graph.
+  //
+  Graphs = &getAnalysis<EQTDDataStructures>();   
+
   // We never modify anything in this pass
   return false;
 }
@@ -307,6 +476,11 @@
   //
   M = &Module;
 
+  //
+  // Get the reference to the DSA Graph.
+  //
+  Graphs = &getAnalysis<EQTDDataStructures>();   
+
   // We never modify anything in this pass
   return false;
 }
@@ -339,6 +513,11 @@
   //
   M = &Module;
 
+  //
+  // Get the reference to the DSA Graph.
+  //
+  Graphs = &getAnalysis<EQTDDataStructures>();   
+
   // We never modify anything in this pass
   return false;
 }
@@ -525,6 +704,11 @@
   //
   M = &Module;
 
+  //
+  // Get the reference to the DSA Graph.
+  //
+  Graphs = &getAnalysis<EQTDDataStructures>();   
+
   // We never modify anything in this pass
   return false;
 }
@@ -557,6 +741,11 @@
   //
   M = &Module;
 
+  //
+  // Get the reference to the DSA Graph.
+  //
+  Graphs = &getAnalysis<EQTDDataStructures>();   
+
   // We never modify anything in this pass
   return false;
 }
@@ -657,13 +846,13 @@
 F ("paheur-OnlyOverhead", "Do not pool allocate anything, but induce all overhead from it");
 
 static RegisterPass<NoNodesHeuristic>
-G ("paheur-NoNodes", "Pool allocate nothing");
+G ("paheur-NoNodes", "Pool allocate nothing heuristic");
 
 //
 // Create the heuristic analysis group.
 //
-//static RegisterAnalysisGroup<Heuristic>
-//HeuristicGroup ("Pool Allocation Heuristic");
+static RegisterAnalysisGroup<Heuristic>
+HeuristicGroup ("Pool Allocation Heuristic");
 
 RegisterAnalysisGroup<Heuristic> Heuristic1(A);
 RegisterAnalysisGroup<Heuristic> Heuristic2(B);

Modified: poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp?rev=114971&r1=114970&r2=114971&view=diff
==============================================================================
--- poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp (original)
+++ poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp Tue Sep 28 13:17:13 2010
@@ -108,6 +108,7 @@
 void PoolAllocate::getAnalysisUsage(AnalysisUsage &AU) const {
   // We will need the heuristic pass to tell us what to do and how to do it
   AU.addRequired<Heuristic>();
+  AU.addPreserved<Heuristic>();
   if (dsa_pass_to_use == PASS_EQTD) {
     AU.addRequiredTransitive<EQTDDataStructures>();
     if(lie_preserve_passes != LIE_NONE)
@@ -862,87 +863,12 @@
 // global pools.
 //
 bool PoolAllocate::SetupGlobalPools(Module &M) {
-  // Get the globals graph for the program.
-  DSGraph* GG = Graphs->getGlobalsGraph();
-
-  // Get all of the nodes reachable from globals.
-  DenseSet<const DSNode*> GlobalHeapNodes;
-  GetNodesReachableFromGlobals(GG, GlobalHeapNodes);
-
-  //
-  // We do not want to create pools for all memory objects reachable from
-  // globals.  We only want those that are heap objects, could be heap objects,
-  // or are array objects.
-  //
-  std::vector<const DSNode *> toRemove;
-  for (DenseSet<const DSNode*>::iterator I = GlobalHeapNodes.begin(),
-         E = GlobalHeapNodes.end(); I != E; ) {
-    DenseSet<const DSNode*>::iterator Last = I; ++I;
-
-    //
-    // FIXME: If the PoolAllocateAllGlobalNodes option is selected for the
-    //        heuristic, then we should make global pools for heap and
-    //        non-heap DSNodes.
-    //
-#if 0
-    //
-    // FIXME:
-    //  This code was disabled for regular pool allocation, but I don't know
-    //  why.
-    //
-    if (!SAFECodeEnabled) {
-      if (!(*Last)->isHeapNode());
-      GlobalHeapNodes.erase(Last);
-    }
-#endif
-
-    //
-    // Nodes that escape to external code could be reachable from globals.
-    // Nodes that are incomplete could be heap nodes.
-    // Unknown nodes could be anything.
-    //
-    const DSNode *tmp = *Last;
-    if (!(tmp->isHeapNode() || tmp->isArrayNode() ||
-          tmp->isExternalNode() || tmp->isIncompleteNode() ||
-          tmp->isUnknownNode()))
-      toRemove.push_back (tmp);
-  }
-  
   //
-  // Remove all the DSNodes for which we do not want to create a global pool.
+  // Find all of the DSNodes which are reachable from globals and may require
+  // pools.
   //
-  while (toRemove.size()) {
-    const DSNode * Node = toRemove.back();
-    toRemove.pop_back();
-    GlobalHeapNodes.erase(Node);
-  }
-
-  //
-  // Scan through all the local graphs looking for DSNodes which may be
-  // reachable by a global.  These nodes may not end up in the globals graph 
-  // because of the fact that DSA doesn't actually know what is happening to
-  // them.
-  //
-  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
-    if (F->isDeclaration()) continue;
-    DSGraph* G = Graphs->getDSGraph(*F);
-    for (DSGraph::node_iterator I = G->node_begin(), E = G->node_end();
-         I != E;
-         ++I){
-      DSNode * Node = I;
-      if (Node->isExternalNode() || Node->isIncompleteNode() ||
-          Node->isUnknownNode()) {
-        GlobalHeapNodes.insert (Node);
-      }
-
-      //
-      // If a DSNode is used as an array and bounds checking is enabled,
-      // then also give it a global node.
-      //
-      if (BoundsChecksEnabled && (Node->isArrayNode()))
-        GlobalHeapNodes.insert (Node);
-    }
-  }
+  std::vector<const DSNode*> NodesToPA;
+  CurHeuristic->findGlobalPoolNodes (NodesToPA);
 
   // Otherwise get the main function to insert the poolinit calls.
   Function *MainFunc = M.getFunction("main");
@@ -952,23 +878,21 @@
     return true;
   }
 
-  errs() << "Pool allocating " << GlobalHeapNodes.size()
-            << " global nodes!\n";
-
-
-  //std::vector<const DSNode*> NodesToPA(GlobalHeapNodes.begin(),
-  //                                     GlobalHeapNodes.end());
-  //FIXME: Explain in more detail: DenseSet Doesn't have polite iterators
-  std::vector<const DSNode*> NodesToPA;
-  for (DenseSet<const DSNode*>::iterator ii = GlobalHeapNodes.begin(),
-         ee = GlobalHeapNodes.end(); ii != ee; ++ii)
-    NodesToPA.push_back(*ii);
+  errs() << "Pool allocating " << NodesToPA.size() << " global nodes!\n";
 
+  DSGraph* GG = Graphs->getGlobalsGraph();
   std::vector<Heuristic::OnePool> ResultPools;
   CurHeuristic->AssignToPools(NodesToPA, 0, GG, ResultPools);
 
   BasicBlock::iterator InsertPt = MainFunc->getEntryBlock().begin();
 
+  //
+  // Create a set of the DSNodes globally reachable from memory.  We'll assign
+  // NULL pool handles for those nodes which are globally reachable but for
+  // which the heuristic did not assign a pool.
+  //
+  std::set<const DSNode *> GlobalHeapNodes (NodesToPA.begin(), NodesToPA.end());
+
   // Perform all global assignments as specified.
   for (unsigned i = 0, e = ResultPools.size(); i != e; ++i) {
     Heuristic::OnePool &Pool = ResultPools[i];
@@ -987,12 +911,12 @@
   }
 
   // Any unallocated DSNodes get null pool descriptor pointers.
-  for (DenseSet<const DSNode*>::iterator I = GlobalHeapNodes.begin(),
+  for (std::set<const DSNode*>::iterator I = GlobalHeapNodes.begin(),
          E = GlobalHeapNodes.end(); I != E; ++I) {
     GlobalNodes[*I] = ConstantPointerNull::get(PointerType::getUnqual(PoolDescType));
     ++NumNonprofit;
   }
-  
+
   return false;
 }
 





More information about the llvm-commits mailing list