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-reducer.h" | 5 #include "src/compiler/common-operator-reducer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "src/compiler/common-operator.h" | 9 #include "src/compiler/common-operator.h" |
10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
11 #include "src/compiler/machine-operator.h" | 11 #include "src/compiler/machine-operator.h" |
12 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
13 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
| 14 #include "src/compiler/node-properties.h" |
14 | 15 |
15 namespace v8 { | 16 namespace v8 { |
16 namespace internal { | 17 namespace internal { |
17 namespace compiler { | 18 namespace compiler { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 enum class Decision { kUnknown, kTrue, kFalse }; | 22 enum class Decision { kUnknown, kTrue, kFalse }; |
22 | 23 |
23 Decision DecideCondition(Node* const cond) { | 24 Decision DecideCondition(Node* const cond) { |
(...skipping 12 matching lines...) Expand all Loading... |
36 : Decision::kFalse; | 37 : Decision::kFalse; |
37 } | 38 } |
38 default: | 39 default: |
39 return Decision::kUnknown; | 40 return Decision::kUnknown; |
40 } | 41 } |
41 } | 42 } |
42 | 43 |
43 } // namespace | 44 } // namespace |
44 | 45 |
45 | 46 |
| 47 CommonOperatorReducer::CommonOperatorReducer(Editor* editor, Graph* graph, |
| 48 CommonOperatorBuilder* common, |
| 49 MachineOperatorBuilder* machine) |
| 50 : AdvancedReducer(editor), |
| 51 graph_(graph), |
| 52 common_(common), |
| 53 machine_(machine), |
| 54 dead_(graph->NewNode(common->Dead())) {} |
| 55 |
| 56 |
46 Reduction CommonOperatorReducer::Reduce(Node* node) { | 57 Reduction CommonOperatorReducer::Reduce(Node* node) { |
47 switch (node->opcode()) { | 58 switch (node->opcode()) { |
48 case IrOpcode::kBranch: | 59 case IrOpcode::kBranch: |
49 return ReduceBranch(node); | 60 return ReduceBranch(node); |
50 case IrOpcode::kMerge: | 61 case IrOpcode::kMerge: |
51 return ReduceMerge(node); | 62 return ReduceMerge(node); |
52 case IrOpcode::kEffectPhi: | 63 case IrOpcode::kEffectPhi: |
53 return ReduceEffectPhi(node); | 64 return ReduceEffectPhi(node); |
54 case IrOpcode::kPhi: | 65 case IrOpcode::kPhi: |
55 return ReducePhi(node); | 66 return ReducePhi(node); |
| 67 case IrOpcode::kReturn: |
| 68 return ReduceReturn(node); |
56 case IrOpcode::kSelect: | 69 case IrOpcode::kSelect: |
57 return ReduceSelect(node); | 70 return ReduceSelect(node); |
58 default: | 71 default: |
59 break; | 72 break; |
60 } | 73 } |
61 return NoChange(); | 74 return NoChange(); |
62 } | 75 } |
63 | 76 |
64 | 77 |
65 Reduction CommonOperatorReducer::ReduceBranch(Node* node) { | 78 Reduction CommonOperatorReducer::ReduceBranch(Node* node) { |
(...skipping 18 matching lines...) Expand all Loading... |
84 } | 97 } |
85 // Update the condition of {branch}. No need to mark the uses for revisit, | 98 // Update the condition of {branch}. No need to mark the uses for revisit, |
86 // since we tell the graph reducer that the {branch} was changed and the | 99 // since we tell the graph reducer that the {branch} was changed and the |
87 // graph reduction logic will ensure that the uses are revisited properly. | 100 // graph reduction logic will ensure that the uses are revisited properly. |
88 node->ReplaceInput(0, cond->InputAt(0)); | 101 node->ReplaceInput(0, cond->InputAt(0)); |
89 return Changed(node); | 102 return Changed(node); |
90 } | 103 } |
91 Decision const decision = DecideCondition(cond); | 104 Decision const decision = DecideCondition(cond); |
92 if (decision == Decision::kUnknown) return NoChange(); | 105 if (decision == Decision::kUnknown) return NoChange(); |
93 Node* const control = node->InputAt(1); | 106 Node* const control = node->InputAt(1); |
94 if (!dead_.is_set()) dead_.set(graph()->NewNode(common()->Dead())); | |
95 for (Node* const use : node->uses()) { | 107 for (Node* const use : node->uses()) { |
96 switch (use->opcode()) { | 108 switch (use->opcode()) { |
97 case IrOpcode::kIfTrue: | 109 case IrOpcode::kIfTrue: |
98 Replace(use, (decision == Decision::kTrue) ? control : dead_.get()); | 110 Replace(use, (decision == Decision::kTrue) ? control : dead()); |
99 break; | 111 break; |
100 case IrOpcode::kIfFalse: | 112 case IrOpcode::kIfFalse: |
101 Replace(use, (decision == Decision::kFalse) ? control : dead_.get()); | 113 Replace(use, (decision == Decision::kFalse) ? control : dead()); |
102 break; | 114 break; |
103 default: | 115 default: |
104 UNREACHABLE(); | 116 UNREACHABLE(); |
105 } | 117 } |
106 } | 118 } |
107 return Replace(dead_.get()); | 119 return Replace(dead()); |
108 } | 120 } |
109 | 121 |
110 | 122 |
111 Reduction CommonOperatorReducer::ReduceMerge(Node* node) { | 123 Reduction CommonOperatorReducer::ReduceMerge(Node* node) { |
112 DCHECK_EQ(IrOpcode::kMerge, node->opcode()); | 124 DCHECK_EQ(IrOpcode::kMerge, node->opcode()); |
113 // | 125 // |
114 // Check if this is a merge that belongs to an unused diamond, which means | 126 // Check if this is a merge that belongs to an unused diamond, which means |
115 // that: | 127 // that: |
116 // | 128 // |
117 // a) the {Merge} has no {Phi} or {EffectPhi} uses, and | 129 // a) the {Merge} has no {Phi} or {EffectPhi} uses, and |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 continue; | 258 continue; |
247 } | 259 } |
248 if (input != value) return NoChange(); | 260 if (input != value) return NoChange(); |
249 } | 261 } |
250 // We might now be able to further reduce the {merge} node. | 262 // We might now be able to further reduce the {merge} node. |
251 Revisit(merge); | 263 Revisit(merge); |
252 return Replace(value); | 264 return Replace(value); |
253 } | 265 } |
254 | 266 |
255 | 267 |
| 268 Reduction CommonOperatorReducer::ReduceReturn(Node* node) { |
| 269 DCHECK_EQ(IrOpcode::kReturn, node->opcode()); |
| 270 Node* const value = node->InputAt(0); |
| 271 Node* const effect = node->InputAt(1); |
| 272 Node* const control = node->InputAt(2); |
| 273 if (value->opcode() == IrOpcode::kPhi && |
| 274 NodeProperties::GetControlInput(value) == control && |
| 275 effect->opcode() == IrOpcode::kEffectPhi && |
| 276 NodeProperties::GetControlInput(effect) == control && |
| 277 control->opcode() == IrOpcode::kMerge) { |
| 278 int const control_input_count = control->InputCount(); |
| 279 DCHECK_NE(0, control_input_count); |
| 280 DCHECK_EQ(control_input_count, value->InputCount() - 1); |
| 281 DCHECK_EQ(control_input_count, effect->InputCount() - 1); |
| 282 Node* const end = graph()->end(); |
| 283 DCHECK_EQ(IrOpcode::kEnd, end->opcode()); |
| 284 DCHECK_NE(0, end->InputCount()); |
| 285 for (int i = 0; i < control_input_count; ++i) { |
| 286 // Create a new {Return} and connect it to {end}. We don't need to mark |
| 287 // {end} as revisit, because we mark {node} as {Dead} below, which was |
| 288 // previously connected to {end}, so we know for sure that at some point |
| 289 // the reducer logic will visit {end} again. |
| 290 Node* ret = graph()->NewNode(common()->Return(), value->InputAt(i), |
| 291 effect->InputAt(i), control->InputAt(i)); |
| 292 end->set_op(common()->End(end->InputCount() + 1)); |
| 293 end->AppendInput(graph()->zone(), ret); |
| 294 } |
| 295 // Mark the merge {control} and return {node} as {dead}. |
| 296 Replace(control, dead()); |
| 297 return Replace(dead()); |
| 298 } |
| 299 return NoChange(); |
| 300 } |
| 301 |
| 302 |
256 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { | 303 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { |
257 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); | 304 DCHECK_EQ(IrOpcode::kSelect, node->opcode()); |
258 Node* const cond = node->InputAt(0); | 305 Node* const cond = node->InputAt(0); |
259 Node* const vtrue = node->InputAt(1); | 306 Node* const vtrue = node->InputAt(1); |
260 Node* const vfalse = node->InputAt(2); | 307 Node* const vfalse = node->InputAt(2); |
261 if (vtrue == vfalse) return Replace(vtrue); | 308 if (vtrue == vfalse) return Replace(vtrue); |
262 switch (DecideCondition(cond)) { | 309 switch (DecideCondition(cond)) { |
263 case Decision::kTrue: | 310 case Decision::kTrue: |
264 return Replace(vtrue); | 311 return Replace(vtrue); |
265 case Decision::kFalse: | 312 case Decision::kFalse: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 node->set_op(op); | 372 node->set_op(op); |
326 node->ReplaceInput(0, a); | 373 node->ReplaceInput(0, a); |
327 node->ReplaceInput(1, b); | 374 node->ReplaceInput(1, b); |
328 node->TrimInputCount(2); | 375 node->TrimInputCount(2); |
329 return Changed(node); | 376 return Changed(node); |
330 } | 377 } |
331 | 378 |
332 } // namespace compiler | 379 } // namespace compiler |
333 } // namespace internal | 380 } // namespace internal |
334 } // namespace v8 | 381 } // namespace v8 |
OLD | NEW |