| Index: src/compiler/graph-reducer.cc
|
| diff --git a/src/compiler/graph-reducer.cc b/src/compiler/graph-reducer.cc
|
| index 7f3a66e0decdba47017d5980f172d3bc5b379351..676b5438951cfdb7eb76b089d7e6f03781d82a14 100644
|
| --- a/src/compiler/graph-reducer.cc
|
| +++ b/src/compiler/graph-reducer.cc
|
| @@ -12,6 +12,9 @@ namespace v8 {
|
| namespace internal {
|
| namespace compiler {
|
|
|
| +bool Reducer::Finish() { return true; }
|
| +
|
| +
|
| enum class GraphReducer::State : uint8_t {
|
| kUnvisited,
|
| kRevisit,
|
| @@ -28,8 +31,14 @@ GraphReducer::GraphReducer(Graph* graph, Zone* zone)
|
| stack_(zone) {}
|
|
|
|
|
| +GraphReducer::~GraphReducer() {
|
| + for (Reducer* reducer : reducers_) reducer->set_observer(nullptr);
|
| +}
|
| +
|
| +
|
| void GraphReducer::AddReducer(Reducer* reducer) {
|
| reducers_.push_back(reducer);
|
| + reducer->set_observer(this);
|
| }
|
|
|
|
|
| @@ -59,7 +68,14 @@ void GraphReducer::ReduceNode(Node* node) {
|
| }
|
|
|
|
|
| -void GraphReducer::ReduceGraph() { ReduceNode(graph()->end()); }
|
| +void GraphReducer::ReduceGraph() {
|
| + for (;;) {
|
| + ReduceNode(graph()->end());
|
| + if (Finish()) break;
|
| + // Reset all marks on the graph in preparation to re-reduce the graph.
|
| + state_.Reset(graph());
|
| + }
|
| +}
|
|
|
|
|
| Reduction GraphReducer::Reduce(Node* const node) {
|
| @@ -135,38 +151,63 @@ void GraphReducer::ReduceTop() {
|
| // After reducing the node, pop it off the stack.
|
| Pop();
|
|
|
| - // Revisit all uses of the node.
|
| - for (Node* const use : node->uses()) {
|
| + // Check if we have a new replacement.
|
| + if (replacement != node) {
|
| + // Replace the old uses of {node} with {replacement}.
|
| + Replace(node, replacement, node_count);
|
| + } else {
|
| + // Revisit all uses of the node.
|
| + for (Node* const user : node->uses()) {
|
| + // Don't revisit this node if it refers to itself.
|
| + if (user != node) Revisit(user);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void GraphReducer::Replace(Node* node, Node* replacement) {
|
| + if (node == graph()->start()) graph()->SetStart(replacement);
|
| + if (node == graph()->end()) graph()->SetEnd(replacement);
|
| + for (Edge edge : node->use_edges()) {
|
| + Node* const user = edge.from();
|
| + edge.UpdateTo(replacement);
|
| // Don't revisit this node if it refers to itself.
|
| - if (use != node) Revisit(use);
|
| + if (user != node) Revisit(user);
|
| }
|
| + node->Kill();
|
| +}
|
|
|
| - // Check if we have a new replacement.
|
| - if (replacement != node) {
|
| - if (node == graph()->start()) graph()->SetStart(replacement);
|
| - if (node == graph()->end()) graph()->SetEnd(replacement);
|
| - // If {node} was replaced by an old node, unlink {node} and assume that
|
| - // {replacement} was already reduced and finish.
|
| - if (replacement->id() < node_count) {
|
| - node->ReplaceUses(replacement);
|
| - node->Kill();
|
| - } else {
|
| - // Otherwise {node} was replaced by a new node. Replace all old uses of
|
| - // {node} with {replacement}. New nodes created by this reduction can
|
| - // use {node}.
|
| - for (Edge edge : node->use_edges()) {
|
| - if (edge.from()->id() < node_count) {
|
| - edge.UpdateTo(replacement);
|
| - }
|
| - }
|
| - // Unlink {node} if it's no longer used.
|
| - if (node->uses().empty()) {
|
| - node->Kill();
|
| - }
|
|
|
| - // If there was a replacement, reduce it after popping {node}.
|
| - Recurse(replacement);
|
| +void GraphReducer::Replace(Node* node, Node* replacement, NodeId max_id) {
|
| + if (node == graph()->start()) graph()->SetStart(replacement);
|
| + if (node == graph()->end()) graph()->SetEnd(replacement);
|
| + // If {node} was replaced by an old node, unlink {node} and assume that
|
| + // {replacement} was already reduced and finish.
|
| + if (replacement->id() < max_id) {
|
| + for (Edge edge : node->use_edges()) {
|
| + Node* const user = edge.from();
|
| + edge.UpdateTo(replacement);
|
| + // Don't revisit this node if it refers to itself.
|
| + if (user != node) Revisit(user);
|
| }
|
| + node->Kill();
|
| + } else {
|
| + // Otherwise {node} was replaced by a new node. Replace all old uses of
|
| + // {node} with {replacement}. New nodes created by this reduction can
|
| + // use {node}.
|
| + for (Edge edge : node->use_edges()) {
|
| + Node* const user = edge.from();
|
| + if (user->id() < max_id) {
|
| + edge.UpdateTo(replacement);
|
| + // Don't revisit this node if it refers to itself.
|
| + if (user != node) Revisit(user);
|
| + }
|
| + }
|
| + // Unlink {node} if it's no longer used.
|
| + if (node->uses().empty()) node->Kill();
|
| +
|
| + // If there was a replacement, reduce it after popping {node}.
|
| + Recurse(replacement);
|
| }
|
| }
|
|
|
|
|