[llvm-commits] [llvm] r53201 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAG.h include/llvm/CodeGen/SelectionDAGNodes.h lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Dan Gohman gohman at apple.com
Mon Jul 7 13:57:50 PDT 2008


Author: djg
Date: Mon Jul  7 15:57:48 2008
New Revision: 53201

URL: http://llvm.org/viewvc/llvm-project?rev=53201&view=rev
Log:
Fix SDNode::MorphNodeTo (a function used by by SelectNodeTo) to
properly track dead nodes that are on the original SDNode's operand
list but not the new one, and have no other uses.

Modified:
    llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
    llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=53201&r1=53200&r2=53201&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Mon Jul  7 15:57:48 2008
@@ -537,6 +537,11 @@
   /// for each node deleted.
   void RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener = 0);
   
+  /// RemoveDeadNodes - This method deletes the unreachable nodes in the
+  /// given list, and any nodes that become unreachable as a result.
+  void RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes,
+                       DAGUpdateListener *UpdateListener = 0);
+
   /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead.
   /// This can cause recursive merging of nodes in the DAG.  Use the first
   /// version if 'From' is known to have a single result, use the second

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=53201&r1=53200&r2=53201&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Mon Jul  7 15:57:48 2008
@@ -1315,12 +1315,18 @@
       ++Ops[i].getVal()->UsesSize;
     }
   }
+
+  /// DropOperands - Release the operands and set this node to have
+  /// zero operands.  This should only be used by HandleSDNode to clear
+  /// its operand list.
+  void DropOperands();
   
   /// MorphNodeTo - This frees the operands of the current node, resets the
   /// opcode, types, and operands to the specified value.  This should only be
   /// used by the SelectionDAG class.
   void MorphNodeTo(unsigned Opc, SDVTList L,
-                   const SDOperand *Ops, unsigned NumOps);
+                   const SDOperand *Ops, unsigned NumOps,
+                   SmallVectorImpl<SDNode *> &DeadNodes);
   
   void addUser(unsigned i, SDNode *User) {
     assert(User->OperandList[i].getUser() && "Node without parent");

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=53201&r1=53200&r2=53201&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Jul  7 15:57:48 2008
@@ -486,42 +486,16 @@
     if (I->use_empty())
       DeadNodes.push_back(I);
 
-  // Process the worklist, deleting the nodes and adding their uses to the
-  // worklist.
-  while (!DeadNodes.empty()) {
-    SDNode *N = DeadNodes.back();
-    DeadNodes.pop_back();
-    
-    // Take the node out of the appropriate CSE map.
-    RemoveNodeFromCSEMaps(N);
-
-    // Next, brutally remove the operand list.  This is safe to do, as there are
-    // no cycles in the graph.
-    for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
-      SDNode *Operand = I->getVal();
-      Operand->removeUser(std::distance(N->op_begin(), I), N);
-      
-      // Now that we removed this operand, see if there are no uses of it left.
-      if (Operand->use_empty())
-        DeadNodes.push_back(Operand);
-    }
-    if (N->OperandsNeedDelete) {
-      delete[] N->OperandList;
-    }
-    N->OperandList = 0;
-    N->NumOperands = 0;
-    
-    // Finally, remove N itself.
-    AllNodes.erase(N);
-  }
+  RemoveDeadNodes(DeadNodes);
   
   // If the root changed (e.g. it was a dead load, update the root).
   setRoot(Dummy.getValue());
 }
 
-void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){
-  SmallVector<SDNode*, 16> DeadNodes;
-  DeadNodes.push_back(N);
+/// RemoveDeadNodes - This method deletes the unreachable nodes in the
+/// given list, and any nodes that become unreachable as a result.
+void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes,
+                                   DAGUpdateListener *UpdateListener) {
 
   // Process the worklist, deleting the nodes and adding their uses to the
   // worklist.
@@ -537,16 +511,13 @@
 
     // Next, brutally remove the operand list.  This is safe to do, as there are
     // no cycles in the graph.
-    unsigned op_num = 0;
     for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
       SDNode *Operand = I->getVal();
-      Operand->removeUser(op_num, N);
+      Operand->removeUser(std::distance(N->op_begin(), I), N);
       
       // Now that we removed this operand, see if there are no uses of it left.
       if (Operand->use_empty())
         DeadNodes.push_back(Operand);
-      
-      op_num++;
     }
     if (N->OperandsNeedDelete) {
       delete[] N->OperandList;
@@ -559,6 +530,12 @@
   }
 }
 
