| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/common-operator.h" | 5 #include "src/compiler/common-operator.h" |
| 6 #include "src/compiler/control-reducer.h" | 6 #include "src/compiler/control-reducer.h" |
| 7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/node-marker.h" | 9 #include "src/compiler/node-marker.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 | 93 |
| 94 // Repair the graph after the possible creation of non-terminating or dead | 94 // Repair the graph after the possible creation of non-terminating or dead |
| 95 // loops. Removing dead loops can produce more opportunities for reduction. | 95 // loops. Removing dead loops can produce more opportunities for reduction. |
| 96 bool RepairAndRemoveLoops() { | 96 bool RepairAndRemoveLoops() { |
| 97 // TODO(turbofan): we can skip this if the graph has no loops, but | 97 // TODO(turbofan): we can skip this if the graph has no loops, but |
| 98 // we have to be careful about proper loop detection during reduction. | 98 // we have to be careful about proper loop detection during reduction. |
| 99 | 99 |
| 100 // Gather all nodes backwards-reachable from end (through inputs). | 100 // Gather all nodes backwards-reachable from end (through inputs). |
| 101 ReachabilityMarker marked(graph()); | 101 ReachabilityMarker marked(graph()); |
| 102 NodeVector nodes(zone_); | 102 NodeVector nodes(zone_); |
| 103 AddNodesReachableFromEnd(marked, nodes); | 103 AddNodesReachableFromRoots(marked, nodes); |
| 104 | 104 |
| 105 // Walk forward through control nodes, looking for back edges to nodes | 105 // Walk forward through control nodes, looking for back edges to nodes |
| 106 // that are not connected to end. Those are non-terminating loops (NTLs). | 106 // that are not connected to end. Those are non-terminating loops (NTLs). |
| 107 Node* start = graph()->start(); | 107 Node* start = graph()->start(); |
| 108 marked.Push(start); | 108 marked.Push(start); |
| 109 marked.SetReachableFromStart(start); | 109 marked.SetReachableFromStart(start); |
| 110 | 110 |
| 111 // We use a stack of (Node, Node::UseEdges::iterator) pairs to avoid | 111 // We use a stack of (Node, Node::UseEdges::iterator) pairs to avoid |
| 112 // O(n^2) traversal. | 112 // O(n^2) traversal. |
| 113 typedef std::pair<Node*, Node::UseEdges::iterator> FwIter; | 113 typedef std::pair<Node*, Node::UseEdges::iterator> FwIter; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 } | 151 } |
| 152 ++fw_stack.back().second; | 152 ++fw_stack.back().second; |
| 153 } | 153 } |
| 154 if (pop) { | 154 if (pop) { |
| 155 marked.Pop(node); | 155 marked.Pop(node); |
| 156 fw_stack.pop_back(); | 156 fw_stack.pop_back(); |
| 157 } | 157 } |
| 158 } | 158 } |
| 159 | 159 |
| 160 // Trim references from dead nodes to live nodes first. | 160 // Trim references from dead nodes to live nodes first. |
| 161 jsgraph_->GetCachedNodes(&nodes); | |
| 162 TrimNodes(marked, nodes); | 161 TrimNodes(marked, nodes); |
| 163 | 162 |
| 164 // Any control nodes not reachable from start are dead, even loops. | 163 // Any control nodes not reachable from start are dead, even loops. |
| 165 for (size_t i = 0; i < nodes.size(); i++) { | 164 for (size_t i = 0; i < nodes.size(); i++) { |
| 166 Node* node = nodes[i]; | 165 Node* node = nodes[i]; |
| 167 if (node->op()->ControlOutputCount() > 0 && | 166 if (node->op()->ControlOutputCount() > 0 && |
| 168 !marked.IsReachableFromStart(node)) { | 167 !marked.IsReachableFromStart(node)) { |
| 169 ReplaceNode(node, dead()); // uses will be added to revisit queue. | 168 ReplaceNode(node, dead()); // uses will be added to revisit queue. |
| 170 } | 169 } |
| 171 } | 170 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 // Mark the node as visited so that we can revisit later. | 243 // Mark the node as visited so that we can revisit later. |
| 245 MarkAsVisited(merge); | 244 MarkAsVisited(merge); |
| 246 } else { | 245 } else { |
| 247 // Append a new input to the final merge at the end. | 246 // Append a new input to the final merge at the end. |
| 248 merge->AppendInput(graph()->zone(), ret); | 247 merge->AppendInput(graph()->zone(), ret); |
| 249 merge->set_op(common_->Merge(merge->InputCount())); | 248 merge->set_op(common_->Merge(merge->InputCount())); |
| 250 } | 249 } |
| 251 return ret; | 250 return ret; |
| 252 } | 251 } |
| 253 | 252 |
| 254 void AddNodesReachableFromEnd(ReachabilityMarker& marked, NodeVector& nodes) { | 253 void AddNodesReachableFromRoots(ReachabilityMarker& marked, |
| 254 NodeVector& nodes) { |
| 255 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots. |
| 255 Node* end = graph()->end(); | 256 Node* end = graph()->end(); |
| 256 marked.SetReachableFromEnd(end); | 257 marked.SetReachableFromEnd(end); |
| 257 if (!end->IsDead()) { | 258 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root. |
| 258 nodes.push_back(end); | 259 for (Node* node : nodes) marked.SetReachableFromEnd(node); |
| 259 AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); | 260 AddBackwardsReachableNodes(marked, nodes, 0); |
| 260 } | |
| 261 } | 261 } |
| 262 | 262 |
| 263 void AddBackwardsReachableNodes(ReachabilityMarker& marked, NodeVector& nodes, | 263 void AddBackwardsReachableNodes(ReachabilityMarker& marked, NodeVector& nodes, |
| 264 size_t cursor) { | 264 size_t cursor) { |
| 265 while (cursor < nodes.size()) { | 265 while (cursor < nodes.size()) { |
| 266 Node* node = nodes[cursor++]; | 266 Node* node = nodes[cursor++]; |
| 267 for (Node* const input : node->inputs()) { | 267 for (Node* const input : node->inputs()) { |
| 268 if (!marked.SetReachableFromEnd(input)) { | 268 if (!marked.SetReachableFromEnd(input)) { |
| 269 nodes.push_back(input); | 269 nodes.push_back(input); |
| 270 } | 270 } |
| 271 } | 271 } |
| 272 } | 272 } |
| 273 } | 273 } |
| 274 | 274 |
| 275 void Trim() { | 275 void Trim() { |
| 276 // Gather all nodes backwards-reachable from end through inputs. | 276 // Gather all nodes backwards-reachable from end through inputs. |
| 277 ReachabilityMarker marked(graph()); | 277 ReachabilityMarker marked(graph()); |
| 278 NodeVector nodes(zone_); | 278 NodeVector nodes(zone_); |
| 279 AddNodesReachableFromEnd(marked, nodes); | |
| 280 | |
| 281 // Process cached nodes in the JSGraph too. | |
| 282 jsgraph_->GetCachedNodes(&nodes); | 279 jsgraph_->GetCachedNodes(&nodes); |
| 280 AddNodesReachableFromRoots(marked, nodes); |
| 283 TrimNodes(marked, nodes); | 281 TrimNodes(marked, nodes); |
| 284 } | 282 } |
| 285 | 283 |
| 286 void TrimNodes(ReachabilityMarker& marked, NodeVector& nodes) { | 284 void TrimNodes(ReachabilityMarker& marked, NodeVector& nodes) { |
| 287 // Remove dead->live edges. | 285 // Remove dead->live edges. |
| 288 for (size_t j = 0; j < nodes.size(); j++) { | 286 for (size_t j = 0; j < nodes.size(); j++) { |
| 289 Node* node = nodes[j]; | 287 Node* node = nodes[j]; |
| 290 for (Edge edge : node->use_edges()) { | 288 for (Edge edge : node->use_edges()) { |
| 291 Node* use = edge.from(); | 289 Node* use = edge.from(); |
| 292 if (!marked.IsReachableFromEnd(use)) { | 290 if (!marked.IsReachableFromEnd(use)) { |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 return impl.ReduceIfProjection(node, kTrue); | 705 return impl.ReduceIfProjection(node, kTrue); |
| 708 case IrOpcode::kIfFalse: | 706 case IrOpcode::kIfFalse: |
| 709 return impl.ReduceIfProjection(node, kFalse); | 707 return impl.ReduceIfProjection(node, kFalse); |
| 710 default: | 708 default: |
| 711 return node; | 709 return node; |
| 712 } | 710 } |
| 713 } | 711 } |
| 714 } | 712 } |
| 715 } | 713 } |
| 716 } // namespace v8::internal::compiler | 714 } // namespace v8::internal::compiler |
| OLD | NEW |