[llvm-commits] CVS: llvm/lib/Analysis/DataStructure/DataStructure.cpp

Chris Lattner lattner at cs.uiuc.edu
Mon Feb 3 13:13:01 PST 2003


Changes in directory llvm/lib/Analysis/DataStructure:

DataStructure.cpp updated: 1.83 -> 1.84

---
Log message:

Implement the globals graph!


---
Diffs of the changes:

Index: llvm/lib/Analysis/DataStructure/DataStructure.cpp
diff -u llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.83 llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.84
--- llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.83	Sat Feb  1 00:54:31 2003
+++ llvm/lib/Analysis/DataStructure/DataStructure.cpp	Mon Feb  3 13:12:15 2003
@@ -233,7 +233,8 @@
       break;
     }
     default:
-      assert(0 && "Unknown type!");
+      foldNodeCompletely();
+      return true;
     }
   }
 
@@ -616,15 +617,12 @@
 
   // Remove alloca markers as specified
   if (CloneFlags & (StripAllocaBit | StripModRefBits)) {
-    unsigned short clearBits =   (CloneFlags & StripAllocaBit
-                                  ? DSNode::AllocaNode : 0)
-                               | (CloneFlags & StripModRefBits
-                                  ? (DSNode::Modified | DSNode::Read) : 0);
-    for (unsigned i = FN, e = Nodes.size(); i != e; ++i)
-      Nodes[i]->NodeType &= ~clearBits;
+    unsigned clearBits = (CloneFlags & StripAllocaBit ? DSNode::AllocaNode : 0)
+       | (CloneFlags & StripModRefBits ? (DSNode::Modified | DSNode::Read) : 0);
+    maskNodeTypes(~clearBits);
   }
 
-  // Copy the value map... and merge all of the global nodes...
+  // Copy the scalar map... merging all of the global nodes...
   for (hash_map<Value*, DSNodeHandle>::const_iterator I = G.ScalarMap.begin(),
          E = G.ScalarMap.end(); I != E; ++I) {
     DSNodeHandle &H = OldValMap[I->first];
@@ -634,11 +632,10 @@
 
     if (isa<GlobalValue>(I->first)) {  // Is this a global?
       hash_map<Value*, DSNodeHandle>::iterator GVI = ScalarMap.find(I->first);
-      if (GVI != ScalarMap.end()) {   // Is the global value in this fn already?
+      if (GVI != ScalarMap.end())     // Is the global value in this fn already?
         GVI->second.mergeWith(H);
-      } else {
+      else
         ScalarMap[I->first] = H;      // Add global pointer to this graph
-      }
     }
   }
 
@@ -716,33 +713,6 @@
   }
 }
 
-#if 0
-// cloneGlobalInto - Clone the given global node and all its target links
-// (and all their llinks, recursively).
-// 
-DSNode *DSGraph::cloneGlobalInto(const DSNode *GNode) {
-  if (GNode == 0 || GNode->getGlobals().size() == 0) return 0;
-
-  // If a clone has already been created for GNode, return it.
-  DSNodeHandle& ValMapEntry = ScalarMap[GNode->getGlobals()[0]];
-  if (ValMapEntry != 0)
-    return ValMapEntry;
-
-  // Clone the node and update the ValMap.
-  DSNode* NewNode = new DSNode(*GNode);
-  ValMapEntry = NewNode;                // j=0 case of loop below!
-  Nodes.push_back(NewNode);
-  for (unsigned j = 1, N = NewNode->getGlobals().size(); j < N; ++j)
-    ScalarMap[NewNode->getGlobals()[j]] = NewNode;
-
-  // Rewrite the links in the new node to point into the current graph.
-  for (unsigned j = 0, e = GNode->getNumLinks(); j != e; ++j)
-    NewNode->setLink(j, cloneGlobalInto(GNode->getLink(j)));
-
-  return NewNode;
-}
-#endif
-
 
 // markIncompleteNodes - Mark the specified node as having contents that are not
 // known with the current analysis we have performed.  Because a node makes all
