From cd0b1bf0a06dec7da3860090d5a9d214a220753c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 19 Jan 2009 21:44:21 +0000 Subject: Fix SelectionDAG::ReplaceAllUsesWith to behave correctly when uses are added to the From node while it is processing From's use list, because of automatic local CSE. The fix is to avoid visiting any new uses. Fix a few places in the DAGCombiner that assumed that after a RAUW call, the From node has no users and may be deleted. This fixes PR3018. llvm-svn: 62533 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp') diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index b83d537e372..d8124e6d7c3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4388,9 +4388,16 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To, "Cannot replace with this method!"); assert(From != To.getNode() && "Cannot replace uses of with self"); - while (!From->use_empty()) { - SDNode::use_iterator UI = From->use_begin(); + // Iterate over all the existing uses of From. This specifically avoids + // visiting any new uses of From that arrise while the replacement is + // happening, because any such uses would be the result of CSE: If an + // existing node looks like From after one of its operands is replaced + // by To, we don't want to replace of all its users with To too. + // See PR3018 for more info. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + while (UI != UE) { SDNode *U = *UI; + do ++UI; while (UI != UE && *UI == U); // This node is about to morph, remove its old self from the CSE maps. RemoveNodeFromCSEMaps(U); @@ -4437,9 +4444,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To, if (From == To) return; - while (!From->use_empty()) { - SDNode::use_iterator UI = From->use_begin(); + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + while (UI != UE) { SDNode *U = *UI; + do ++UI; while (UI != UE && *UI == U); // This node is about to morph, remove its old self from the CSE maps. RemoveNodeFromCSEMaps(U); @@ -4480,9 +4490,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, if (From->getNumValues() == 1) // Handle the simple case efficiently. return ReplaceAllUsesWith(SDValue(From, 0), To[0], UpdateListener); - while (!From->use_empty()) { - SDNode::use_iterator UI = From->use_begin(); + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + while (UI != UE) { SDNode *U = *UI; + do ++UI; while (UI != UE && *UI == U); // This node is about to morph, remove its old self from the CSE maps. RemoveNodeFromCSEMaps(U); -- cgit v1.2.3