[llvm-commits] [llvm] r55498 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/alloca-align-rounding.ll
Dan Gohman
gohman at apple.com
Thu Aug 28 14:01:56 PDT 2008
Author: djg
Date: Thu Aug 28 16:01:56 2008
New Revision: 55498
URL: http://llvm.org/viewvc/llvm-project?rev=55498&view=rev
Log:
Optimize DAGCombiner's worklist processing. Previously it started
its work by putting all nodes in the worklist, requiring a big
dynamic allocation. Now, DAGCombiner just iterates over the AllNodes
list and maintains a worklist for nodes that are newly created or
need to be revisited. This allows the worklist to stay small in most
cases, so it can be a SmallVector.
This has the side effect of making DAGCombine not miss a folding
opportunity in alloca-align-rounding.ll.
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/trunk/test/CodeGen/X86/alloca-align-rounding.ll
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=55498&r1=55497&r2=55498&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Thu Aug 28 16:01:56 2008
@@ -53,12 +53,31 @@
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.
- std::vector<SDNode*> WorkList;
+ SmallVector<SDNode*, 8> WorkList;
+
+ // The current position of our iteration through the allnodes list.
+ SelectionDAG::allnodes_iterator CurNode;
// 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.
@@ -86,6 +105,10 @@
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,
@@ -243,10 +266,14 @@
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);
};
}
@@ -575,91 +602,89 @@
// 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).Val);
+
+ DAG.DeleteNode(N);
+ return;
+ }
+
+ SDValue RV = combine(N);
+
+ if (RV.Val == 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.Val == N)
+ return;
+
+ assert(N->getOpcode() != ISD::DELETED_NODE &&
+ RV.Val->getOpcode() != ISD::DELETED_NODE &&
+ "Node was deleted but visit returned new node!");
+
+ DOUT << "\nReplacing.3 "; DEBUG(N->dump(&DAG));
+ DOUT << "\nWith: "; DEBUG(RV.Val->dump(&DAG));
+ DOUT << '\n';
+
+ if (N->getNumValues() == RV.Val->getNumValues())
+ DAG.ReplaceAllUsesWith(N, RV.Val);
+ 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.Val);
+ AddUsersToWorkList(RV.Val);
+}
+
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());
- // 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).Val);
-
- DAG.DeleteNode(N);
- continue;
+ // 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);
}
-
- SDValue RV = combine(N);
-
- if (RV.Val == 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.Val == N)
- continue;
-
- assert(N->getOpcode() != ISD::DELETED_NODE &&
- RV.Val->getOpcode() != ISD::DELETED_NODE &&
- "Node was deleted but visit returned new node!");
+ } while (CurNode != DAG.allnodes_end());
- DOUT << "\nReplacing.3 "; DEBUG(N->dump(&DAG));
- DOUT << "\nWith: "; DEBUG(RV.Val->dump(&DAG));
- DOUT << '\n';
- WorkListRemover DeadNodes(*this);
- if (N->getNumValues() == RV.Val->getNumValues())
- DAG.ReplaceAllUsesWith(N, RV.Val, &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.Val);
- AddUsersToWorkList(RV.Val);
-
- // 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).Val);
-
- // 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());
}
Modified: llvm/trunk/test/CodeGen/X86/alloca-align-rounding.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/alloca-align-rounding.ll?rev=55498&r1=55497&r2=55498&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/alloca-align-rounding.ll (original)
+++ llvm/trunk/test/CodeGen/X86/alloca-align-rounding.ll Thu Aug 28 16:01:56 2008
@@ -1,5 +1,5 @@
; RUN: llvm-as < %s | llc -march=x86 -mtriple=i686-apple-darwin | grep and | count 1
-; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=i686-pc-linux | grep and | count 3
+; RUN: llvm-as < %s | llc -march=x86-64 -mtriple=i686-pc-linux | grep and | count 1
declare void @bar(<2 x i64>* %n)
More information about the llvm-commits
mailing list