@@ -808,27 +778,6 @@
     }
 }
 
-// removeRefsToGlobal - Helper function that removes globals from the
-// ScalarMap so that the referrer count will go down to zero.
-static void removeRefsToGlobal(DSNode* N,
-                               hash_map<Value*, DSNodeHandle> &ScalarMap) {
-  while (!N->getGlobals().empty()) {
-    GlobalValue *GV = N->getGlobals().back();
-    N->getGlobals().pop_back();      
-    ScalarMap.erase(GV);
-  }
-}
-
-
-// isNodeDead - This method checks to see if a node is dead, and if it isn't, it
-// checks to see if there are simple transformations that it can do to make it
-// dead.
-//
-bool DSGraph::isNodeDead(DSNode *N) {
-  // Is it a trivially dead shadow node?
-  return N->getReferrers().empty() && (N->NodeType & ~DSNode::DEAD) == 0;
-}
-
 static inline void killIfUselessEdge(DSNodeHandle &Edge) {
   if (DSNode *N = Edge.getNode())  // Is there an edge?
     if (N->getReferrers().size() == 1)  // Does it point to a lonely node?
@@ -927,11 +876,32 @@
   removeIdenticalCalls(FunctionCalls, Func ? Func->getName() : "");
   removeIdenticalCalls(AuxFunctionCalls, Func ? Func->getName() : "");
 
-  for (unsigned i = 0; i != Nodes.size(); ++i)
-    if (isNodeDead(Nodes[i])) {               // This node is dead!
-      delete Nodes[i];                        // Free memory...
+  for (unsigned i = 0; i != Nodes.size(); ++i) {
+    DSNode *Node = Nodes[i];
+    if (!(Node->NodeType & ~(DSNode::Composition | DSNode::Array |
+                                 DSNode::DEAD))) {
+      // This is a useless node if it has no mod/ref info (checked above),
+      // outgoing edges (which it cannot, as it is not modified in this
+      // context), and it has no incoming edges.  If it is a global node it may
+      // have all of these properties and still have incoming edges, due to the
+      // scalar map, so we check those now.
+      //
+      if (Node->getReferrers().size() == Node->getGlobals().size()) {
+        std::vector<GlobalValue*> &Globals = Node->getGlobals();
+        for (unsigned j = 0, e = Globals.size(); j != e; ++j)
+          ScalarMap.erase(Globals[j]);
+        Globals.clear();
+          
+        Node->NodeType = DSNode::DEAD;
+      }
+    }
+
+    if ((Node->NodeType & ~DSNode::DEAD) == 0 &&
+        Node->getReferrers().empty()) {   // This node is dead!
+      delete Node;                        // Free memory...
       Nodes.erase(Nodes.begin()+i--);         // Remove from node list...
     }
+  }
 }
 
 
@@ -952,8 +922,8 @@
   getRetVal().getNode()->markReachableNodes(Nodes);
   getCallee().getNode()->markReachableNodes(Nodes);
   
-  for (unsigned j = 0, e = getNumPtrArgs(); j != e; ++j)
-    getPtrArg(j).getNode()->markReachableNodes(Nodes);
+  for (unsigned i = 0, e = getNumPtrArgs(); i != e; ++i)
+    getPtrArg(i).getNode()->markReachableNodes(Nodes);
 }
 
 // CanReachAliveNodes - Simple graph walker that recursively traverses the graph
@@ -989,30 +959,12 @@
   if (CanReachAliveNodes(CS.getRetVal().getNode(), Alive, Visited) ||
       CanReachAliveNodes(CS.getCallee().getNode(), Alive, Visited))
     return true;
-  for (unsigned j = 0, e = CS.getNumPtrArgs(); j != e; ++j)
-    if (CanReachAliveNodes(CS.getPtrArg(j).getNode(), Alive, Visited))
+  for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i)
+    if (CanReachAliveNodes(CS.getPtrArg(i).getNode(), Alive, Visited))
       return true;
   return false;
 }
 
