diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a57d815c2d5d..ab27925189e4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -53,31 +53,12 @@ namespace { bool AfterLegalize; bool Fast; - // Create a dummy node (which is not added to allnodes), that adds a reference - // to the root node, preventing it from being deleted, and tracking any - // changes of the root. - HandleSDNode Dummy; - // Worklist of all of the nodes that need to be simplified. - SmallVector WorkList; - - // The current position of our iteration through the allnodes list. - SelectionDAG::allnodes_iterator CurNode; + std::vector WorkList; // AA - Used for DAG load/store alias analysis. AliasAnalysis &AA; - /// AdvanceCurNode - Update CurNode to point to the next node to process. - /// - void AdvanceCurNode() { - // We start at the end of the list and work towards the front. Setting - // CurNode to DAG.allnodes_end() indicates that we're done. - if (CurNode == DAG.allnodes_begin()) - CurNode = DAG.allnodes_end(); - else - --CurNode; - } - /// AddUsersToWorkList - When an instruction is simplified, add all users of /// the instruction to the work lists because they might get more simplified /// now. @@ -105,10 +86,6 @@ namespace { void removeFromWorkList(SDNode *N) { WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), N), WorkList.end()); - // If the next node we were planning to process is deleted, - // skip past it. - if (N == CurNode) - AdvanceCurNode(); } SDValue CombineTo(SDNode *N, const SDValue *To, unsigned NumTo, @@ -148,9 +125,9 @@ namespace { // Visitation implementation - Implement dag node combining for different // node types. The semantics are as follows: // Return Value: - // SDValue.getNode() == 0 - No change was made - // SDValue.getNode() == N - N was replaced, is dead, and is already handled. - // otherwise - N should be replaced by the returned Operand. + // SDValue.getNode() == 0 - No change was made + // SDValue.getNode() == N - N was replaced, is dead and has been handled. + // otherwise - N should be replaced by the returned Operand. // SDValue visitTokenFactor(SDNode *N); SDValue visitMERGE_VALUES(SDNode *N); @@ -266,14 +243,10 @@ public: TLI(D.getTargetLoweringInfo()), AfterLegalize(false), Fast(fast), - Dummy(D.getRoot()), AA(A) {} /// Run - runs the dag combiner on all nodes in the work list void Run(bool RunningAfterLegalize); - - /// ProcessNode - runs the dag combiner on a node - void ProcessNode(SDNode *N); }; } @@ -602,89 +575,91 @@ bool DAGCombiner::SimplifyDemandedBits(SDValue Op, const APInt &Demanded) { // Main DAG Combiner implementation //===----------------------------------------------------------------------===// -void DAGCombiner::ProcessNode(SDNode *N) { - // If N has no uses, it is dead. Make sure to revisit all N's operands once - // N is deleted from the DAG, since they too may now be dead or may have a - // reduced number of uses, allowing other xforms. - if (N->use_empty() && N != &Dummy) { - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) - AddToWorkList(N->getOperand(i).getNode()); - - DAG.DeleteNode(N); - return; - } - - SDValue RV = combine(N); - - if (RV.getNode() == 0) - return; - - ++NodesCombined; - - // If we get back the same node we passed in, rather than a new node or - // zero, we know that the node must have defined multiple values and - // CombineTo was used. Since CombineTo takes care of the worklist - // mechanics for us, we have no work to do in this case. - if (RV.getNode() == N) - return; - - assert(N->getOpcode() != ISD::DELETED_NODE && - RV.getNode()->getOpcode() != ISD::DELETED_NODE && - "Node was deleted but visit returned new node!"); - - DOUT << "\nReplacing.3 "; DEBUG(N->dump(&DAG)); - DOUT << "\nWith: "; DEBUG(RV.getNode()->dump(&DAG)); - DOUT << '\n'; - - if (N->getNumValues() == RV.getNode()->getNumValues()) - DAG.ReplaceAllUsesWith(N, RV.getNode()); - else { - assert(N->getValueType(0) == RV.getValueType() && - N->getNumValues() == 1 && "Type mismatch"); - SDValue OpV = RV; - DAG.ReplaceAllUsesWith(N, &OpV); - } - - // Delete the old node. - removeFromWorkList(N); - DAG.DeleteNode(N); - - // Push the new node and any users onto the worklist - AddToWorkList(RV.getNode()); - AddUsersToWorkList(RV.getNode()); -} - void DAGCombiner::Run(bool RunningAfterLegalize) { // set the instance variable, so that the various visit routines may use it. AfterLegalize = RunningAfterLegalize; + // Add all the dag nodes to the worklist. + WorkList.reserve(DAG.allnodes_size()); + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) + WorkList.push_back(I); + + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted, and tracking any + // changes of the root. + HandleSDNode Dummy(DAG.getRoot()); + // The root of the dag may dangle to deleted nodes until the dag combiner is // done. Set it to null to avoid confusion. DAG.setRoot(SDValue()); - // Process all the original dag nodes. We process starting from the - // end of the list and working forward, which is in roughly topological - // order. Starting at the end and working forward means we won't - // accidentally revisit nodes created during the dagcombine process. - CurNode = prior(DAG.allnodes_end()); - do { - SDNode *N = &*CurNode; - AdvanceCurNode(); - ProcessNode(N); - // Processing the node may have resulted in nodes being added to the - // worklist, because the were newly created or because one of their - // operands changed or some other reason they should be revisited. - // While the worklist isn't empty, inspect the node on the end of it - // and try and combine it. - while (!WorkList.empty()) { - SDNode *N = WorkList.back(); - WorkList.pop_back(); - if (N == CurNode) - AdvanceCurNode(); - ProcessNode(N); + // while the worklist isn't empty, inspect the node on the end of it and + // try and combine it. + while (!WorkList.empty()) { + SDNode *N = WorkList.back(); + WorkList.pop_back(); + + // If N has no uses, it is dead. Make sure to revisit all N's operands once + // N is deleted from the DAG, since they too may now be dead or may have a + // reduced number of uses, allowing other xforms. + if (N->use_empty() && N != &Dummy) { + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + AddToWorkList(N->getOperand(i).getNode()); + + DAG.DeleteNode(N); + continue; } - } while (CurNode != DAG.allnodes_end()); + + SDValue RV = combine(N); + + if (RV.getNode() == 0) + continue; + + ++NodesCombined; + + // If we get back the same node we passed in, rather than a new node or + // zero, we know that the node must have defined multiple values and + // CombineTo was used. Since CombineTo takes care of the worklist + // mechanics for us, we have no work to do in this case. + if (RV.getNode() == N) + continue; + + assert(N->getOpcode() != ISD::DELETED_NODE && + RV.getNode()->getOpcode() != ISD::DELETED_NODE && + "Node was deleted but visit returned new node!"); + DOUT << "\nReplacing.3 "; DEBUG(N->dump(&DAG)); + DOUT << "\nWith: "; DEBUG(RV.getNode()->dump(&DAG)); + DOUT << '\n'; + WorkListRemover DeadNodes(*this); + if (N->getNumValues() == RV.getNode()->getNumValues()) + DAG.ReplaceAllUsesWith(N, RV.getNode(), &DeadNodes); + else { + assert(N->getValueType(0) == RV.getValueType() && + N->getNumValues() == 1 && "Type mismatch"); + SDValue OpV = RV; + DAG.ReplaceAllUsesWith(N, &OpV, &DeadNodes); + } + + // Push the new node and any users onto the worklist + AddToWorkList(RV.getNode()); + AddUsersToWorkList(RV.getNode()); + + // Add any uses of the old node to the worklist in case this node is the + // last one that uses them. They may become dead after this node is + // deleted. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + AddToWorkList(N->getOperand(i).getNode()); + + // Nodes can be reintroduced into the worklist. Make sure we do not + // process a node that has been replaced. + removeFromWorkList(N); + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); + } + // If the root changed (e.g. it was a dead load, update the root). DAG.setRoot(Dummy.getValue()); } @@ -3453,7 +3428,7 @@ SDValue DAGCombiner::visitBIT_CONVERT(SDNode *N) { } } - // If the input is a constant, let getNode() fold it. + // If the input is a constant, let Val fold it. if (isa(N0) || isa(N0)) { SDValue Res = DAG.getNode(ISD::BIT_CONVERT, VT, N0); if (Res.getNode() != N) return Res;