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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); | 78 DCHECK_EQ(IrOpcode::kBranch, node->opcode()); |
79 Node* const cond = node->InputAt(0); | 79 Node* const cond = node->InputAt(0); |
80 // Swap IfTrue/IfFalse on {branch} if {cond} is a BooleanNot and use the input | 80 // Swap IfTrue/IfFalse on {branch} if {cond} is a BooleanNot and use the input |
81 // to BooleanNot as new condition for {branch}. Note we assume that {cond} was | 81 // to BooleanNot as new condition for {branch}. Note we assume that {cond} was |
82 // already properly optimized before we get here (as guaranteed by the graph | 82 // already properly optimized before we get here (as guaranteed by the graph |
83 // reduction logic). | 83 // reduction logic). |
84 if (cond->opcode() == IrOpcode::kBooleanNot) { | 84 if (cond->opcode() == IrOpcode::kBooleanNot) { |
85 for (Node* const use : node->uses()) { | 85 for (Node* const use : node->uses()) { |
86 switch (use->opcode()) { | 86 switch (use->opcode()) { |
87 case IrOpcode::kIfTrue: | 87 case IrOpcode::kIfTrue: |
88 use->set_op(common()->IfFalse()); | 88 NodeProperties::ChangeOp(use, common()->IfFalse()); |
89 break; | 89 break; |
90 case IrOpcode::kIfFalse: | 90 case IrOpcode::kIfFalse: |
91 use->set_op(common()->IfTrue()); | 91 NodeProperties::ChangeOp(use, common()->IfTrue()); |
92 break; | 92 break; |
93 default: | 93 default: |
94 UNREACHABLE(); | 94 UNREACHABLE(); |
95 } | 95 } |
96 } | 96 } |
97 // 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, |
98 // 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 |
99 // graph reduction logic will ensure that the uses are revisited properly. | 99 // graph reduction logic will ensure that the uses are revisited properly. |
100 node->ReplaceInput(0, cond->InputAt(0)); | 100 node->ReplaceInput(0, cond->InputAt(0)); |
101 // Negate the hint for {branch}. | 101 // Negate the hint for {branch}. |
102 node->set_op(common()->Branch(NegateBranchHint(BranchHintOf(node->op())))); | 102 NodeProperties::ChangeOp( |
| 103 node, common()->Branch(NegateBranchHint(BranchHintOf(node->op())))); |
103 return Changed(node); | 104 return Changed(node); |
104 } | 105 } |
105 Decision const decision = DecideCondition(cond); | 106 Decision const decision = DecideCondition(cond); |
106 if (decision == Decision::kUnknown) return NoChange(); | 107 if (decision == Decision::kUnknown) return NoChange(); |
107 Node* const control = node->InputAt(1); | 108 Node* const control = node->InputAt(1); |
108 for (Node* const use : node->uses()) { | 109 for (Node* const use : node->uses()) { |
109 switch (use->opcode()) { | 110 switch (use->opcode()) { |
110 case IrOpcode::kIfTrue: | 111 case IrOpcode::kIfTrue: |
111 Replace(use, (decision == Decision::kTrue) ? control : dead()); | 112 Replace(use, (decision == Decision::kTrue) ? control : dead()); |
112 break; | 113 break; |
(...skipping 28 matching lines...) Expand all Loading... |
141 if (if_true->opcode() != IrOpcode::kIfTrue) std::swap(if_true, if_false); | 142 if (if_true->opcode() != IrOpcode::kIfTrue) std::swap(if_true, if_false); |
142 if (if_true->opcode() == IrOpcode::kIfTrue && | 143 if (if_true->opcode() == IrOpcode::kIfTrue && |
143 if_false->opcode() == IrOpcode::kIfFalse && | 144 if_false->opcode() == IrOpcode::kIfFalse && |
144 if_true->InputAt(0) == if_false->InputAt(0) && if_true->OwnedBy(node) && | 145 if_true->InputAt(0) == if_false->InputAt(0) && if_true->OwnedBy(node) && |
145 if_false->OwnedBy(node)) { | 146 if_false->OwnedBy(node)) { |
146 Node* const branch = if_true->InputAt(0); | 147 Node* const branch = if_true->InputAt(0); |
147 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); | 148 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); |
148 DCHECK(branch->OwnedBy(if_true, if_false)); | 149 DCHECK(branch->OwnedBy(if_true, if_false)); |
149 Node* const control = branch->InputAt(1); | 150 Node* const control = branch->InputAt(1); |
150 // Mark the {branch} as {Dead}. | 151 // Mark the {branch} as {Dead}. |
151 branch->set_op(common()->Dead()); | |
152 branch->TrimInputCount(0); | 152 branch->TrimInputCount(0); |
| 153 NodeProperties::ChangeOp(branch, common()->Dead()); |
153 return Replace(control); | 154 return Replace(control); |
154 } | 155 } |
155 } | 156 } |
156 return NoChange(); | 157 return NoChange(); |
157 } | 158 } |
158 | 159 |
159 | 160 |
160 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { | 161 Reduction CommonOperatorReducer::ReduceEffectPhi(Node* node) { |
161 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); | 162 DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode()); |
162 int const input_count = node->InputCount() - 1; | 163 int const input_count = node->InputCount() - 1; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 Node* const control = node->InputAt(2); | 274 Node* const control = node->InputAt(2); |
274 if (value->opcode() == IrOpcode::kPhi && | 275 if (value->opcode() == IrOpcode::kPhi && |
275 NodeProperties::GetControlInput(value) == control && | 276 NodeProperties::GetControlInput(value) == control && |
276 effect->opcode() == IrOpcode::kEffectPhi && | 277 effect->opcode() == IrOpcode::kEffectPhi && |
277 NodeProperties::GetControlInput(effect) == control && | 278 NodeProperties::GetControlInput(effect) == control && |
278 control->opcode() == IrOpcode::kMerge) { | 279 control->opcode() == IrOpcode::kMerge) { |
279 int const control_input_count = control->InputCount(); | 280 int const control_input_count = control->InputCount(); |
280 DCHECK_NE(0, control_input_count); | 281 DCHECK_NE(0, control_input_count); |
281 DCHECK_EQ(control_input_count, value->InputCount() - 1); | 282 DCHECK_EQ(control_input_count, value->InputCount() - 1); |
282 DCHECK_EQ(control_input_count, effect->InputCount() - 1); | 283 DCHECK_EQ(control_input_count, effect->InputCount() - 1); |
283 Node* const end = graph()->end(); | 284 DCHECK_EQ(IrOpcode::kEnd, graph()->end()->opcode()); |
284 DCHECK_EQ(IrOpcode::kEnd, end->opcode()); | 285 DCHECK_NE(0, graph()->end()->InputCount()); |
285 DCHECK_NE(0, end->InputCount()); | |
286 for (int i = 0; i < control_input_count; ++i) { | 286 for (int i = 0; i < control_input_count; ++i) { |
287 // Create a new {Return} and connect it to {end}. We don't need to mark | 287 // Create a new {Return} and connect it to {end}. We don't need to mark |
288 // {end} as revisit, because we mark {node} as {Dead} below, which was | 288 // {end} as revisit, because we mark {node} as {Dead} below, which was |
289 // previously connected to {end}, so we know for sure that at some point | 289 // previously connected to {end}, so we know for sure that at some point |
290 // the reducer logic will visit {end} again. | 290 // the reducer logic will visit {end} again. |
291 Node* ret = graph()->NewNode(common()->Return(), value->InputAt(i), | 291 Node* ret = graph()->NewNode(common()->Return(), value->InputAt(i), |
292 effect->InputAt(i), control->InputAt(i)); | 292 effect->InputAt(i), control->InputAt(i)); |
293 end->set_op(common()->End(end->InputCount() + 1)); | 293 NodeProperties::MergeControlToEnd(graph(), common(), ret); |
294 end->AppendInput(graph()->zone(), ret); | |
295 } | 294 } |
296 // Mark the merge {control} and return {node} as {dead}. | 295 // Mark the merge {control} and return {node} as {dead}. |
297 Replace(control, dead()); | 296 Replace(control, dead()); |
298 return Replace(dead()); | 297 return Replace(dead()); |
299 } | 298 } |
300 return NoChange(); | 299 return NoChange(); |
301 } | 300 } |
302 | 301 |
303 | 302 |
304 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { | 303 Reduction CommonOperatorReducer::ReduceSelect(Node* node) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 } | 353 } |
355 default: | 354 default: |
356 break; | 355 break; |
357 } | 356 } |
358 return NoChange(); | 357 return NoChange(); |
359 } | 358 } |
360 | 359 |
361 | 360 |
362 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, | 361 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, |
363 Node* a) { | 362 Node* a) { |
364 node->set_op(op); | |
365 node->ReplaceInput(0, a); | 363 node->ReplaceInput(0, a); |
366 node->TrimInputCount(1); | 364 node->TrimInputCount(1); |
| 365 NodeProperties::ChangeOp(node, op); |
367 return Changed(node); | 366 return Changed(node); |
368 } | 367 } |
369 | 368 |
370 | 369 |
371 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, Node* a, | 370 Reduction CommonOperatorReducer::Change(Node* node, Operator const* op, Node* a, |
372 Node* b) { | 371 Node* b) { |
373 node->set_op(op); | |
374 node->ReplaceInput(0, a); | 372 node->ReplaceInput(0, a); |
375 node->ReplaceInput(1, b); | 373 node->ReplaceInput(1, b); |
376 node->TrimInputCount(2); | 374 node->TrimInputCount(2); |
| 375 NodeProperties::ChangeOp(node, op); |
377 return Changed(node); | 376 return Changed(node); |
378 } | 377 } |
379 | 378 |
380 } // namespace compiler | 379 } // namespace compiler |
381 } // namespace internal | 380 } // namespace internal |
382 } // namespace v8 | 381 } // namespace v8 |
OLD | NEW |