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