mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-21 00:32:23 +00:00
Fix a bug in SelectionDAG's ReplaceAllUsesWith in the case where
CSE and recursive RAUW calls delete a node from the use list, invalidating the use list iterator. There's currently no known way to reproduce this in an unmodified LLVM, however there's no fundamental reason why a SelectionDAG couldn't be formed which would trigger this case. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97665 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
16b48b8a05
commit
a72d2a210c
@ -4869,6 +4869,43 @@ SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// RAUWUpdateListner - Helper for ReplaceAllUsesWith - When the node
|
||||
/// pointed to by a use iterator is deleted, increment the use iterator
|
||||
/// so that it doesn't dangle.
|
||||
///
|
||||
/// This class also manages a "downlink" DAGUpdateListener, to forward
|
||||
/// messages to ReplaceAllUsesWith's callers.
|
||||
///
|
||||
class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener {
|
||||
SelectionDAG::DAGUpdateListener *DownLink;
|
||||
SDNode::use_iterator &UI;
|
||||
SDNode::use_iterator &UE;
|
||||
|
||||
virtual void NodeDeleted(SDNode *N, SDNode *E) {
|
||||
// Increment the iterator as needed.
|
||||
while (UI != UE && N == *UI)
|
||||
++UI;
|
||||
|
||||
// Then forward the message.
|
||||
if (DownLink) DownLink->NodeDeleted(N, E);
|
||||
}
|
||||
|
||||
virtual void NodeUpdated(SDNode *N) {
|
||||
// Just forward the message.
|
||||
if (DownLink) DownLink->NodeUpdated(N);
|
||||
}
|
||||
|
||||
public:
|
||||
RAUWUpdateListener(SelectionDAG::DAGUpdateListener *dl,
|
||||
SDNode::use_iterator &ui,
|
||||
SDNode::use_iterator &ue)
|
||||
: DownLink(dl), UI(ui), UE(ue) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead.
|
||||
/// This can cause recursive merging of nodes in the DAG.
|
||||
///
|
||||
@ -4889,6 +4926,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To,
|
||||
// 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();
|
||||
RAUWUpdateListener Listener(UpdateListener, UI, UE);
|
||||
while (UI != UE) {
|
||||
SDNode *User = *UI;
|
||||
|
||||
@ -4907,7 +4945,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To,
|
||||
|
||||
// Now that we have modified User, add it back to the CSE maps. If it
|
||||
// already exists there, recursively merge the results together.
|
||||
AddModifiedNodeToCSEMaps(User, UpdateListener);
|
||||
AddModifiedNodeToCSEMaps(User, &Listener);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4933,6 +4971,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To,
|
||||
// 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();
|
||||
RAUWUpdateListener Listener(UpdateListener, UI, UE);
|
||||
while (UI != UE) {
|
||||
SDNode *User = *UI;
|
||||
|
||||
@ -4951,7 +4990,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To,
|
||||
|
||||
// Now that we have modified User, add it back to the CSE maps. If it
|
||||
// already exists there, recursively merge the results together.
|
||||
AddModifiedNodeToCSEMaps(User, UpdateListener);
|
||||
AddModifiedNodeToCSEMaps(User, &Listener);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4969,6 +5008,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From,
|
||||
// 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();
|
||||
RAUWUpdateListener Listener(UpdateListener, UI, UE);
|
||||
while (UI != UE) {
|
||||
SDNode *User = *UI;
|
||||
|
||||
@ -4988,7 +5028,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From,
|
||||
|
||||
// Now that we have modified User, add it back to the CSE maps. If it
|
||||
// already exists there, recursively merge the results together.
|
||||
AddModifiedNodeToCSEMaps(User, UpdateListener);
|
||||
AddModifiedNodeToCSEMaps(User, &Listener);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5010,6 +5050,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To,
|
||||
// the ReplaceAllUsesWith above.
|
||||
SDNode::use_iterator UI = From.getNode()->use_begin(),
|
||||
UE = From.getNode()->use_end();
|
||||
RAUWUpdateListener Listener(UpdateListener, UI, UE);
|
||||
while (UI != UE) {
|
||||
SDNode *User = *UI;
|
||||
bool UserRemovedFromCSEMaps = false;
|
||||
@ -5045,7 +5086,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To,
|
||||
|
||||
// Now that we have modified User, add it back to the CSE maps. If it
|
||||
// already exists there, recursively merge the results together.
|
||||
AddModifiedNodeToCSEMaps(User, UpdateListener);
|
||||
AddModifiedNodeToCSEMaps(User, &Listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user