+void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){
+  SmallVector<SDNode*, 16> DeadNodes;
+  DeadNodes.push_back(N);
+  RemoveDeadNodes(DeadNodes, UpdateListener);
+}
+
 void SelectionDAG::DeleteNode(SDNode *N) {
   assert(N->use_empty() && "Cannot delete a node that is not dead!");
 
@@ -3681,16 +3658,22 @@
 /// opcode, types, and operands to the specified value.  This should only be
 /// used by the SelectionDAG class.
 void SDNode::MorphNodeTo(unsigned Opc, SDVTList L,
-                         const SDOperand *Ops, unsigned NumOps) {
+                         const SDOperand *Ops, unsigned NumOps,
+                         SmallVectorImpl<SDNode *> &DeadNodes) {
   NodeType = Opc;
   ValueList = L.VTs;
   NumValues = L.NumVTs;
   
   // Clear the operands list, updating used nodes to remove this from their
-  // use list.
-  for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
-    I->getVal()->removeUser(std::distance(op_begin(), I), this);
-  
+  // use list.  Keep track of any operands that become dead as a result.
+  SmallPtrSet<SDNode*, 16> DeadNodeSet;
+  for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) {
+    SDNode *N = I->getVal();
+    N->removeUser(std::distance(op_begin(), I), this);
+    if (N->use_empty())
+      DeadNodeSet.insert(N);
+  }
+
   // If NumOps is larger than the # of operands we currently have, reallocate
   // the operand list.
   if (NumOps > NumOperands) {
@@ -3710,7 +3693,29 @@
     SDNode *N = OperandList[i].getVal();
     N->addUser(i, this);
     ++N->UsesSize;
+    DeadNodeSet.erase(N);
   }
+
+  // Clean up any nodes that are still dead after adding the uses for the
+  // new operands.
+  for (SmallPtrSet<SDNode *, 16>::iterator I = DeadNodeSet.begin(),
+       E = DeadNodeSet.end(); I != E; ++I)
+    DeadNodes.push_back(*I);
+}
+
+/// DropOperands - Release the operands and set this node to have
+/// zero operands.  This should only be used by HandleSDNode to clear
+/// its operand list.
+void SDNode::DropOperands() {
+  assert(NodeType == ISD::HANDLENODE &&
+         "DropOperands is for HANDLENODE only!");
+
+  // Unlike the code in MorphNodeTo that does this, we don't need to
+  // watch for dead nodes here.
+  for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
+    I->getVal()->removeUser(std::distance(op_begin(), I), this);
+
+  NumOperands = 0;
 }
 
 /// SelectNodeTo - These are used for target selectors to *mutate* the
@@ -3814,7 +3819,10 @@
 
   RemoveNodeFromCSEMaps(N);
 
-  N->MorphNodeTo(ISD::BUILTIN_OP_END+TargetOpc, VTs, Ops, NumOps);
+  SmallVector<SDNode *, 16> DeadNodes;
+  N->MorphNodeTo(ISD::BUILTIN_OP_END+TargetOpc, VTs, Ops, NumOps, DeadNodes);
+  RemoveDeadNodes(DeadNodes);
+
   CSEMap.InsertNode(N, IP);   // Memoize the new node.
   return N;
 }
@@ -4250,8 +4258,7 @@
 void AtomicSDNode::ANCHOR() {}
 
 HandleSDNode::~HandleSDNode() {
-  SDVTList VTs = { 0, 0 };
-  MorphNodeTo(ISD::HANDLENODE, VTs, 0, 0);  // Drops operand uses.
+  DropOperands();
 }
 
 GlobalAddressSDNode::GlobalAddressSDNode(bool isTarget, const GlobalValue *GA,





More information about the llvm-commits mailing list