One mundane change: Change ReplaceAllUsesOfValueWith to *optionally*
[oota-llvm.git] / lib / CodeGen / SelectionDAG / SelectionDAG.cpp
index eb6e60302d920cfdb5cbad46f2ebfeb409323b49..9a1ea7cb3867bead52a017601049a1f708ff8b33 100644 (file)
@@ -3232,11 +3232,11 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From,
 /// uses of other values produced by From.Val alone.  The Deleted vector is
 /// handled the same was as for ReplaceAllUsesWith.
 void SelectionDAG::ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To,
-                                             std::vector<SDNode*> &Deleted) {
+                                             std::vector<SDNode*> *Deleted) {
   assert(From != To && "Cannot replace a value with itself");
   // Handle the simple, trivial, case efficiently.
   if (From.Val->getNumValues() == 1 && To.Val->getNumValues() == 1) {
-    ReplaceAllUsesWith(From, To, &Deleted);
+    ReplaceAllUsesWith(From, To, Deleted);
     return;
   }
   
@@ -3244,48 +3244,66 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To,
   // deterministically ordered and uniqued set, so we use a SmallSetVector.
   SmallSetVector<SDNode*, 16> Users(From.Val->use_begin(), From.Val->use_end());
 
+  std::vector<SDNode*> LocalDeletionVector;
+  
+  // Pick a deletion vector to use.  If the user specified one, use theirs,
+  // otherwise use a local one.
+  std::vector<SDNode*> *DeleteVector = Deleted ? Deleted : &LocalDeletionVector;
   while (!Users.empty()) {
     // We know that this user uses some value of From.  If it is the right
     // value, update it.
     SDNode *User = Users.back();
     Users.pop_back();
     
-    for (SDOperand *Op = User->OperandList,
-         *E = User->OperandList+User->NumOperands; Op != E; ++Op) {
+    // Scan for an operand that matches From.
+    SDOperand *Op = User->OperandList, *E = User->OperandList+User->NumOperands;
+    for (; Op != E; ++Op)
+      if (*Op == From) break;
+    
+    // If there are no matches, the user must use some other result of From.
+    if (Op == E) continue;
+      
+    // Okay, we know this user needs to be updated.  Remove its old self
+    // from the CSE maps.
+    RemoveNodeFromCSEMaps(User);
+    
+    // Update all operands that match "From".
+    for (; Op != E; ++Op) {
       if (*Op == From) {
-        // Okay, we know this user needs to be updated.  Remove its old self
-        // from the CSE maps.
-        RemoveNodeFromCSEMaps(User);
-        
-        // Update all operands that match "From".
-        for (; Op != E; ++Op) {
-          if (*Op == From) {
-            From.Val->removeUser(User);
-            *Op = To;
-            To.Val->addUser(User);
-          }
-        }
-                   
-        // Now that we have modified User, add it back to the CSE maps.  If it
-        // already exists there, recursively merge the results together.
-        if (SDNode *Existing = AddNonLeafNodeToCSEMaps(User)) {
-          unsigned NumDeleted = Deleted.size();
-          ReplaceAllUsesWith(User, Existing, &Deleted);
-          
-          // User is now dead.
-          Deleted.push_back(User);
-          DeleteNodeNotInCSEMaps(User);
-          
-          // We have to be careful here, because ReplaceAllUsesWith could have
-          // deleted a user of From, which means there may be dangling pointers
-          // in the "Users" setvector.  Scan over the deleted node pointers and
-          // remove them from the setvector.
-          for (unsigned i = NumDeleted, e = Deleted.size(); i != e; ++i)
-            Users.remove(Deleted[i]);
-        }
-        break;   // Exit the operand scanning loop.
+        From.Val->removeUser(User);
+        *Op = To;
+        To.Val->addUser(User);
       }
     }
+               
+    // Now that we have modified User, add it back to the CSE maps.  If it
+    // already exists there, recursively merge the results together.
+    SDNode *Existing = AddNonLeafNodeToCSEMaps(User);
+    if (!Existing) continue;  // Continue on to next user.
+    
+    // If there was already an existing matching node, use ReplaceAllUsesWith
+    // to replace the dead one with the existing one.  However, this can cause
+    // recursive merging of other unrelated nodes down the line.  The merging
+    // can cause deletion of nodes that used the old value.  In this case,
+    // we have to be certain to remove them from the Users set.
+    unsigned NumDeleted = DeleteVector->size();
+    ReplaceAllUsesWith(User, Existing, DeleteVector);
+    
+    // User is now dead.
+    DeleteVector->push_back(User);
+    DeleteNodeNotInCSEMaps(User);
+    
+    // We have to be careful here, because ReplaceAllUsesWith could have
+    // deleted a user of From, which means there may be dangling pointers
+    // in the "Users" setvector.  Scan over the deleted node pointers and
+    // remove them from the setvector.
+    for (unsigned i = NumDeleted, e = DeleteVector->size(); i != e; ++i)
+      Users.remove((*DeleteVector)[i]);
+
+    // If the user doesn't need the set of deleted elements, don't retain them
+    // to the next loop iteration.
+    if (Deleted == 0)
+      LocalDeletionVector.clear();
   }
 }