Many changes
authorChris Lattner <sabre@nondot.org>
Thu, 28 Mar 2002 17:56:03 +0000 (17:56 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 28 Mar 2002 17:56:03 +0000 (17:56 +0000)
* Simplify a lot of the inlining stuff.  There are still problems, but not
  many
* Break up the Function representation to have a vector for every different
  node type so it is fast to find nodes of a particular flavor.
* Do more intelligent merging of call values
* Allow elimination of unreachable shadow and allocation nodes
* Generalize indistinguishability testing to allow merging of identical calls.
* Increase shadow node merging power

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2010 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/DataStructure/ComputeClosure.cpp
lib/Analysis/DataStructure/DataStructure.cpp
lib/Analysis/DataStructure/EliminateNodes.cpp
lib/Analysis/DataStructure/FunctionRepBuilder.cpp
lib/Analysis/DataStructure/FunctionRepBuilder.h
lib/Analysis/DataStructure/NodeImpl.cpp

index 9fd7d607e146667bab5a7731103fe94f62a5dc8c..1f15b681abc269929ddb882fb959c35bbe5ccfc5 100644 (file)
 #include "llvm/Assembly/Writer.h"
 #endif
 
-// copyEdgesFromTo - Make a copy of all of the edges to Node to also point
-// PV.  If there are edges out of Node, the edges are added to the subgraph
-// starting at PV.
+// Make all of the pointers that point to Val also point to N.
 //
-static void copyEdgesFromTo(DSNode *Node, const PointerValSet &PVS) {
-  // Make all of the pointers that pointed to Node now also point to PV...
-  const vector<PointerValSet*> &PVSToUpdate(Node->getReferrers());
-  for (unsigned i = 0, e = PVSToUpdate.size(); i != e; ++i)
-    for (unsigned pn = 0, pne = PVS.size(); pn != pne; ++pn)
-      PVSToUpdate[i]->add(PVS[pn]);
-}
-
-static void CalculateNodeMapping(ShadowDSNode *Shadow, DSNode *Node,
-                              multimap<ShadowDSNode *, DSNode *> &NodeMapping) {
-#ifdef DEBUG_IP_CLOSURE
-  cerr << "Mapping " << (void*)Shadow << " to " << (void*)Node << "\n";
-  cerr << "Type = '" << Shadow->getType() << "' and '"
-       << Node->getType() << "'\n";
-  cerr << "Shadow Node:\n";
-  Shadow->print(cerr);
-  cerr << "\nMapped Node:\n";
-  Node->print(cerr);
-#endif
-  assert(Shadow->getType() == Node->getType() &&
-         "Shadow and mapped nodes disagree about type!");
-  
-  multimap<ShadowDSNode *, DSNode *>::iterator
-    NI = NodeMapping.lower_bound(Shadow),
-    NE = NodeMapping.upper_bound(Shadow);
-
-  for (; NI != NE; ++NI)
-    if (NI->second == Node) return;       // Already processed node, return.
+static void copyEdgesFromTo(PointerVal Val, DSNode *N) {
+  assert(Val.Index == 0 && "copyEdgesFromTo:index != 0 TODO");
 
-  NodeMapping.insert(make_pair(Shadow, Node));   // Add a mapping...
-
-  // Loop over all of the outgoing links in the shadow node...
-  //
-  assert(Node->getNumLinks() == Shadow->getNumLinks() &&
-         "Same type, but different number of links?");
-  for (unsigned i = 0, e = Shadow->getNumLinks(); i != e; ++i) {
-    PointerValSet &Link = Shadow->getLink(i);
-
-    // Loop over all of the values coming out of this pointer...
-    for (unsigned l = 0, le = Link.size(); l != le; ++l) {
-      // If the outgoing node points to a shadow node, map the shadow node to
-      // all of the outgoing values in Node.
-      //
-      if (ShadowDSNode *ShadOut = dyn_cast<ShadowDSNode>(Link[l].Node)) {
-        PointerValSet &NLink = Node->getLink(i);
-        for (unsigned ol = 0, ole = NLink.size(); ol != ole; ++ol)
-          CalculateNodeMapping(ShadOut, NLink[ol].Node, NodeMapping);
-      }
-    }
-  }
+  const vector<PointerValSet*> &PVSToUpdate(Val.Node->getReferrers());
+  for (unsigned i = 0, e = PVSToUpdate.size(); i != e; ++i)
+    PVSToUpdate[i]->add(N);  // TODO: support index
 }
 
-
 static void ResolveNodesTo(const PointerVal &FromPtr,
                            const PointerValSet &ToVals) {
   assert(FromPtr.Index == 0 &&
          "Resolved node return pointer should be index 0!");
-  if (!isa<ShadowDSNode>(FromPtr.Node)) return;
-  
+  assert(isa<ShadowDSNode>(FromPtr.Node) &&
+         "Resolved node should be a shadow!");
   ShadowDSNode *Shadow = cast<ShadowDSNode>(FromPtr.Node);
+  assert(Shadow->isCriticalNode() && "Shadow node should be a critical node!");
   Shadow->resetCriticalMark();
 
-  typedef multimap<ShadowDSNode *, DSNode *> ShadNodeMapTy;
-  ShadNodeMapTy NodeMapping;
+  // Make everything that pointed to the shadow node also point to the values in
+  // ToVals...
+  //
   for (unsigned i = 0, e = ToVals.size(); i != e; ++i)
-    CalculateNodeMapping(Shadow, ToVals[i].Node, NodeMapping);
+    copyEdgesFromTo(ToVals[i], Shadow);
 
-  // Now loop through the shadow node graph, mirroring the edges in the shadow
-  // graph onto the realized graph...
-  //
-  for (ShadNodeMapTy::iterator I = NodeMapping.begin(),
-         E = NodeMapping.end(); I != E; ++I) {
-    DSNode *Node = I->second;
-    ShadowDSNode *ShadNode = I->first;
-    PointerValSet PVSx;
-    PVSx.add(Node);
-    copyEdgesFromTo(ShadNode, PVSx);
-
-    // Must loop over edges in the shadow graph, adding edges in the real graph
-    // that correspond to to the edges, but are mapped into real values by the
-    // NodeMapping.
-    //
-    for (unsigned i = 0, e = Node->getNumLinks(); i != e; ++i) {
-      const PointerValSet &ShadLinks = ShadNode->getLink(i);
-      PointerValSet &NewLinks = Node->getLink(i);
-
-      // Add a link to all of the nodes pointed to by the shadow field...
-      for (unsigned l = 0, le = ShadLinks.size(); l != le; ++l) {
-        DSNode *ShadLink = ShadLinks[l].Node;
-
-        if (ShadowDSNode *SL = dyn_cast<ShadowDSNode>(ShadLink)) {
-          // Loop over all of the values in the range 
-          ShadNodeMapTy::iterator St = NodeMapping.lower_bound(SL),
-                                  En = NodeMapping.upper_bound(SL);
-          if (St != En) {
-            for (; St != En; ++St)
-              NewLinks.add(PointerVal(St->second, ShadLinks[l].Index));
-          } else {
-            // We must retain the shadow node...
-            NewLinks.add(ShadLinks[l]);
-          }
-        } else {
-          // Otherwise, add a direct link to the data structure pointed to by
-          // the shadow node...
-          NewLinks.add(ShadLinks[l]);
-        }
-      }
-    }
-  }
+  // Make everything that pointed to the shadow node now also point to the
+  // values it is equivalent to...
+  const vector<PointerValSet*> &PVSToUpdate(Shadow->getReferrers());
+  for (unsigned i = 0, e = PVSToUpdate.size(); i != e; ++i)
+    PVSToUpdate[i]->add(ToVals);
 }
 
 
@@ -137,20 +55,21 @@ static void ResolveNodesTo(const PointerVal &FromPtr,
 static void ResolveNodeTo(DSNode *Node, const PointerValSet &ToVals) {
   assert(Node->getNumLinks() == 1 && "Resolved node can only be a scalar!!");
 
-  PointerValSet PVS = Node->getLink(0);
+  const PointerValSet &PVS = Node->getLink(0);
 
-  for (unsigned i = 0, e = PVS.size(); i != e; ++i)
-    ResolveNodesTo(PVS[i], ToVals);
+  // Only resolve the first pointer, although there many be many pointers here.
+  // The problem is that the inlined function might return one of the arguments
+  // to the function, and if so, extra values can be added to the arg or call
+  // node that point to what the other one got resolved to.  Since these will
+  // be added to the end of the PVS pointed in, we just ignore them.
+  //
+  ResolveNodesTo(PVS[0], ToVals);
 }
 
 // isResolvableCallNode - Return true if node is a call node and it is a call
 // node that we can inline...
 //
-static bool isResolvableCallNode(DSNode *N) {
-  // Only operate on call nodes...
-  CallDSNode *CN = dyn_cast<CallDSNode>(N);
-  if (CN == 0) return false;
-
+static bool isResolvableCallNode(CallDSNode *CN) {
   // Only operate on call nodes with direct method calls
   Function *F = CN->getCall()->getCalledFunction();
   if (F == 0) return false;
@@ -164,35 +83,42 @@ static bool isResolvableCallNode(DSNode *N) {
 // of their corresponding method data structure graph...
 //
 void FunctionDSGraph::computeClosure(const DataStructure &DS) {
-  vector<DSNode*>::iterator NI = std::find_if(Nodes.begin(), Nodes.end(),
-                                              isResolvableCallNode);
+  typedef pair<vector<PointerValSet>, CallInst *> CallDescriptor;
+  map<CallDescriptor, PointerValSet> CallMap;
 
-  map<Function*, unsigned> InlineCount; // FIXME
+  unsigned NumInlines = 0;
 
   // Loop over the resolvable call nodes...
-  while (NI != Nodes.end()) {
-    CallDSNode *CN = cast<CallDSNode>(*NI);
+  vector<CallDSNode*>::iterator NI;
+  NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
+  while (NI != CallNodes.end()) {
+    CallDSNode *CN = *NI;
     Function *F = CN->getCall()->getCalledFunction();
-    //if (F == Func) return;  // Do not do self inlining
 
-    // FIXME: Gross hack to prevent explosions when inlining a recursive func.
-    if (InlineCount[F]++ > 2) return;
+    if (NumInlines++ == 30) {      // CUTE hack huh?
+      cerr << "Infinite (?) recursion halted\n";
+      return;
+    }
 
-    Nodes.erase(NI);                     // Remove the call node from the graph
+    CallNodes.erase(NI);                 // Remove the call node from the graph
 
-    unsigned CallNodeOffset = NI-Nodes.begin();
+    unsigned CallNodeOffset = NI-CallNodes.begin();
 
-    // StartNode - The first node of the incorporated graph, last node of the
-    // preexisting data structure graph...
+    // Find out if we have already incorporated this node... if so, it will be
+    // in the CallMap...
     //
-    unsigned StartNode = Nodes.size();
+    CallDescriptor FDesc(CN->getArgs(), CN->getCall());
+    map<CallDescriptor, PointerValSet>::iterator CMI = CallMap.find(FDesc);
 
     // Hold the set of values that correspond to the incorporated methods
     // return set.
     //
     PointerValSet RetVals;
 
-    if (F != Func) {  // If this is not a recursive call...
+    if (CMI != CallMap.end()) {
+      // We have already inlined an identical function call!
+      RetVals = CMI->second;
+    } else {
       // Get the datastructure graph for the new method.  Note that we are not
       // allowed to modify this graph because it will be the cached graph that
       // is returned by other users that want the local datastructure graph for
@@ -200,79 +126,64 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
       //
       const FunctionDSGraph &NewFunction = DS.getDSGraph(F);
 
-      unsigned StartShadowNodes = ShadowNodes.size();
+      // StartNode - The first node of the incorporated graph, last node of the
+      // preexisting data structure graph...
+      //
+      unsigned StartArgNode   = ArgNodes.size();
+      unsigned StartAllocNode = AllocNodes.size();
 
       // Incorporate a copy of the called function graph into the current graph,
       // allowing us to do local transformations to local graph to link
       // arguments to call values, and call node to return value...
       //
-      RetVals = cloneFunctionIntoSelf(NewFunction, false);
-
-      // Only detail is that we need to reset all of the critical shadow nodes
-      // in the incorporated graph, because they are now no longer critical.
-      //
-      for (unsigned i = StartShadowNodes, e = ShadowNodes.size(); i != e; ++i)
-        ShadowNodes[i]->resetCriticalMark();
-
-    } else {     // We are looking at a recursive function!
-      StartNode = 0;  // Arg nodes start at 0 now...
-      RetVals = RetNode;
-    }
-
-    // If the function returns a pointer value...  Resolve values pointing to
-    // the shadow nodes pointed to by CN to now point the values in RetVals...
-    //
-    if (CN->getNumLinks()) ResolveNodeTo(CN, RetVals);
-
-    // If the call node has arguments, process them now!
-    if (CN->getNumArgs()) {
-      // The ArgNodes of the incorporated graph should be the nodes starting at
-      // StartNode, ordered the same way as the call arguments.  The arg nodes
-      // are seperated by a single shadow node, but that shadow node might get
-      // eliminated in the process of optimization.
-      //
-      unsigned ArgOffset = StartNode;
-      for (unsigned i = 0, e = CN->getNumArgs(); i != e; ++i) {
-        // Get the arg node of the incorporated method...
-        while (!isa<ArgDSNode>(Nodes[ArgOffset]))  // Scan for next arg node
-          ArgOffset++;
-        ArgDSNode *ArgNode = cast<ArgDSNode>(Nodes[ArgOffset]);
-
-        // Now we make all of the nodes inside of the incorporated method point
-        // to the real arguments values, not to the shadow nodes for the
-        // argument.
+      RetVals = cloneFunctionIntoSelf(NewFunction, F == Func);
+      CallMap[FDesc] = RetVals;
+
+      // If the call node has arguments, process them now!
+      if (CN->getNumArgs()) {
+        // The ArgNodes of the incorporated graph should be the nodes starting
+        // at StartNode, ordered the same way as the call arguments.  The arg
+        // nodes are seperated by a single shadow node, but that shadow node
+        // might get eliminated in the process of optimization.
         //
-        ResolveNodeTo(ArgNode, CN->getArgValues(i));
-
-        if (StartNode) {        // Not Self recursion?
+        for (unsigned i = 0, e = CN->getNumArgs(); i != e; ++i) {
+          // Get the arg node of the incorporated method...
+          ArgDSNode *ArgNode = ArgNodes[StartArgNode];
+          
+          // Now we make all of the nodes inside of the incorporated method
+          // point to the real arguments values, not to the shadow nodes for the
+          // argument.
+          //
+          ResolveNodeTo(ArgNode, CN->getArgValues(i));
+          
           // Remove the argnode from the set of nodes in this method...
-          Nodes.erase(Nodes.begin()+ArgOffset);
-
+          ArgNodes.erase(ArgNodes.begin()+StartArgNode);
+            
           // ArgNode is no longer useful, delete now!
           delete ArgNode;
-        } else {
-          ArgOffset++;  // Step to the next argument...
         }
       }
+
+      // Loop through the nodes, deleting alloca nodes in the inlined function.
+      // Since the memory has been released, we cannot access their pointer
+      // fields (with defined results at least), so it is not possible to use
+      // any pointers to the alloca.  Drop them now, and remove the alloca's
+      // since they are dead (we just removed all links to them).
+      //
+      for (unsigned i = StartAllocNode; i != AllocNodes.size(); ++i)
+        if (AllocNodes[i]->isAllocaNode()) {
+          AllocDSNode *NDS = AllocNodes[i];
+          NDS->removeAllIncomingEdges();          // These edges are invalid now
+          delete NDS;                             // Node is dead
+          AllocNodes.erase(AllocNodes.begin()+i); // Remove slot in Nodes array
+          --i;                                    // Don't skip the next node
+        }
     }
 
-    // Loop through the nodes, deleting alloc nodes in the inlined function...
-    // Since the memory has been released, we cannot access their pointer
-    // fields (with defined results at least), so it is not possible to use any
-    // pointers to the alloca.  Drop them now, and remove the alloca's since
-    // they are dead (we just removed all links to them).  Only do this if we
-    // are not self recursing though.  :)
+    // If the function returns a pointer value...  Resolve values pointing to
+    // the shadow nodes pointed to by CN to now point the values in RetVals...
     //
-    if (StartNode)  // Don't do this if self recursing...
-      for (unsigned i = StartNode; i != Nodes.size(); ++i)
-        if (NewDSNode *NDS = dyn_cast<NewDSNode>(Nodes[i]))
-          if (NDS->isAllocaNode()) {
-            NDS->removeAllIncomingEdges();  // These edges are invalid now!
-            delete NDS;                     // Node is dead
-            Nodes.erase(Nodes.begin()+i);   // Remove slot in Nodes array
-            --i;                            // Don't skip the next node
-          }
-
+    if (CN->getNumLinks()) ResolveNodeTo(CN, RetVals);
 
     // Now the call node is completely destructable.  Eliminate it now.
     delete CN;
@@ -291,6 +202,6 @@ void FunctionDSGraph::computeClosure(const DataStructure &DS) {
     //if (F == Func) return;  // Only do one self inlining
     
     // Move on to the next call node...
-    NI = std::find_if(Nodes.begin(), Nodes.end(), isResolvableCallNode);
+    NI = std::find_if(CallNodes.begin(), CallNodes.end(), isResolvableCallNode);
   }
 }
index d90d84a06b5fd322bae7928e4436139342374302..13d3dce174c0433fa5e62c51fae1160c89edd0f2 100644 (file)
@@ -90,6 +90,28 @@ const PointerValSet &PointerValSet::operator=(const PointerValSet &PVS) {
   return *this;
 }
 
+// operator< - Allow insertion into a map...
+bool PointerValSet::operator<(const PointerValSet &PVS) const {
+  if (Vals.size() < PVS.Vals.size()) return true;
+  if (Vals.size() > PVS.Vals.size()) return false;
+  if (Vals.size() == 1) return Vals[0] < PVS.Vals[0];  // Most common case
+
+  vector<PointerVal> S1(Vals), S2(PVS.Vals);
+  sort(S1.begin(), S1.end());
+  sort(S2.begin(), S2.end());
+  return S1 < S2;
+}
+
+bool PointerValSet::operator==(const PointerValSet &PVS) const {
+  if (Vals.size() != PVS.Vals.size()) return false;
+  if (Vals.size() == 1) return Vals[0] == PVS.Vals[0];  // Most common case...
+
+  vector<PointerVal> S1(Vals), S2(PVS.Vals);
+  sort(S1.begin(), S1.end());
+  sort(S2.begin(), S2.end());
+  return S1 == S2;
+}
+
 
 bool PointerValSet::add(const PointerVal &PV, Value *Pointer) {
   if (std::find(Vals.begin(), Vals.end(), PV) != Vals.end())
index 3d1319dcf23c4df219ec2db69a675ddd90c9cc0b..ca82ed1cd92efac0c831a9cd81846d47f927f429 100644 (file)
 
 //#define DEBUG_NODE_ELIMINATE 1
 
+bool AllocDSNode::isEquivalentTo(DSNode *Node) const {
+  if (AllocDSNode *N = dyn_cast<AllocDSNode>(Node))
+    return N->Allocation == Allocation;
+  return false;
+}
+
+bool GlobalDSNode::isEquivalentTo(DSNode *Node) const {
+  if (GlobalDSNode *G = dyn_cast<GlobalDSNode>(Node))
+    return G->Val == Val;
+  return false;
+}
+
+bool CallDSNode::isEquivalentTo(DSNode *Node) const {
+  if (CallDSNode *C = dyn_cast<CallDSNode>(Node))
+    return C->CI == CI && C->ArgLinks == ArgLinks;
+  return false;
+}
+
+bool ArgDSNode::isEquivalentTo(DSNode *Node) const {
+  return false;
+}
+
 // NodesAreEquivalent - Check to see if the nodes are equivalent in all ways
 // except node type.  Since we know N1 is a shadow node, N2 is allowed to be
 // any type.
 //
-static bool NodesAreEquivalent(const ShadowDSNode *N1, const DSNode *N2) {
-  assert(N1 != N2 && "A node is always equivalent to itself!");
-
-  // Perform simple, fast checks first...
-  if (N1->getType() != N2->getType() ||  // Must have same type...
-      N1->isCriticalNode())              // Must not be a critical node...
-    return false;
-
-#if 0
-  return true;
-#else
-
-  // The shadow node is considered equivalent if it has a subset of the incoming
-  // edges that N2 does...
-  if (N1->getReferrers().size() > N2->getReferrers().size()) return false;
-
-  // Check to see if the referring (incoming) pointers are all the same...
-  std::vector<PointerValSet*> N1R = N1->getReferrers();
-  std::vector<PointerValSet*> N2R = N2->getReferrers();
-  sort(N1R.begin(), N1R.end());
-  sort(N2R.begin(), N2R.end());
-
-  // The nodes are equivalent if the incoming edges to N1 are a subset of N2.
-  unsigned i1 = 0, e1 = N1R.size();
-  unsigned i2 = 0, e2 = N2R.size();
-  for (; i1 != e1 && i2 < e2; ++i1, ++i2) {
-    while (N1R[i1] > N2R[i2] && i2 < e2)
-      ++i2;
-
-    if (N1R[i1] < N2R[i2]) return false;  // Error case...
-  }
-
-  return i1 == e1 && i2 <= e2;
-#endif
+bool ShadowDSNode::isEquivalentTo(DSNode *Node) const {
+  return !isCriticalNode();              // Must not be a critical node...
 }
 
-// IndistinguishableShadowNode - A shadow node is indistinguishable if some
-// other node (shadow or otherwise) has exactly the same incoming and outgoing
-// links to it (or if there are no edges coming in, in which it is trivially
-// dead).
-//
-static bool IndistinguishableShadowNode(const ShadowDSNode *SN) {
-  if (SN->getReferrers().empty()) return true;  // Node is trivially dead
 
+
+// isIndistinguishableNode - A node is indistinguishable if some other node
+// has exactly the same incoming links to it and if the node considers itself
+// to be the same as the other node...
+//
+bool isIndistinguishableNode(DSNode *DN) {
+  if (DN->getReferrers().empty()) {       // No referrers...
+    if (isa<ShadowDSNode>(DN) || isa<AllocDSNode>(DN))
+      return true;  // Node is trivially dead
+    else
+      return false;
+  }
+  
   // Pick a random referrer... Ptr is the things that the referrer points to.
-  // Since SN is in the Ptr set, look through the set seeing if there are any
-  // other nodes that are exactly equilivant to SN (with the exception of node
-  // type), but are not SN.  If anything exists, then SN is indistinguishable.
+  // Since DN is in the Ptr set, look through the set seeing if there are any
+  // other nodes that are exactly equilivant to DN (with the exception of node
+  // type), but are not DN.  If anything exists, then DN is indistinguishable.
   //
-  const PointerValSet &Ptr = *SN->getReferrers()[0];
-
-  for (unsigned i = 0, e = Ptr.size(); i != e; ++i)
-    if (Ptr[i].Index == 0 && Ptr[i].Node != cast<DSNode>(SN) &&
-        NodesAreEquivalent(SN, Ptr[i].Node))
-      return true;
+  const std::vector<PointerValSet*> &Refs = DN->getReferrers();
+  for (unsigned R = 0, RE = Refs.size(); R != RE; ++R) {
+    const PointerValSet &Ptr = *Refs[R];
+
+    for (unsigned i = 0, e = Ptr.size(); i != e; ++i) {
+      DSNode *N2 = Ptr[i].Node;
+      if (Ptr[i].Index == 0 && N2 != cast<DSNode>(DN) &&
+          DN->getType() == N2->getType() && DN->isEquivalentTo(N2)) {
+
+        // Otherwise, the nodes can be merged.  Make sure that N2 contains all
+        // of the  outgoing edges (fields) that DN does...
+        //
+        assert(DN->getNumLinks() == N2->getNumLinks() &&
+               "Same type, diff # fields?");
+        for (unsigned i = 0, e = DN->getNumLinks(); i != e; ++i)
+          N2->getLink(i).add(DN->getLink(i));
+        
+        // Now make sure that all of the nodes that point to the shadow node
+        // also  point to the node that we are merging it with...
+        //
+        const std::vector<PointerValSet*> &Refs = DN->getReferrers();
+        for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
+          PointerValSet &PVS = *Refs[i];
+          // FIXME: this is incorrect if the referring pointer has index != 0
+          //
+          PVS.add(N2);
+        }
+        return true;
+      }
+    }
+  }
 
   // Otherwise, nothing found, perhaps next time....
   return false;
 }
 
-
-// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
-// distinguishable from some other node in the graph...
-//
-bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
+template<typename NodeTy>
+bool removeIndistinguishableNode(std::vector<NodeTy*> &Nodes) {
   bool Changed = false;
-  // Loop over all of the shadow nodes, checking to see if they are
-  // indistinguishable from some other node.  If so, eliminate the node!
-  //
-  for (vector<ShadowDSNode*>::iterator I = ShadowNodes.begin();
-       I != ShadowNodes.end(); )
-    if (IndistinguishableShadowNode(*I)) {
+  std::vector<NodeTy*>::iterator I = Nodes.begin();
+  while (I != Nodes.end()) {
+    if (isIndistinguishableNode(*I)) {
 #ifdef DEBUG_NODE_ELIMINATE
-      cerr << "Found Indistinguishable Shadow Node:\n";
+      cerr << "Found Indistinguishable Node:\n";
       (*I)->print(cerr);
 #endif
       (*I)->removeAllIncomingEdges();
-      // Don't need to dropAllRefs, because nothing can point to it now
       delete *I;
-      
-      I = ShadowNodes.erase(I);
+      I = Nodes.erase(I);
       Changed = true;
     } else {
       ++I;
     }
+  }
   return Changed;
 }
 
-static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
-                                       vector<bool> &Reachable);
+// UnlinkUndistinguishableShadowNodes - Eliminate shadow nodes that are not
+// distinguishable from some other node in the graph...
+//
+bool FunctionDSGraph::UnlinkUndistinguishableShadowNodes() {
+  // Loop over all of the shadow nodes, checking to see if they are
+  // indistinguishable from some other node.  If so, eliminate the node!
+  //
+  return
+    removeIndistinguishableNode(AllocNodes) |
+    removeIndistinguishableNode(ShadowNodes) |
+    removeIndistinguishableNode(GlobalNodes);
+}
+
+static void MarkReferredNodesReachable(DSNode *N,
+                                       vector<ShadowDSNode*> &ShadowNodes,
+                                       vector<bool> &ReachableShadowNodes,
+                                       vector<AllocDSNode*>  &AllocNodes,
+                                       vector<bool> &ReachableAllocNodes);
 
 static inline void MarkReferredNodeSetReachable(const PointerValSet &PVS,
-                                                vector<ShadowDSNode*> &Nodes,
-                                                vector<bool> &Reachable) {
+                                            vector<ShadowDSNode*> &ShadowNodes,
+                                            vector<bool> &ReachableShadowNodes,
+                                            vector<AllocDSNode*>  &AllocNodes,
+                                            vector<bool> &ReachableAllocNodes) {
   for (unsigned i = 0, e = PVS.size(); i != e; ++i)
-    if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(PVS[i].Node))
-      MarkReferredNodesReachable(Shad, Nodes, Reachable);
+    if (isa<ShadowDSNode>(PVS[i].Node) || isa<ShadowDSNode>(PVS[i].Node))
+      MarkReferredNodesReachable(PVS[i].Node, ShadowNodes, ReachableShadowNodes,
+                                 AllocNodes, ReachableAllocNodes);
 }
 
-static void MarkReferredNodesReachable(DSNode *N, vector<ShadowDSNode*> &Nodes,
-                                       vector<bool> &Reachable) {
-  assert(Nodes.size() == Reachable.size());
-  ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N);
+static void MarkReferredNodesReachable(DSNode *N,
+                                       vector<ShadowDSNode*> &ShadowNodes,
+                                       vector<bool> &ReachableShadowNodes,
+                                       vector<AllocDSNode*>  &AllocNodes,
+                                       vector<bool> &ReachableAllocNodes) {
+  assert(ShadowNodes.size() == ReachableShadowNodes.size());
+  assert(AllocNodes.size()  == ReachableAllocNodes.size());
 
-  if (Shad) {
+  if (ShadowDSNode *Shad = dyn_cast<ShadowDSNode>(N)) {
     vector<ShadowDSNode*>::iterator I =
-      std::find(Nodes.begin(), Nodes.end(), Shad);
-    unsigned i = I-Nodes.begin();
-    if (Reachable[i]) return;  // Recursion detected, abort...
-    Reachable[i] = true;
+      std::find(ShadowNodes.begin(), ShadowNodes.end(), Shad);
+    unsigned i = I-ShadowNodes.begin();
+    if (ReachableShadowNodes[i]) return;  // Recursion detected, abort...
+    ReachableShadowNodes[i] = true;
+  } else if (AllocDSNode *Alloc = dyn_cast<AllocDSNode>(N)) {
+    vector<AllocDSNode*>::iterator I =
+      std::find(AllocNodes.begin(), AllocNodes.end(), Alloc);
+    unsigned i = I-AllocNodes.begin();
+    if (ReachableAllocNodes[i]) return;  // Recursion detected, abort...
+    ReachableAllocNodes[i] = true;
   }
 
   for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i)
-    MarkReferredNodeSetReachable(N->getLink(i), Nodes, Reachable);
+    MarkReferredNodeSetReachable(N->getLink(i),
+                                 ShadowNodes, ReachableShadowNodes,
+                                 AllocNodes, ReachableAllocNodes);
 
   const std::vector<PointerValSet> *Links = N->getAuxLinks();
   if (Links)
     for (unsigned i = 0, e = Links->size(); i != e; ++i)
-      MarkReferredNodeSetReachable((*Links)[i], Nodes, Reachable);  
+      MarkReferredNodeSetReachable((*Links)[i],
+                                   ShadowNodes, ReachableShadowNodes,
+                                   AllocNodes, ReachableAllocNodes);
 }
 
 bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
   bool Changed = false;
   while (1) {
-
-    // Reachable - Contains true if there is an edge from a nonshadow node to
-    // the numbered node...
+    // Reachable*Nodes - Contains true if there is an edge from a reachable
+    // node to the numbered node...
     //
-    vector<bool> Reachable(ShadowNodes.size());
+    vector<bool> ReachableShadowNodes(ShadowNodes.size());
+    vector<bool> ReachableAllocNodes (AllocNodes.size());
 
     // Mark all shadow nodes that have edges from other nodes as reachable.  
     // Recursively mark any shadow nodes pointed to by the newly live shadow
     // nodes as also alive.
     //
-    for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
-      // Loop over all of the nodes referred and mark them live if they are
-      // shadow nodes...
-      MarkReferredNodesReachable(Nodes[i], ShadowNodes, Reachable);
+    for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
+      MarkReferredNodesReachable(ArgNodes[i],
+                                 ShadowNodes, ReachableShadowNodes,
+                                 AllocNodes, ReachableAllocNodes);
+
+    for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
+      MarkReferredNodesReachable(GlobalNodes[i],
+                                 ShadowNodes, ReachableShadowNodes,
+                                 AllocNodes, ReachableAllocNodes);
+
+    for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
+      MarkReferredNodesReachable(CallNodes[i],
+                                 ShadowNodes, ReachableShadowNodes,
+                                 AllocNodes, ReachableAllocNodes);
 
     // Mark all nodes in the return set as being reachable...
-    MarkReferredNodeSetReachable(RetNode, ShadowNodes, Reachable);
+    MarkReferredNodeSetReachable(RetNode,
+                                 ShadowNodes, ReachableShadowNodes,
+                                 AllocNodes, ReachableAllocNodes);
 
     // Mark all nodes in the value map as being reachable...
     for (std::map<Value*, PointerValSet>::iterator I = ValueMap.begin(),
            E = ValueMap.end(); I != E; ++I)
-      MarkReferredNodeSetReachable(I->second, ShadowNodes, Reachable);
-
+      MarkReferredNodeSetReachable(I->second,
+                                   ShadowNodes, ReachableShadowNodes,
+                                   AllocNodes, ReachableAllocNodes);
 
     // At this point, all reachable shadow nodes have a true value in the
     // Reachable vector.  This means that any shadow nodes without an entry in
@@ -179,26 +238,43 @@ bool FunctionDSGraph::RemoveUnreachableShadowNodes() {
     // a two part process, because we must drop all references before we delete
     // the shadow nodes [in case cycles exist].
     // 
-    vector<ShadowDSNode*> DeadNodes;
+    bool LocalChange = false;
     for (unsigned i = 0; i != ShadowNodes.size(); ++i)
-      if (!Reachable[i]) {
+      if (!ReachableShadowNodes[i]) {
         // Track all unreachable nodes...
 #if DEBUG_NODE_ELIMINATE
         cerr << "Unreachable node eliminated:\n";
         ShadowNodes[i]->print(cerr);
 #endif
-        DeadNodes.push_back(ShadowNodes[i]);
-        ShadowNodes[i]->dropAllReferences();  // Drop references to other nodes
-        Reachable.erase(Reachable.begin()+i); // Remove from reachable...
+        ShadowNodes[i]->removeAllIncomingEdges();
+        delete ShadowNodes[i];
+
+        // Remove from reachable...
+        ReachableShadowNodes.erase(ReachableShadowNodes.begin()+i);
         ShadowNodes.erase(ShadowNodes.begin()+i);   // Remove node entry
         --i;  // Don't skip the next node.
+        LocalChange = true;
       }
 
-    if (DeadNodes.empty()) return Changed;      // No more dead nodes...
+    for (unsigned i = 0; i != AllocNodes.size(); ++i)
+      if (!ReachableAllocNodes[i]) {
+        // Track all unreachable nodes...
+#if DEBUG_NODE_ELIMINATE
+        cerr << "Unreachable node eliminated:\n";
+        AllocNodes[i]->print(cerr);
+#endif
+        AllocNodes[i]->removeAllIncomingEdges();
+        delete AllocNodes[i];
 
-    Changed = true;
+        // Remove from reachable...
+        ReachableAllocNodes.erase(ReachableAllocNodes.begin()+i);
+        AllocNodes.erase(AllocNodes.begin()+i);   // Remove node entry
+        --i;  // Don't skip the next node.
+        LocalChange = true;
+      }
+
+    if (!LocalChange) return Changed;      // No more dead nodes...
 
-    // All dead nodes are in the DeadNodes vector... delete them now.
-    for_each(DeadNodes.begin(), DeadNodes.end(), deleter<DSNode>);
+    Changed = true;
   }
 }
index e2544c82dcf5ad6eeca509fbbd2aa020d431e327..87d4a332cedd2647f83a36e74ecc648bf976f013 100644 (file)
@@ -44,7 +44,7 @@ void InitVisitor::visitOperand(Value *V) {
   if (!Rep->ValueMap.count(V))                  // Only process it once...
     if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
       GlobalDSNode *N = new GlobalDSNode(GV);
-      Rep->Nodes.push_back(N);
+      Rep->GlobalNodes.push_back(N);
       Rep->ValueMap[V].add(N);
       Rep->addAllUsesToWorkList(GV);
 
@@ -60,7 +60,7 @@ void InitVisitor::visitOperand(Value *V) {
 //
 void InitVisitor::visitCallInst(CallInst *CI) {
   CallDSNode *C = new CallDSNode(CI);
-  Rep->Nodes.push_back(C);
+  Rep->CallNodes.push_back(C);
   Rep->CallMap[CI] = C;
       
   if (isa<PointerType>(CI->getType())) {
@@ -95,8 +95,8 @@ void InitVisitor::visitCallInst(CallInst *CI) {
 // global vars...
 //
 void InitVisitor::visitAllocationInst(AllocationInst *AI) {
-  NewDSNode *N = new NewDSNode(AI);
-  Rep->Nodes.push_back(N);
+  AllocDSNode *N = new AllocDSNode(AI);
+  Rep->AllocNodes.push_back(N);
   
   Rep->ValueMap[AI].add(N, AI);
   
@@ -144,7 +144,7 @@ void FunctionRepBuilder::initializeWorkList(Function *Func) {
     // Only process arguments that are of pointer type...
     if (isa<PointerType>((*I)->getType())) {
       ArgDSNode *Arg = new ArgDSNode(*I);
-      Nodes.push_back(Arg);
+      ArgNodes.push_back(Arg);
       
       // Add a critical shadow value for it to represent what it is pointing
       // to and add this to the value map...
@@ -326,10 +326,13 @@ void FunctionRepBuilder::visitPHINode(PHINode *PN) {
 //
 FunctionDSGraph::FunctionDSGraph(Function *F) : Func(F) {
   FunctionRepBuilder Builder(this);
-  Nodes = Builder.getNodes();
+  ArgNodes    = Builder.getArgNodes();
+  AllocNodes  = Builder.getAllocNodes();
   ShadowNodes = Builder.getShadowNodes();
-  RetNode = Builder.getRetNode();
-  ValueMap = Builder.getValueMap();
+  GlobalNodes = Builder.getGlobalNodes();
+  CallNodes   = Builder.getCallNodes();
+  RetNode     = Builder.getRetNode();
+  ValueMap    = Builder.getValueMap();
 
   bool Changed = true;
   while (Changed) {
index 6809261b90ccddcfc6cc15b3d61dc4c125f08d5a..bc561342f2d4c78cba8f67eaf7b951152b6d5d55 100644 (file)
@@ -61,8 +61,11 @@ class FunctionRepBuilder : InstVisitor<FunctionRepBuilder> {
   // Nodes - Keep track of all of the resultant nodes, because there may not
   // be edges connecting these to anything.
   //
-  std::vector<DSNode*> Nodes;
+  std::vector<ArgDSNode*>    ArgNodes;
+  std::vector<AllocDSNode*>  AllocNodes;
   std::vector<ShadowDSNode*> ShadowNodes;
+  std::vector<GlobalDSNode*> GlobalNodes;
+  std::vector<CallDSNode*>   CallNodes;
 
   // addAllUsesToWorkList - Add all of the instructions users of the specified
   // value to the work list for further processing...
@@ -75,11 +78,13 @@ public:
     processWorkList();
   }
 
-  void addNode(DSNode *N) { Nodes.push_back(N); }
-  const std::vector<DSNode*> &getNodes() const { return Nodes; }
-
-  void addShadowNode(ShadowDSNode *N) { ShadowNodes.push_back(N); }
+  const std::vector<ArgDSNode*>    &getArgNodes() const { return ArgNodes; }
+  const std::vector<AllocDSNode*>  &getAllocNodes() const { return AllocNodes; }
   const std::vector<ShadowDSNode*> &getShadowNodes() const {return ShadowNodes;}
+  const std::vector<GlobalDSNode*> &getGlobalNodes() const {return GlobalNodes;}
+  const std::vector<CallDSNode*>   &getCallNodes() const { return CallNodes; }
+
+  void addShadowNode(ShadowDSNode *SN) { ShadowNodes.push_back(SN); }
 
   const PointerValSet &getRetNode() const { return RetNode; }
 
index 967c67eea0ffdeca39f853c034793dc5d53427b2..b8fabf8a7472520968a40c2c97a03ffc24ef8b85 100644 (file)
@@ -20,8 +20,8 @@
 //
 
 static void MapPVS(PointerValSet &PVSOut, const PointerValSet &PVSIn,
-                   map<const DSNode*, DSNode*> &NodeMap{
-  assert(PVSOut.empty() && "Value set already initialized!");
+                   map<const DSNode*, DSNode*> &NodeMap, bool ReinitOk = false){
+  assert((ReinitOk || PVSOut.empty()) && "Value set already initialized!");
 
   for (unsigned i = 0, e = PVSIn.size(); i != e; ++i)
     PVSOut.add(PointerVal(NodeMap[PVSIn[i].Node], PVSIn[i].Index));
@@ -148,16 +148,16 @@ void DSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap, const DSNode *Old) {
     MapPVS(FieldLinks[j], Old->FieldLinks[j], NodeMap);
 }
 
-NewDSNode::NewDSNode(AllocationInst *V)
+AllocDSNode::AllocDSNode(AllocationInst *V)
   : DSNode(NewNode, V->getType()->getElementType()), Allocation(V) {
 }
 
-bool NewDSNode::isAllocaNode() const {
+bool AllocDSNode::isAllocaNode() const {
   return isa<AllocaInst>(Allocation);
 }
 
 
-string NewDSNode::getCaption() const {
+string AllocDSNode::getCaption() const {
   stringstream OS;
   OS << (isMallocNode() ? "new " : "alloca ");
 
@@ -175,7 +175,7 @@ GlobalDSNode::GlobalDSNode(GlobalValue *V)
 string GlobalDSNode::getCaption() const {
   stringstream OS;
   WriteTypeSymbolic(OS, getType(), Val->getParent());
-  return "global " + OS.str();
+  return "global " + OS.str() + " %" + Val->getName();
 }
 
 
@@ -243,7 +243,7 @@ string CallDSNode::getCaption() const {
 
 void CallDSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap,
                          const DSNode *O) {
-  const CallDSNode *Old = (CallDSNode*)O;
+  const CallDSNode *Old = cast<CallDSNode>(O);
   DSNode::mapNode(NodeMap, Old);  // Map base portions first...
 
   assert(ArgLinks.size() == Old->ArgLinks.size() && "# Arguments changed!?");
@@ -266,10 +266,16 @@ void FunctionDSGraph::printFunction(std::ostream &O,
                                     const char *Label) const {
   O << "\tsubgraph cluster_" << Label << "_Function" << (void*)this << " {\n";
   O << "\t\tlabel=\"" << Label << " Function\\ " << Func->getName() << "\";\n";
-  for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
-    Nodes[i]->print(O);
+  for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
+    ArgNodes[i]->print(O);
+  for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
+    AllocNodes[i]->print(O);
   for (unsigned i = 0, e = ShadowNodes.size(); i != e; ++i)
     ShadowNodes[i]->print(O);
+  for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
+    GlobalNodes[i]->print(O);
+  for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
+    CallNodes[i]->print(O);
 
   if (RetNode.size()) {
     O << "\t\tNode" << (void*)this << Label
@@ -315,14 +321,30 @@ FunctionDSGraph::FunctionDSGraph(const FunctionDSGraph &DSG) : Func(DSG.Func) {
 PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
                                                      bool CloneValueMap) {
   map<const DSNode*, DSNode*> NodeMap;  // Map from old graph to new graph...
-  unsigned StartSize = Nodes.size();    // We probably already have nodes...
-  Nodes.reserve(StartSize+DSG.Nodes.size());
+  unsigned StartArgSize = ArgNodes.size();
+  ArgNodes.reserve(StartArgSize+DSG.ArgNodes.size());
+  unsigned StartAllocSize = AllocNodes.size();
+  AllocNodes.reserve(StartAllocSize+DSG.AllocNodes.size());
   unsigned StartShadowSize = ShadowNodes.size();
   ShadowNodes.reserve(StartShadowSize+DSG.ShadowNodes.size());
+  unsigned StartGlobalSize = GlobalNodes.size();
+  GlobalNodes.reserve(StartGlobalSize+DSG.GlobalNodes.size());
+  unsigned StartCallSize = CallNodes.size();
+  CallNodes.reserve(StartCallSize+DSG.CallNodes.size());
+
+  // Clone all of the arg nodes...
+  for (unsigned i = 0, e = DSG.ArgNodes.size(); i != e; ++i) {
+    ArgDSNode *New = cast<ArgDSNode>(DSG.ArgNodes[i]->clone());
+    NodeMap[DSG.ArgNodes[i]] = New;
+    ArgNodes.push_back(New);
+  }
 
-  // Clone all of the nodes, keeping track of the mapping...
-  for (unsigned i = 0, e = DSG.Nodes.size(); i != e; ++i)
-    Nodes.push_back(NodeMap[DSG.Nodes[i]] = DSG.Nodes[i]->clone());
+  // Clone all of the alloc nodes similarly...
+  for (unsigned i = 0, e = DSG.AllocNodes.size(); i != e; ++i) {
+    AllocDSNode *New = cast<AllocDSNode>(DSG.AllocNodes[i]->clone());
+    NodeMap[DSG.AllocNodes[i]] = New;
+    AllocNodes.push_back(New);
+  }
 
   // Clone all of the shadow nodes similarly...
   for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i) {
@@ -331,14 +353,34 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
     ShadowNodes.push_back(New);
   }
 
+  // Clone all of the global nodes...
+  for (unsigned i = 0, e = DSG.GlobalNodes.size(); i != e; ++i) {
+    GlobalDSNode *New = cast<GlobalDSNode>(DSG.GlobalNodes[i]->clone());
+    NodeMap[DSG.GlobalNodes[i]] = New;
+    GlobalNodes.push_back(New);
+  }
+
+  // Clone all of the call nodes...
+  for (unsigned i = 0, e = DSG.CallNodes.size(); i != e; ++i) {
+    CallDSNode *New = cast<CallDSNode>(DSG.CallNodes[i]->clone());
+    NodeMap[DSG.CallNodes[i]] = New;
+    CallNodes.push_back(New);
+  }
+
   // Convert all of the links over in the nodes now that the map has been filled
   // in all the way...
   //
-  for (unsigned i = 0, e = DSG.Nodes.size(); i != e; ++i)
-    Nodes[i+StartSize]->mapNode(NodeMap, DSG.Nodes[i]);
-
+  for (unsigned i = 0, e = DSG.ArgNodes.size(); i != e; ++i)
+    ArgNodes[i+StartArgSize]->mapNode(NodeMap, DSG.ArgNodes[i]);
+  for (unsigned i = 0, e = DSG.AllocNodes.size(); i != e; ++i)
+    AllocNodes[i+StartAllocSize]->mapNode(NodeMap, DSG.AllocNodes[i]);
   for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i)
     ShadowNodes[i+StartShadowSize]->mapNode(NodeMap, DSG.ShadowNodes[i]);
+  for (unsigned i = 0, e = DSG.GlobalNodes.size(); i != e; ++i)
+    GlobalNodes[i+StartGlobalSize]->mapNode(NodeMap, DSG.GlobalNodes[i]);
+  for (unsigned i = 0, e = DSG.CallNodes.size(); i != e; ++i)
+    CallNodes[i+StartCallSize]->mapNode(NodeMap, DSG.CallNodes[i]);
+
 
   if (CloneValueMap) {
     // Convert value map... the values themselves stay the same, just the nodes
@@ -346,7 +388,7 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
     //
     for (std::map<Value*,PointerValSet>::const_iterator I =DSG.ValueMap.begin(),
            E = DSG.ValueMap.end(); I != E; ++I)
-      MapPVS(ValueMap[I->first], I->second, NodeMap);
+      MapPVS(ValueMap[I->first], I->second, NodeMap, true);
   }
 
   // Convert over return node...
@@ -359,10 +401,20 @@ PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
 FunctionDSGraph::~FunctionDSGraph() {
   RetNode.clear();
   ValueMap.clear();
-  for_each(Nodes.begin(), Nodes.end(), mem_fun(&DSNode::dropAllReferences));
+  for_each(ArgNodes.begin(), ArgNodes.end(),
+           mem_fun(&DSNode::dropAllReferences));
+  for_each(AllocNodes.begin(), AllocNodes.end(),
+           mem_fun(&DSNode::dropAllReferences));
   for_each(ShadowNodes.begin(), ShadowNodes.end(),
            mem_fun(&DSNode::dropAllReferences));
-  for_each(Nodes.begin(), Nodes.end(), deleter<DSNode>);
+  for_each(GlobalNodes.begin(), GlobalNodes.end(),
+           mem_fun(&DSNode::dropAllReferences));
+  for_each(CallNodes.begin(), CallNodes.end(),
+           mem_fun(&DSNode::dropAllReferences));
+  for_each(ArgNodes.begin(),    ArgNodes.end(),    deleter<DSNode>);
+  for_each(AllocNodes.begin(),  AllocNodes.end(),  deleter<DSNode>);
   for_each(ShadowNodes.begin(), ShadowNodes.end(), deleter<DSNode>);
+  for_each(GlobalNodes.begin(), GlobalNodes.end(), deleter<DSNode>);
+  for_each(CallNodes.begin(),   CallNodes.end(),   deleter<DSNode>);
 }