-// GlobalIsAlivenessRoot - Return true if the specified global node is
-// intrinsically alive in the context of the current graph (ie, it is a root of
-// aliveness).  For TD graphs, no globals are.  For the BU graphs all are unless
-// they are trivial globals...
-//
-static bool GlobalIsAlivenessRoot(DSNode *N, unsigned Flags) {
-  if (Flags & DSGraph::RemoveUnreachableGlobals)
-    return false;                 // If we are to remove all globals, go for it.
-
-  // Ok, we are keeping globals... hrm, we can still delete it if it has no
-  // links, and no mod/ref or other info...  If it is not modified, it can't
-  // have links...
-  //
-  if ((N->NodeType & ~(DSNode::Composition | DSNode::Array)) == 0)
-    return false;
-  return true;
-}
-
 // removeDeadNodes - Use a more powerful reachability analysis to eliminate
 // subgraphs that are unreachable.  This often occurs because the data
 // structure doesn't "escape" into it's caller, and thus should be eliminated
@@ -1020,7 +972,8 @@
 // inlining graphs.
 //
 void DSGraph::removeDeadNodes(unsigned Flags) {
-  // Reduce the amount of work we have to do...
+  // Reduce the amount of work we have to do... remove dummy nodes left over by
+  // merging...
   removeTriviallyDeadNodes();
 
   // FIXME: Merge nontrivially identical call nodes...
@@ -1032,75 +985,133 @@
   // Mark all nodes reachable by (non-global) scalar nodes as alive...
   for (hash_map<Value*, DSNodeHandle>::iterator I = ScalarMap.begin(),
          E = ScalarMap.end(); I != E; ++I)
-    if (!isa<GlobalValue>(I->first) ||
-        GlobalIsAlivenessRoot(I->second.getNode(), Flags))
+    if (!isa<GlobalValue>(I->first))
       I->second.getNode()->markReachableNodes(Alive);
-    else                    // Keep track of global nodes
+    else {                   // Keep track of global nodes
       GlobalNodes.push_back(std::make_pair(I->first, I->second.getNode()));
+      assert(I->second.getNode() && "Null global node?");
+    }
 
   // The return value is alive as well...
   RetNode.getNode()->markReachableNodes(Alive);
 
-  // If any global nodes points to a non-global that is "alive", the global is
-  // "alive" as well...
-  //
-  hash_set<DSNode*> Visited;
-  for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
-    CanReachAliveNodes(GlobalNodes[i].second, Alive, Visited);
-
-  std::vector<bool> FCallsAlive(FunctionCalls.size());
+  // Mark any nodes reachable by primary calls as alive...
   for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i)
-    if (!(Flags & DSGraph::RemoveUnreachableGlobals) ||
-        CallSiteUsesAliveArgs(FunctionCalls[i], Alive, Visited)) {
-      FunctionCalls[i].markReachableNodes(Alive);
-      FCallsAlive[i] = true;
-    }
+    FunctionCalls[i].markReachableNodes(Alive);
 
