| 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.h" | 5 #include "src/compiler/common-operator.h" |
| 6 #include "src/compiler/control-reducer.h" | 6 #include "src/compiler/control-reducer.h" |
| 7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/compiler/node-marker.h" | 9 #include "src/compiler/node-marker.h" |
| 10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 // If a node has only one control input and it is dead, replace with dead. | 350 // If a node has only one control input and it is dead, replace with dead. |
| 351 Node* control = NodeProperties::GetControlInput(node); | 351 Node* control = NodeProperties::GetControlInput(node); |
| 352 if (control->opcode() == IrOpcode::kDead) { | 352 if (control->opcode() == IrOpcode::kDead) { |
| 353 TRACE(("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic())); | 353 TRACE(("ControlDead: #%d:%s\n", node->id(), node->op()->mnemonic())); |
| 354 return control; | 354 return control; |
| 355 } | 355 } |
| 356 } | 356 } |
| 357 | 357 |
| 358 // Reduce branches, phis, and merges. | 358 // Reduce branches, phis, and merges. |
| 359 switch (node->opcode()) { | 359 switch (node->opcode()) { |
| 360 case IrOpcode::kBranch: | 360 case IrOpcode::kIfTrue: |
| 361 return ReduceBranch(node); | 361 return ReduceIfTrue(node); |
| 362 case IrOpcode::kIfFalse: |
| 363 return ReduceIfFalse(node); |
| 362 case IrOpcode::kLoop: | 364 case IrOpcode::kLoop: |
| 363 case IrOpcode::kMerge: | 365 case IrOpcode::kMerge: |
| 364 return ReduceMerge(node); | 366 return ReduceMerge(node); |
| 365 case IrOpcode::kSelect: | 367 case IrOpcode::kSelect: |
| 366 return ReduceSelect(node); | 368 return ReduceSelect(node); |
| 367 case IrOpcode::kPhi: | 369 case IrOpcode::kPhi: |
| 368 case IrOpcode::kEffectPhi: | 370 case IrOpcode::kEffectPhi: |
| 369 return ReducePhi(node); | 371 return ReducePhi(node); |
| 370 default: | 372 default: |
| 371 return node; | 373 return node; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 phi->op()->mnemonic(), live)); | 475 phi->op()->mnemonic(), live)); |
| 474 RemoveDeadInputs(node, phi); | 476 RemoveDeadInputs(node, phi); |
| 475 Revisit(phi); | 477 Revisit(phi); |
| 476 } | 478 } |
| 477 // Edit the merge in place, removing dead inputs. | 479 // Edit the merge in place, removing dead inputs. |
| 478 RemoveDeadInputs(node, node); | 480 RemoveDeadInputs(node, node); |
| 479 return node; | 481 return node; |
| 480 } | 482 } |
| 481 | 483 |
| 482 // Reduce branches if they have constant inputs. | 484 // Reduce branches if they have constant inputs. |
| 483 Node* ReduceBranch(Node* node) { | 485 Node* ReduceIfTrue(Node* node) { |
| 484 Decision result = DecideCondition(node->InputAt(0)); | 486 Node* branch = node->InputAt(0); |
| 485 if (result == kUnknown) return node; | 487 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); |
| 488 Decision result = DecideCondition(branch->InputAt(0)); |
| 489 if (result == kTrue) { |
| 490 // fold a true branch by replacing IfTrue with the branch control. |
| 491 TRACE(("BranchReduce: #%d:%s => #%d:%s\n", branch->id(), |
| 492 branch->op()->mnemonic(), node->id(), node->op()->mnemonic())); |
| 493 return branch->InputAt(1); |
| 494 } |
| 495 return result == kUnknown ? node : dead(); |
| 496 } |
| 486 | 497 |
| 487 TRACE(("BranchReduce: #%d:%s = %s\n", node->id(), node->op()->mnemonic(), | 498 // Reduce branches if they have constant inputs. |
| 488 (result == kTrue) ? "true" : "false")); | 499 Node* ReduceIfFalse(Node* node) { |
| 489 | 500 Node* branch = node->InputAt(0); |
| 490 // Replace IfTrue and IfFalse projections from this branch. | 501 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); |
| 491 Node* control = NodeProperties::GetControlInput(node); | 502 Decision result = DecideCondition(branch->InputAt(0)); |
| 492 for (Edge edge : node->use_edges()) { | 503 if (result == kFalse) { |
| 493 Node* use = edge.from(); | 504 // fold a false branch by replacing IfFalse with the branch control. |
| 494 if (use->opcode() == IrOpcode::kIfTrue) { | 505 TRACE(("BranchReduce: #%d:%s => #%d:%s\n", branch->id(), |
| 495 TRACE((" IfTrue: #%d:%s\n", use->id(), use->op()->mnemonic())); | 506 branch->op()->mnemonic(), node->id(), node->op()->mnemonic())); |
| 496 edge.UpdateTo(NULL); | 507 return branch->InputAt(1); |
| 497 ReplaceNode(use, (result == kTrue) ? control : dead()); | |
| 498 control = NodeProperties::GetControlInput(node); // Could change! | |
| 499 } else if (use->opcode() == IrOpcode::kIfFalse) { | |
| 500 TRACE((" IfFalse: #%d:%s\n", use->id(), use->op()->mnemonic())); | |
| 501 edge.UpdateTo(NULL); | |
| 502 ReplaceNode(use, (result == kTrue) ? dead() : control); | |
| 503 control = NodeProperties::GetControlInput(node); // Could change! | |
| 504 } | |
| 505 } | 508 } |
| 506 return control; | 509 return result == kUnknown ? node : dead(); |
| 507 } | 510 } |
| 508 | 511 |
| 509 // Remove inputs to {node} corresponding to the dead inputs to {merge} | 512 // Remove inputs to {node} corresponding to the dead inputs to {merge} |
| 510 // and compact the remaining inputs, updating the operator. | 513 // and compact the remaining inputs, updating the operator. |
| 511 void RemoveDeadInputs(Node* merge, Node* node) { | 514 void RemoveDeadInputs(Node* merge, Node* node) { |
| 512 int live = 0; | 515 int live = 0; |
| 513 for (int i = 0; i < merge->InputCount(); i++) { | 516 for (int i = 0; i < merge->InputCount(); i++) { |
| 514 // skip dead inputs. | 517 // skip dead inputs. |
| 515 if (merge->InputAt(i)->opcode() == IrOpcode::kDead) continue; | 518 if (merge->InputAt(i)->opcode() == IrOpcode::kDead) continue; |
| 516 // compact live inputs. | 519 // compact live inputs. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 | 574 |
| 572 Node* ControlReducer::ReduceMergeForTesting(JSGraph* jsgraph, | 575 Node* ControlReducer::ReduceMergeForTesting(JSGraph* jsgraph, |
| 573 CommonOperatorBuilder* common, | 576 CommonOperatorBuilder* common, |
| 574 Node* node) { | 577 Node* node) { |
| 575 Zone zone; | 578 Zone zone; |
| 576 ControlReducerImpl impl(&zone, jsgraph, common); | 579 ControlReducerImpl impl(&zone, jsgraph, common); |
| 577 return impl.ReduceMerge(node); | 580 return impl.ReduceMerge(node); |
| 578 } | 581 } |
| 579 | 582 |
| 580 | 583 |
| 581 Node* ControlReducer::ReduceBranchForTesting(JSGraph* jsgraph, | 584 Node* ControlReducer::ReduceIfNodeForTesting(JSGraph* jsgraph, |
| 582 CommonOperatorBuilder* common, | 585 CommonOperatorBuilder* common, |
| 583 Node* node) { | 586 Node* node) { |
| 584 Zone zone; | 587 Zone zone; |
| 585 ControlReducerImpl impl(&zone, jsgraph, common); | 588 ControlReducerImpl impl(&zone, jsgraph, common); |
| 586 return impl.ReduceBranch(node); | 589 switch (node->opcode()) { |
| 590 case IrOpcode::kIfTrue: |
| 591 return impl.ReduceIfTrue(node); |
| 592 case IrOpcode::kIfFalse: |
| 593 return impl.ReduceIfFalse(node); |
| 594 default: |
| 595 return node; |
| 596 } |
| 587 } | 597 } |
| 588 } | 598 } |
| 589 } | 599 } |
| 590 } // namespace v8::internal::compiler | 600 } // namespace v8::internal::compiler |
| OLD | NEW |