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/graph-reducer.h" | 8 #include "src/compiler/graph-reducer.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/node-marker.h" | 10 #include "src/compiler/node-marker.h" |
11 #include "src/compiler/node-matchers.h" | 11 #include "src/compiler/node-matchers.h" |
12 #include "src/compiler/node-properties.h" | 12 #include "src/compiler/node-properties.h" |
13 #include "src/zone-containers.h" | 13 #include "src/zone-containers.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 namespace compiler { | 17 namespace compiler { |
18 | 18 |
19 #define TRACE(...) \ | 19 #define TRACE(...) \ |
20 do { \ | 20 do { \ |
21 if (FLAG_trace_turbo_reduction) PrintF(__VA_ARGS__); \ | 21 if (FLAG_trace_turbo_reduction) PrintF(__VA_ARGS__); \ |
22 } while (false) | 22 } while (false) |
23 | 23 |
24 enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; | |
25 enum Decision { kFalse, kUnknown, kTrue }; | 24 enum Decision { kFalse, kUnknown, kTrue }; |
26 | 25 |
27 class ReachabilityMarker : public NodeMarker<uint8_t> { | |
28 public: | |
29 explicit ReachabilityMarker(Graph* graph) : NodeMarker<uint8_t>(graph, 8) {} | |
30 bool SetReachableFromEnd(Node* node) { | |
31 uint8_t before = Get(node); | |
32 Set(node, before | kFromEnd); | |
33 return before & kFromEnd; | |
34 } | |
35 bool IsReachableFromEnd(Node* node) { return Get(node) & kFromEnd; } | |
36 void Push(Node* node) { Set(node, Get(node) | kFwStack); } | |
37 void Pop(Node* node) { Set(node, Get(node) & ~kFwStack); } | |
38 bool IsOnStack(Node* node) { return Get(node) & kFwStack; } | |
39 | |
40 private: | |
41 enum Bit { kFromEnd = 1, kFwStack = 2 }; | |
42 }; | |
43 | |
44 | |
45 class ControlReducerImpl final : public AdvancedReducer { | 26 class ControlReducerImpl final : public AdvancedReducer { |
46 public: | 27 public: |
47 Zone* zone_; | 28 Zone* zone_; |
48 JSGraph* jsgraph_; | 29 JSGraph* jsgraph_; |
49 int max_phis_for_select_; | 30 int max_phis_for_select_; |
50 | 31 |
51 ControlReducerImpl(Editor* editor, Zone* zone, JSGraph* jsgraph) | 32 ControlReducerImpl(Editor* editor, Zone* zone, JSGraph* jsgraph) |
52 : AdvancedReducer(editor), | 33 : AdvancedReducer(editor), |
53 zone_(zone), | 34 zone_(zone), |
54 jsgraph_(jsgraph), | 35 jsgraph_(jsgraph), |
55 max_phis_for_select_(0) {} | 36 max_phis_for_select_(0) {} |
56 | 37 |
57 Graph* graph() { return jsgraph_->graph(); } | 38 Graph* graph() { return jsgraph_->graph(); } |
58 CommonOperatorBuilder* common() { return jsgraph_->common(); } | 39 CommonOperatorBuilder* common() { return jsgraph_->common(); } |
59 Node* dead() { return jsgraph_->DeadControl(); } | 40 Node* dead() { return jsgraph_->DeadControl(); } |
60 | 41 |
61 // Finish reducing the graph by trimming nodes. | |
62 bool Finish() final { | |
63 // TODO(bmeurer): Move this to the GraphReducer. | |
64 Trim(); | |
65 return true; | |
66 } | |
67 | |
68 void AddNodesReachableFromRoots(ReachabilityMarker& marked, | |
69 NodeVector& nodes) { | |
70 jsgraph_->GetCachedNodes(&nodes); // Consider cached nodes roots. | |
71 Node* end = graph()->end(); | |
72 marked.SetReachableFromEnd(end); | |
73 if (!end->IsDead()) nodes.push_back(end); // Consider end to be a root. | |
74 for (Node* node : nodes) marked.SetReachableFromEnd(node); | |
75 AddBackwardsReachableNodes(marked, nodes, 0); | |
76 } | |
77 | |
78 void AddBackwardsReachableNodes(ReachabilityMarker& marked, NodeVector& nodes, | |
79 size_t cursor) { | |
80 while (cursor < nodes.size()) { | |
81 Node* node = nodes[cursor++]; | |
82 for (Node* const input : node->inputs()) { | |
83 if (!marked.SetReachableFromEnd(input)) { | |
84 nodes.push_back(input); | |
85 } | |
86 } | |
87 } | |
88 } | |
89 | |
90 void Trim() { | |
91 // Gather all nodes backwards-reachable from end through inputs. | |
92 ReachabilityMarker marked(graph()); | |
93 NodeVector nodes(zone_); | |
94 jsgraph_->GetCachedNodes(&nodes); | |
95 AddNodesReachableFromRoots(marked, nodes); | |
96 TrimNodes(marked, nodes); | |
97 } | |
98 | |
99 void TrimNodes(ReachabilityMarker& marked, NodeVector& nodes) { | |
100 // Remove dead->live edges. | |
101 for (size_t j = 0; j < nodes.size(); j++) { | |
102 Node* node = nodes[j]; | |
103 for (Edge edge : node->use_edges()) { | |
104 Node* use = edge.from(); | |
105 if (!marked.IsReachableFromEnd(use)) { | |
106 TRACE("DeadLink: #%d:%s(%d) -> #%d:%s\n", use->id(), | |
107 use->op()->mnemonic(), edge.index(), node->id(), | |
108 node->op()->mnemonic()); | |
109 edge.UpdateTo(NULL); | |
110 } | |
111 } | |
112 } | |
113 #if DEBUG | |
114 // Verify that no inputs to live nodes are NULL. | |
115 for (Node* node : nodes) { | |
116 for (int index = 0; index < node->InputCount(); index++) { | |
117 Node* input = node->InputAt(index); | |
118 if (input == nullptr) { | |
119 std::ostringstream str; | |
120 str << "GraphError: node #" << node->id() << ":" << *node->op() | |
121 << "(input @" << index << ") == null"; | |
122 FATAL(str.str().c_str()); | |
123 } | |
124 if (input->opcode() == IrOpcode::kDead) { | |
125 std::ostringstream str; | |
126 str << "GraphError: node #" << node->id() << ":" << *node->op() | |
127 << "(input @" << index << ") == dead"; | |
128 FATAL(str.str().c_str()); | |
129 } | |
130 } | |
131 for (Node* use : node->uses()) { | |
132 CHECK(marked.IsReachableFromEnd(use)); | |
133 } | |
134 } | |
135 #endif | |
136 } | |
137 | |
138 //=========================================================================== | 42 //=========================================================================== |
139 // Reducer implementation: perform reductions on a node. | 43 // Reducer implementation: perform reductions on a node. |
140 //=========================================================================== | 44 //=========================================================================== |
141 Reduction Reduce(Node* node) override { | 45 Reduction Reduce(Node* node) override { |
142 if (node->op()->ControlInputCount() == 1 || | 46 if (node->op()->ControlInputCount() == 1 || |
143 node->opcode() == IrOpcode::kLoop) { | 47 node->opcode() == IrOpcode::kLoop) { |
144 // If a node has only one control input and it is dead, replace with dead. | 48 // If a node has only one control input and it is dead, replace with dead. |
145 Node* control = NodeProperties::GetControlInput(node); | 49 Node* control = NodeProperties::GetControlInput(node); |
146 if (control->opcode() == IrOpcode::kDead) { | 50 if (control->opcode() == IrOpcode::kDead) { |
147 TRACE("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic()); | 51 TRACE("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic()); |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 node->ReplaceUses(replacement); | 340 node->ReplaceUses(replacement); |
437 } | 341 } |
438 void Revisit(Node* node) final {} | 342 void Revisit(Node* node) final {} |
439 void ReplaceWithValue(Node* node, Node* value, Node* effect, | 343 void ReplaceWithValue(Node* node, Node* value, Node* effect, |
440 Node* control) final {} | 344 Node* control) final {} |
441 }; | 345 }; |
442 | 346 |
443 } // namespace | 347 } // namespace |
444 | 348 |
445 | 349 |
446 void ControlReducer::TrimGraph(Zone* zone, JSGraph* jsgraph) { | |
447 DummyEditor editor; | |
448 ControlReducerImpl impl(&editor, zone, jsgraph); | |
449 impl.Trim(); | |
450 } | |
451 | |
452 | |
453 Node* ControlReducer::ReduceMerge(JSGraph* jsgraph, Node* node, | 350 Node* ControlReducer::ReduceMerge(JSGraph* jsgraph, Node* node, |
454 int max_phis_for_select) { | 351 int max_phis_for_select) { |
455 Zone zone; | 352 Zone zone; |
456 DummyEditor editor; | 353 DummyEditor editor; |
457 ControlReducerImpl impl(&editor, &zone, jsgraph); | 354 ControlReducerImpl impl(&editor, &zone, jsgraph); |
458 impl.max_phis_for_select_ = max_phis_for_select; | 355 impl.max_phis_for_select_ = max_phis_for_select; |
459 return impl.ReduceMerge(node); | 356 return impl.ReduceMerge(node); |
460 } | 357 } |
461 | 358 |
462 | 359 |
(...skipping 15 matching lines...) Expand all Loading... |
478 case IrOpcode::kIfFalse: | 375 case IrOpcode::kIfFalse: |
479 return impl.ReduceIfProjection(node, kFalse); | 376 return impl.ReduceIfProjection(node, kFalse); |
480 default: | 377 default: |
481 return node; | 378 return node; |
482 } | 379 } |
483 } | 380 } |
484 | 381 |
485 } // namespace compiler | 382 } // namespace compiler |
486 } // namespace internal | 383 } // namespace internal |
487 } // namespace v8 | 384 } // namespace v8 |
OLD | NEW |