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