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 |