diff options
author | Chris Lattner <sabre@nondot.org> | 2005-01-07 21:09:16 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2005-01-07 21:09:16 +0000 |
commit | 0e12e6e0418564d4b2e83138fe2044be29a6f6d5 (patch) | |
tree | 6ca1885050cac15f1c1ce126ab3e97a1a1694bb8 /lib/CodeGen/SelectionDAG/SelectionDAG.cpp | |
parent | d1fc96499b7619356c7542200d32da898b79f7c1 (diff) |
Implement RemoveDeadNodes
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19345 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAG.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index f02bdcd95b..3fdc7fe995 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -17,6 +17,7 @@ #include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include <iostream> +#include <set> #include <cmath> using namespace llvm; @@ -98,6 +99,124 @@ ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2, return ISD::CondCode(Op1 & Op2); } +/// RemoveDeadNodes - This method deletes all unreachable nodes in the +/// SelectionDAG, including nodes (like loads) that have uses of their token +/// 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. +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 + // to the root node, preventing it from being deleted. + SDNode *DummyNode = new SDNode(ISD::EntryToken, getRoot()); + + DeleteNodeIfDead(N, &AllNodeSet); + + Restart: + 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. + if (AllNodes.size() != NumNodes) + AllNodes.assign(AllNodeSet.begin(), AllNodeSet.end()); + + // If the root changed (e.g. it was a dead load, update the root). + setRoot(DummyNode->getOperand(0)); + + // Now that we are done with the dummy node, delete it. + DummyNode->getOperand(0).Val->removeUser(DummyNode); + delete DummyNode; +} + +void SelectionDAG::DeleteNodeIfDead(SDNode *N, void *NodeSet) { + if (!N->use_empty()) + return; + + // Okay, we really are going to delete this node. First take this out of the + // appropriate CSE map. + switch (N->getOpcode()) { + case ISD::Constant: + Constants.erase(std::make_pair(cast<ConstantSDNode>(N)->getValue(), + N->getValueType(0))); + break; + case ISD::ConstantFP: + ConstantFPs.erase(std::make_pair(cast<ConstantFPSDNode>(N)->getValue(), + N->getValueType(0))); + break; + case ISD::GlobalAddress: + GlobalValues.erase(cast<GlobalAddressSDNode>(N)->getGlobal()); + break; + case ISD::FrameIndex: + FrameIndices.erase(cast<FrameIndexSDNode>(N)->getIndex()); + break; + case ISD::ConstantPool: + ConstantPoolIndices.erase(cast<ConstantPoolSDNode>(N)->getIndex()); + break; + case ISD::BasicBlock: + BBNodes.erase(cast<BasicBlockSDNode>(N)->getBasicBlock()); + break; + case ISD::ExternalSymbol: + ExternalSymbols.erase(cast<ExternalSymbolSDNode>(N)->getSymbol()); + break; + + case ISD::LOAD: + Loads.erase(std::make_pair(N->getOperand(1), + std::make_pair(N->getOperand(0), + N->getValueType(0)))); + break; + case ISD::SETCC: + SetCCs.erase(std::make_pair(std::make_pair(N->getOperand(0), + N->getOperand(1)), + cast<SetCCSDNode>(N)->getCondition())); + break; + default: + if (N->getNumOperands() == 1) + UnaryOps.erase(std::make_pair(N->getOpcode(), + std::make_pair(N->getOperand(0), + N->getValueType(0)))); + else if (N->getNumOperands() == 2) + BinaryOps.erase(std::make_pair(N->getOpcode(), + std::make_pair(N->getOperand(0), + N->getOperand(1)))); + break; + } + + // Next, brutally remove the operand list. + std::vector<SDNode*> Operands; + while (!N->Operands.empty()) { + SDOperand O = N->Operands.back(); + N->Operands.pop_back(); + Operands.push_back(O.Val); + O.Val->removeUser(N); + } + + // Remove the node from the nodes set and delete it. + std::set<SDNode*> &AllNodeSet = *(std::set<SDNode*>*)NodeSet; + AllNodeSet.erase(N); + delete N; + + // Now that the node is gone, check to see if any of the operands of this node + // are dead now. + + // Remove duplicate operand entries. + std::sort(Operands.begin(), Operands.end()); + Operands.erase(std::unique(Operands.begin(), Operands.end()), + Operands.end()); + + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + DeleteNodeIfDead(Operands[i], NodeSet); +} + + SelectionDAG::~SelectionDAG() { for (unsigned i = 0, e = AllNodes.size(); i != e; ++i) delete AllNodes[i]; |