Worklist.push_back(N);
}
-void DAGTypeLegalizer::SanityCheck(SDNode *N) {
- for (SmallVector<SDNode*, 128>::iterator I = Worklist.begin(),
- E = Worklist.end(); I != E; ++I)
- assert(*I != N);
-
- for (DenseMap<SDOperand, SDOperand>::iterator I = ReplacedNodes.begin(),
- E = ReplacedNodes.end(); I != E; ++I) {
- assert(I->first.Val != N);
- assert(I->second.Val != N);
- }
-
- for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedNodes.begin(),
- E = PromotedNodes.end(); I != E; ++I) {
- assert(I->first.Val != N);
- assert(I->second.Val != N);
- }
-
- for (DenseMap<SDOperand, SDOperand>::iterator
- I = FloatToIntedNodes.begin(),
- E = FloatToIntedNodes.end(); I != E; ++I) {
- assert(I->first.Val != N);
- assert(I->second.Val != N);
- }
-
- for (DenseMap<SDOperand, SDOperand>::iterator I = ScalarizedNodes.begin(),
- E = ScalarizedNodes.end(); I != E; ++I) {
- assert(I->first.Val != N);
- assert(I->second.Val != N);
- }
-
- for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
- I = ExpandedNodes.begin(), E = ExpandedNodes.end(); I != E; ++I) {
- assert(I->first.Val != N);
- assert(I->second.first.Val != N);
- assert(I->second.second.Val != N);
- }
-
- for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
- I = SplitNodes.begin(), E = SplitNodes.end(); I != E; ++I) {
- assert(I->first.Val != N);
- assert(I->second.first.Val != N);
- assert(I->second.second.Val != N);
- }
-}
-
namespace {
/// NodeUpdateListener - This class is a DAGUpdateListener that listens for
/// updates to nodes and recomputes their ready state.
public:
NodeUpdateListener(DAGTypeLegalizer &dtl) : DTL(dtl) {}
- virtual void NodeDeleted(SDNode *N) {
- // Ignore deletes.
+ virtual void NodeDeleted(SDNode *N, SDNode *E) {
assert(N->getNodeId() != DAGTypeLegalizer::Processed &&
N->getNodeId() != DAGTypeLegalizer::ReadyToProcess &&
"RAUW deleted processed node!");
-#ifndef NDEBUG
- DTL.SanityCheck(N);
-#endif
+ // It is possible, though rare, for the deleted node N to occur as a
+ // target in a map, so note the replacement N -> E in ReplacedNodes.
+ assert(E && "Node not replaced?");
+ for (unsigned i = 0, e = E->getNumValues(); i != e; ++i)
+ DTL.NoteReplacement(SDOperand(N, i), SDOperand(E, i));
}
virtual void NodeUpdated(SDNode *N) {
NodeUpdateListener NUL(*this);
DAG.ReplaceAllUsesOfValueWith(From, To, &NUL);
- // The old node may still be present in ExpandedNodes or PromotedNodes.
- // Inform them about the replacement.
- ReplacedNodes[From] = To;
+ // The old node may still be present in a map like ExpandedNodes or
+ // PromotedNodes. Inform maps about the replacement.
+ NoteReplacement(From, To);
}
/// ReplaceNodeWith - Replace uses of the 'from' node's results with the 'to'
// can potentially cause recursive merging.
NodeUpdateListener NUL(*this);
DAG.ReplaceAllUsesWith(From, To, &NUL);
-
- // The old node may still be present in ExpandedNodes or PromotedNodes.
- // Inform them about the replacement.
+
+ // The old node may still be present in a map like ExpandedNodes or
+ // PromotedNodes. Inform maps about the replacement.
for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) {
assert(From->getValueType(i) == To->getValueType(i) &&
"Node results don't match");
- ReplacedNodes[SDOperand(From, i)] = SDOperand(To, i);
+ NoteReplacement(SDOperand(From, i), SDOperand(To, i));
}
}
}
}
+/// ExpungeNode - If this is a deleted value that was kept around to speed up
+/// remapping, remove it globally now. The only map that can have a deleted
+/// node as a source is ReplacedNodes. Other maps can have deleted nodes as
+/// targets, but since their looked-up values are always immediately remapped
+/// using RemapNode, resulting in a not-deleted node, this is harmless as long
+/// as ReplacedNodes/RemapNode always performs correct mappings. The mapping
+/// will always be correct as long as ExpungeNode is called on the source when
+/// adding a new node to ReplacedNodes, and called on the target when adding
+/// a new node to any map.
+void DAGTypeLegalizer::ExpungeNode(SDOperand N) {
+ SDOperand Replacement = N;
+ RemapNode(Replacement);
+ if (Replacement != N) {
+ // Remove N from all maps - this is expensive but extremely rare.
+ ReplacedNodes.erase(N);
+
+ for (DenseMap<SDOperand, SDOperand>::iterator I = ReplacedNodes.begin(),
+ E = ReplacedNodes.end(); I != E; ++I) {
+ if (I->second == N)
+ I->second = Replacement;
+ }
+
+ for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedNodes.begin(),
+ E = PromotedNodes.end(); I != E; ++I) {
+ assert(I->first != N);
+ if (I->second == N)
+ I->second = Replacement;
+ }
+
+ for (DenseMap<SDOperand, SDOperand>::iterator I = FloatToIntedNodes.begin(),
+ E = FloatToIntedNodes.end(); I != E; ++I) {
+ assert(I->first != N);
+ if (I->second == N)
+ I->second = Replacement;
+ }
+
+ for (DenseMap<SDOperand, SDOperand>::iterator I = ScalarizedNodes.begin(),
+ E = ScalarizedNodes.end(); I != E; ++I) {
+ assert(I->first != N);
+ if (I->second == N)
+ I->second = Replacement;
+ }
+
+ for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
+ I = ExpandedNodes.begin(), E = ExpandedNodes.end(); I != E; ++I) {
+ assert(I->first != N);
+ if (I->second.first == N)
+ I->second.first = Replacement;
+ if (I->second.second == N)
+ I->second.second = Replacement;
+ }
+
+ for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
+ I = SplitNodes.begin(), E = SplitNodes.end(); I != E; ++I) {
+ assert(I->first != N);
+ if (I->second.first == N)
+ I->second.first = Replacement;
+ if (I->second.second == N)
+ I->second.second = Replacement;
+ }
+ }
+}
+
+
void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) {
+ ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
SDOperand &OpEntry = PromotedNodes[Op];
}
void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) {
+ ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
SDOperand &OpEntry = FloatToIntedNodes[Op];
}
void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) {
+ ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
SDOperand &OpEntry = ScalarizedNodes[Op];
}
void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
+ ExpungeNode(Lo);
+ ExpungeNode(Hi);
+
// Lo/Hi may have been newly allocated, if so, add nodeid's as relevant.
AnalyzeNewNode(Lo.Val);
AnalyzeNewNode(Hi.Val);
}
void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
+ ExpungeNode(Lo);
+ ExpungeNode(Hi);
+
// Lo/Hi may have been newly allocated, if so, add nodeid's as relevant.
AnalyzeNewNode(Lo.Val);
AnalyzeNewNode(Hi.Val);
DeadNodes.pop_back();
if (UpdateListener)
- UpdateListener->NodeDeleted(N);
+ UpdateListener->NodeDeleted(N, 0);
// Take the node out of the appropriate CSE map.
RemoveNodeFromCSEMaps(N);
ReplaceAllUsesWith(U, Existing, UpdateListener);
// U is now dead. Inform the listener if it exists and delete it.
if (UpdateListener)
- UpdateListener->NodeDeleted(U);
+ UpdateListener->NodeDeleted(U, Existing);
DeleteNodeNotInCSEMaps(U);
} else {
// If the node doesn't already exist, we updated it. Inform a listener if
ReplaceAllUsesWith(U, Existing, UpdateListener);
// U is now dead. Inform the listener if it exists and delete it.
if (UpdateListener)
- UpdateListener->NodeDeleted(U);
+ UpdateListener->NodeDeleted(U, Existing);
DeleteNodeNotInCSEMaps(U);
} else {
// If the node doesn't already exist, we updated it. Inform a listener if
ReplaceAllUsesWith(U, Existing, UpdateListener);
// U is now dead. Inform the listener if it exists and delete it.
if (UpdateListener)
- UpdateListener->NodeDeleted(U);
+ UpdateListener->NodeDeleted(U, Existing);
DeleteNodeNotInCSEMaps(U);
} else {
// If the node doesn't already exist, we updated it. Inform a listener if
SelectionDAG::DAGUpdateListener *chain)
: Set(set), Chain(chain) {}
- virtual void NodeDeleted(SDNode *N) {
+ virtual void NodeDeleted(SDNode *N, SDNode *E) {
Set.remove(N);
- if (Chain) Chain->NodeDeleted(N);
+ if (Chain) Chain->NodeDeleted(N, E);
}
virtual void NodeUpdated(SDNode *N) {
if (Chain) Chain->NodeUpdated(N);
ReplaceAllUsesWith(User, Existing, &CSUL);
// User is now dead. Notify a listener if present.
- if (UpdateListener) UpdateListener->NodeDeleted(User);
+ if (UpdateListener) UpdateListener->NodeDeleted(User, Existing);
DeleteNodeNotInCSEMaps(User);
}
}