Clean up RemoveDeadNodes significantly, by eliminating the need for a temporary

set and eliminating the need to iterate whenever something is removed (which
can be really slow in some cases).  Thx to Jim for pointing out something silly
I was getting stuck on. :)

llvm-svn: 24241
This commit is contained in:
Chris Lattner 2005-11-08 18:52:27 +00:00
parent 88e234dd49
commit aba48dd34c
1 changed files with 35 additions and 33 deletions

View File

@ -167,41 +167,47 @@ const TargetMachine &SelectionDAG::getTarget() const {
/// chain but no other uses and no side effect. If a node is passed in as an /// chain but no other uses and no side effect. If a node is passed in as an
/// argument, it is used as the seed for node deletion. /// argument, it is used as the seed for node deletion.
void SelectionDAG::RemoveDeadNodes(SDNode *N) { void SelectionDAG::RemoveDeadNodes(SDNode *N) {
std::set<SDNode*> AllNodeSet(AllNodes.begin(), AllNodes.end());
// Create a dummy node (which is not added to allnodes), that adds a reference // Create a dummy node (which is not added to allnodes), that adds a reference
// to the root node, preventing it from being deleted. // to the root node, preventing it from being deleted.
HandleSDNode Dummy(getRoot()); HandleSDNode Dummy(getRoot());
bool MadeChange = false;
// If we have a hint to start from, use it. // If we have a hint to start from, use it.
if (N) DeleteNodeIfDead(N, &AllNodeSet); if (N && N->use_empty()) {
DestroyDeadNode(N);
Restart: MadeChange = true;
unsigned NumNodes = AllNodeSet.size();
for (std::set<SDNode*>::iterator I = AllNodeSet.begin(), E = AllNodeSet.end();
I != E; ++I) {
// Try to delete this node.
DeleteNodeIfDead(*I, &AllNodeSet);
// If we actually deleted any nodes, do not use invalid iterators in
// AllNodeSet.
if (AllNodeSet.size() != NumNodes)
goto Restart;
} }
// Restore AllNodes. for (unsigned i = 0, e = AllNodes.size(); i != e; ++i) {
if (AllNodes.size() != NumNodes) // Try to delete this node.
AllNodes.assign(AllNodeSet.begin(), AllNodeSet.end()); SDNode *N = AllNodes[i];
if (N->use_empty() && N->getOpcode() != 65535) {
DestroyDeadNode(N);
MadeChange = true;
}
}
// Walk the nodes list, removing the nodes we've marked as dead.
if (MadeChange) {
for (unsigned i = 0, e = AllNodes.size(); i != e; ++i)
if (AllNodes[i]->use_empty()) {
delete AllNodes[i];
AllNodes[i] = AllNodes.back();
AllNodes.pop_back();
--i; --e;
}
}
// If the root changed (e.g. it was a dead load, update the root). // If the root changed (e.g. it was a dead load, update the root).
setRoot(Dummy.getValue()); setRoot(Dummy.getValue());
} }
/// DestroyDeadNode - We know that N is dead. Nuke it from the CSE maps for the
void SelectionDAG::DeleteNodeIfDead(SDNode *N, void *NodeSet) { /// graph. If it is the last user of any of its operands, recursively process
if (!N->use_empty()) /// them the same way.
return; ///
void SelectionDAG::DestroyDeadNode(SDNode *N) {
// Okay, we really are going to delete this node. First take this out of the // Okay, we really are going to delete this node. First take this out of the
// appropriate CSE map. // appropriate CSE map.
RemoveNodeFromCSEMaps(N); RemoveNodeFromCSEMaps(N);
@ -214,16 +220,12 @@ void SelectionDAG::DeleteNodeIfDead(SDNode *N, void *NodeSet) {
O->removeUser(N); O->removeUser(N);
// Now that we removed this operand, see if there are no uses of it left. // Now that we removed this operand, see if there are no uses of it left.
DeleteNodeIfDead(O, NodeSet); if (O->use_empty())
DestroyDeadNode(O);
} }
// Remove the node from the nodes set and delete it. // Mark the node as dead.
std::set<SDNode*> &AllNodeSet = *(std::set<SDNode*>*)NodeSet; N->MorphNodeTo(65535);
AllNodeSet.erase(N);
// Now that the node is gone, check to see if any of the operands of this node
// are dead now.
delete N;
} }
void SelectionDAG::DeleteNode(SDNode *N) { void SelectionDAG::DeleteNode(SDNode *N) {