diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAG.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 93 |
1 files changed, 50 insertions, 43 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index b9f84080ba..3f262df713 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -486,42 +486,16 @@ void SelectionDAG::RemoveDeadNodes() { if (I->use_empty()) DeadNodes.push_back(I); - // Process the worklist, deleting the nodes and adding their uses to the - // worklist. - while (!DeadNodes.empty()) { - SDNode *N = DeadNodes.back(); - DeadNodes.pop_back(); - - // Take the node out of the appropriate CSE map. - RemoveNodeFromCSEMaps(N); - - // Next, brutally remove the operand list. This is safe to do, as there are - // no cycles in the graph. - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) { - SDNode *Operand = I->getVal(); - Operand->removeUser(std::distance(N->op_begin(), I), N); - - // Now that we removed this operand, see if there are no uses of it left. - if (Operand->use_empty()) - DeadNodes.push_back(Operand); - } - if (N->OperandsNeedDelete) { - delete[] N->OperandList; - } - N->OperandList = 0; - N->NumOperands = 0; - - // Finally, remove N itself. - AllNodes.erase(N); - } + RemoveDeadNodes(DeadNodes); // If the root changed (e.g. it was a dead load, update the root). setRoot(Dummy.getValue()); } -void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){ - SmallVector<SDNode*, 16> DeadNodes; - DeadNodes.push_back(N); +/// RemoveDeadNodes - This method deletes the unreachable nodes in the +/// given list, and any nodes that become unreachable as a result. +void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes, + DAGUpdateListener *UpdateListener) { // Process the worklist, deleting the nodes and adding their uses to the // worklist. @@ -537,16 +511,13 @@ void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){ // Next, brutally remove the operand list. This is safe to do, as there are // no cycles in the graph. - unsigned op_num = 0; for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) { SDNode *Operand = I->getVal(); - Operand->removeUser(op_num, N); + Operand->removeUser(std::distance(N->op_begin(), I), N); // Now that we removed this operand, see if there are no uses of it left. if (Operand->use_empty()) DeadNodes.push_back(Operand); - - op_num++; } if (N->OperandsNeedDelete) { delete[] N->OperandList; @@ -559,6 +530,12 @@ void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){ } } +void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){ + SmallVector<SDNode*, 16> DeadNodes; + DeadNodes.push_back(N); + RemoveDeadNodes(DeadNodes, UpdateListener); +} + void SelectionDAG::DeleteNode(SDNode *N) { assert(N->use_empty() && "Cannot delete a node that is not dead!"); @@ -3681,16 +3658,22 @@ UpdateNodeOperands(SDOperand InN, const SDOperand *Ops, unsigned NumOps) { /// opcode, types, and operands to the specified value. This should only be /// used by the SelectionDAG class. void SDNode::MorphNodeTo(unsigned Opc, SDVTList L, - const SDOperand *Ops, unsigned NumOps) { + const SDOperand *Ops, unsigned NumOps, + SmallVectorImpl<SDNode *> &DeadNodes) { NodeType = Opc; ValueList = L.VTs; NumValues = L.NumVTs; // Clear the operands list, updating used nodes to remove this from their - // use list. - for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) - I->getVal()->removeUser(std::distance(op_begin(), I), this); - + // use list. Keep track of any operands that become dead as a result. + SmallPtrSet<SDNode*, 16> DeadNodeSet; + for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) { + SDNode *N = I->getVal(); + N->removeUser(std::distance(op_begin(), I), this); + if (N->use_empty()) + DeadNodeSet.insert(N); + } + // If NumOps is larger than the # of operands we currently have, reallocate // the operand list. if (NumOps > NumOperands) { @@ -3710,7 +3693,29 @@ void SDNode::MorphNodeTo(unsigned Opc, SDVTList L, SDNode *N = OperandList[i].getVal(); N->addUser(i, this); ++N->UsesSize; + DeadNodeSet.erase(N); } + + // Clean up any nodes that are still dead after adding the uses for the + // new operands. + for (SmallPtrSet<SDNode *, 16>::iterator I = DeadNodeSet.begin(), + E = DeadNodeSet.end(); I != E; ++I) + DeadNodes.push_back(*I); +} + +/// DropOperands - Release the operands and set this node to have +/// zero operands. This should only be used by HandleSDNode to clear +/// its operand list. +void SDNode::DropOperands() { + assert(NodeType == ISD::HANDLENODE && + "DropOperands is for HANDLENODE only!"); + + // Unlike the code in MorphNodeTo that does this, we don't need to + // watch for dead nodes here. + for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) + I->getVal()->removeUser(std::distance(op_begin(), I), this); + + NumOperands = 0; } /// SelectNodeTo - These are used for target selectors to *mutate* the @@ -3814,7 +3819,10 @@ SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc, RemoveNodeFromCSEMaps(N); - N->MorphNodeTo(ISD::BUILTIN_OP_END+TargetOpc, VTs, Ops, NumOps); + SmallVector<SDNode *, 16> DeadNodes; + N->MorphNodeTo(ISD::BUILTIN_OP_END+TargetOpc, VTs, Ops, NumOps, DeadNodes); + RemoveDeadNodes(DeadNodes); + CSEMap.InsertNode(N, IP); // Memoize the new node. return N; } @@ -4250,8 +4258,7 @@ void StoreSDNode::ANCHOR() {} void AtomicSDNode::ANCHOR() {} HandleSDNode::~HandleSDNode() { - SDVTList VTs = { 0, 0 }; - MorphNodeTo(ISD::HANDLENODE, VTs, 0, 0); // Drops operand uses. + DropOperands(); } GlobalAddressSDNode::GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, |