| 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 |