-  std::vector<bool> AuxFCallsAlive(AuxFunctionCalls.size());
-  for (unsigned i = 0, e = AuxFunctionCalls.size(); i != e; ++i)
-    if (!(Flags & DSGraph::RemoveUnreachableGlobals) ||
-        CallSiteUsesAliveArgs(AuxFunctionCalls[i], Alive, Visited)) {
-      AuxFunctionCalls[i].markReachableNodes(Alive);
-      AuxFCallsAlive[i] = true;
-    }
+  bool Iterate;
+  hash_set<DSNode*> Visited;
+  std::vector<unsigned char> AuxFCallsAlive(AuxFunctionCalls.size());
+  do {
+    Visited.clear();
+    // If any global nodes points to a non-global that is "alive", the global is
+    // "alive" as well...  Remov it from the GlobalNodes list so we only have
+    // unreachable globals in the list.
+    //
+    Iterate = false;
+    for (unsigned i = 0; i != GlobalNodes.size(); ++i)
+      if (CanReachAliveNodes(GlobalNodes[i].second, Alive, Visited)) {
+        std::swap(GlobalNodes[i--], GlobalNodes.back()); // Move to end to erase
+        GlobalNodes.pop_back();                          // Erase efficiently
+        Iterate = true;
+      }
 
-  // Remove all dead function calls...
-  unsigned CurIdx = 0;
-  for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i)
-    if (FCallsAlive[i])
-      FunctionCalls[CurIdx++].swap(FunctionCalls[i]);
-  // Crop all the bad ones out...
-  FunctionCalls.erase(FunctionCalls.begin()+CurIdx, FunctionCalls.end());
+    for (unsigned i = 0, e = AuxFunctionCalls.size(); i != e; ++i)
+      if (!AuxFCallsAlive[i] &&
+          CallSiteUsesAliveArgs(AuxFunctionCalls[i], Alive, Visited)) {
+        AuxFunctionCalls[i].markReachableNodes(Alive);
+        AuxFCallsAlive[i] = true;
+        Iterate = true;
+      }
+  } while (Iterate);
 
   // Remove all dead aux function calls...
-  CurIdx = 0;
+  unsigned CurIdx = 0;
   for (unsigned i = 0, e = AuxFunctionCalls.size(); i != e; ++i)
     if (AuxFCallsAlive[i])
       AuxFunctionCalls[CurIdx++].swap(AuxFunctionCalls[i]);
-  // Crop all the bad ones out...
+  if (!(Flags & DSGraph::RemoveUnreachableGlobals)) {
+    // Move the unreachable call nodes to the globals graph...
+    GlobalsGraph->AuxFunctionCalls.insert(GlobalsGraph->AuxFunctionCalls.end(),
+                                          AuxFunctionCalls.begin()+CurIdx,
+                                          AuxFunctionCalls.end());
+  }
+  // Crop all the useless ones out...
   AuxFunctionCalls.erase(AuxFunctionCalls.begin()+CurIdx,
                          AuxFunctionCalls.end());
 
-
-  // Remove all unreachable globals from the ScalarMap
-  for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
-    if (!Alive.count(GlobalNodes[i].second))
-      ScalarMap.erase(GlobalNodes[i].first);
-
-  // Loop over all unreachable nodes, dropping their references...
+  // At this point, any nodes which are visited, but not alive, are nodes which
+  // should be moved to the globals graph.  Loop over all nodes, eliminating
+  // completely unreachable nodes, and moving visited nodes to the globals graph
+  //
   for (unsigned i = 0; i != Nodes.size(); ++i)
     if (!Alive.count(Nodes[i])) {
       DSNode *N = Nodes[i];
       std::swap(Nodes[i--], Nodes.back());  // move node to end of vector
       Nodes.pop_back();                // Erase node from alive list.
-      N->dropAllReferences();          // Drop all outgoing edges
+      if (!(Flags & DSGraph::RemoveUnreachableGlobals) &&  // Not in TD pass
+          Visited.count(N)) {                    // Visited but not alive?
+        GlobalsGraph->Nodes.push_back(N);        // Move node to globals graph
+      } else {                                 // Otherwise, delete the node
+        assert(((N->NodeType & DSNode::GlobalNode) == 0 ||
+                (Flags & DSGraph::RemoveUnreachableGlobals))
+               && "Killing a global?");
+        while (!N->getReferrers().empty())       // Rewrite referrers
+          N->getReferrers().back()->setNode(0);
+        delete N;                                // Usecount is zero
+      }
+    }
+
+  // Now that the nodes have either been deleted or moved to the globals graph,
+  // loop over the scalarmap, updating the entries for globals...
+  //
+  if (!(Flags & DSGraph::RemoveUnreachableGlobals)) {  // Not in the TD pass?
+    // In this array we start the remapping, which can cause merging.  Because
+    // of this, the DSNode pointers in GlobalNodes may be invalidated, so we
+    // must always go through the ScalarMap (which contains DSNodeHandles [which
+    // cannot be invalidated by merging]).
+    //
+    for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i) {
+      Value *G = GlobalNodes[i].first;
+      hash_map<Value*, DSNodeHandle>::iterator I = ScalarMap.find(G);
+      assert(I != ScalarMap.end() && "Global not in scalar map anymore?");
+      assert(I->second.getNode() && "Global not pointing to anything?");
+      assert(!Alive.count(I->second.getNode()) && "Node is alive??");
+      GlobalsGraph->ScalarMap[G].mergeWith(I->second);
+      assert(GlobalsGraph->ScalarMap[G].getNode() &&
+             "Global not pointing to anything?");
+      ScalarMap.erase(I);
+    }
+
+    // Merging leaves behind silly nodes, we remove them to avoid polluting the
+    // globals graph.
+    GlobalsGraph->removeTriviallyDeadNodes();
+  } else {
+    // If we are in the top-down pass, remove all unreachable globals from the
+    // ScalarMap...
+    for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
+      ScalarMap.erase(GlobalNodes[i].first);
+  }
+
+  DEBUG(AssertGraphOK(); GlobalsGraph->AssertGraphOK());
+}
 
