aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-01-19 21:44:21 +0000
committerDan Gohman <gohman@apple.com>2009-01-19 21:44:21 +0000
commitdbe664adcddd8610952968d86791478c874cf1cd (patch)
tree5d0f6b564ca7fc6a240dde912ad6e20b096def3f /lib/CodeGen/SelectionDAG/SelectionDAG.cpp
parent2c7ed11d93239dacf81540e2307f0db456bb9122 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62533 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAG.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp25
1 files changed, 19 insertions, 6 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index b83d537e37..d8124e6d7c 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/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);