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 |