-      while (!N->getReferrers().empty())
-        N->getReferrers().back()->setNode(0);
-      delete N;
+void DSGraph::AssertGraphOK() const {
+  for (hash_map<Value*, DSNodeHandle>::const_iterator I = ScalarMap.begin(),
+         E = ScalarMap.end(); I != E; ++I) {
+    assert(I->second.getNode() && "Null node in scalarmap!");
+    AssertNodeInGraph(I->second.getNode());
+    if (GlobalValue *GV = dyn_cast<GlobalValue>(I->first)) {
+      assert((I->second.getNode()->NodeType & DSNode::GlobalNode) &&
+             "Global points to node, but node isn't global?");
+      AssertNodeContainsGlobal(I->second.getNode(), GV);
     }
+  }
+  AssertCallNodesInGraph();
+  AssertAuxCallNodesInGraph();
 }
 
+
 #if 0
 //===----------------------------------------------------------------------===//
 // GlobalDSGraph Implementation
@@ -1110,6 +1121,30 @@
 // Bits used in the next function
 static const char ExternalTypeBits = DSNode::GlobalNode | DSNode::HeapNode;
 
+// cloneGlobalInto - Clone the given global node and all its target links
+// (and all their llinks, recursively).
+// 
+DSNode *DSGraph::cloneGlobalInto(const DSNode *GNode) {
+  if (GNode == 0 || GNode->getGlobals().size() == 0) return 0;
+
+  // If a clone has already been created for GNode, return it.
+  DSNodeHandle& ValMapEntry = ScalarMap[GNode->getGlobals()[0]];
+  if (ValMapEntry != 0)
+    return ValMapEntry;
+
+  // Clone the node and update the ValMap.
+  DSNode* NewNode = new DSNode(*GNode);
+  ValMapEntry = NewNode;                // j=0 case of loop below!
+  Nodes.push_back(NewNode);
+  for (unsigned j = 1, N = NewNode->getGlobals().size(); j < N; ++j)
+    ScalarMap[NewNode->getGlobals()[j]] = NewNode;
+
+  // Rewrite the links in the new node to point into the current graph.
+  for (unsigned j = 0, e = GNode->getNumLinks(); j != e; ++j)
+    NewNode->setLink(j, cloneGlobalInto(GNode->getLink(j)));
+
+  return NewNode;
+}
 
 // GlobalDSGraph::cloneNodeInto - Clone a global node and all its externally
 // visible target links (and recursively their such links) into this graph.





More information about the llvm-commits mailing list