| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/flow_graph_builder.h" | 7 #include "vm/flow_graph_builder.h" |
| 8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
| 9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
| 10 #include "vm/parser.h" | 10 #include "vm/parser.h" |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 | 589 |
| 590 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 590 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
| 591 instr->computation()->Accept(this, instr); | 591 instr->computation()->Accept(this, instr); |
| 592 } | 592 } |
| 593 | 593 |
| 594 | 594 |
| 595 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, | 595 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, |
| 596 BindInstr* instr) { | 596 BindInstr* instr) { |
| 597 if (FLAG_eliminate_type_checks && | 597 if (FLAG_eliminate_type_checks && |
| 598 !comp->is_eliminated() && | 598 !comp->is_eliminated() && |
| 599 !comp->dst_type().IsMalformed() && | |
| 600 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { | 599 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { |
| 600 // TODO(regis): Remove is_eliminated_ field and support. |
| 601 comp->eliminate(); | 601 comp->eliminate(); |
| 602 if (is_ssa_) { |
| 603 UseVal* use = comp->value()->AsUse(); |
| 604 ASSERT(use != NULL); |
| 605 Definition* result = use->definition(); |
| 606 ASSERT(result != NULL); |
| 607 // Replace uses and remove the current instructions via the iterator. |
| 608 instr->ReplaceUsesWith(result); |
| 609 ASSERT(current_iterator()->Current() == instr); |
| 610 current_iterator()->RemoveCurrentFromGraph(); |
| 611 if (FLAG_trace_optimization) { |
| 612 OS::Print("Replacing v%d with v%d\n", |
| 613 instr->ssa_temp_index(), |
| 614 result->ssa_temp_index()); |
| 615 } |
| 616 } |
| 602 if (FLAG_trace_type_check_elimination) { | 617 if (FLAG_trace_type_check_elimination) { |
| 603 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 618 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 604 comp->token_pos(), | 619 comp->token_pos(), |
| 605 comp->value(), | 620 comp->value(), |
| 606 comp->dst_type(), | 621 comp->dst_type(), |
| 607 comp->dst_name(), | 622 comp->dst_name(), |
| 608 comp->is_eliminated()); | 623 comp->is_eliminated()); |
| 609 } | 624 } |
| 610 } | 625 } |
| 611 } | 626 } |
| 612 | 627 |
| 613 | 628 |
| 614 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp, | 629 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp, |
| 615 BindInstr* instr) { | 630 BindInstr* instr) { |
| 631 // TODO(regis): Propagate NullType as well and revise the comment and code |
| 632 // below to also eliminate the test for non-null and non-constant value. |
| 633 |
| 634 // We can only eliminate an 'assert boolean' test when the checked value is |
| 635 // a constant time constant. Indeed, a variable of the proper compile time |
| 636 // type (bool) may still hold null at run time and therefore fail the test. |
| 616 if (FLAG_eliminate_type_checks && | 637 if (FLAG_eliminate_type_checks && |
| 617 !comp->is_eliminated() && | 638 !comp->is_eliminated() && |
| 639 comp->value()->BindsToConstant() && |
| 640 !comp->value()->BindsToConstantNull() && |
| 618 comp->value()->CompileTypeIsMoreSpecificThan( | 641 comp->value()->CompileTypeIsMoreSpecificThan( |
| 619 Type::Handle(Type::BoolInterface()))) { | 642 Type::Handle(Type::BoolInterface()))) { |
| 643 // TODO(regis): Remove is_eliminated_ field and support. |
| 620 comp->eliminate(); | 644 comp->eliminate(); |
| 645 if (is_ssa_) { |
| 646 UseVal* use = comp->value()->AsUse(); |
| 647 ASSERT(use != NULL); |
| 648 Definition* result = use->definition(); |
| 649 ASSERT(result != NULL); |
| 650 // Replace uses and remove the current instructions via the iterator. |
| 651 instr->ReplaceUsesWith(result); |
| 652 ASSERT(current_iterator()->Current() == instr); |
| 653 current_iterator()->RemoveCurrentFromGraph(); |
| 654 if (FLAG_trace_optimization) { |
| 655 OS::Print("Replacing v%d with v%d\n", |
| 656 instr->ssa_temp_index(), |
| 657 result->ssa_temp_index()); |
| 658 } |
| 659 } |
| 621 if (FLAG_trace_type_check_elimination) { | 660 if (FLAG_trace_type_check_elimination) { |
| 622 const String& name = String::Handle(Symbols::New("boolean expression")); | 661 const String& name = String::Handle(Symbols::New("boolean expression")); |
| 623 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 662 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 624 comp->token_pos(), | 663 comp->token_pos(), |
| 625 comp->value(), | 664 comp->value(), |
| 626 Type::Handle(Type::BoolInterface()), | 665 Type::Handle(Type::BoolInterface()), |
| 627 name, | 666 name, |
| 628 comp->is_eliminated()); | 667 comp->is_eliminated()); |
| 629 } | 668 } |
| 630 } | 669 } |
| 631 } | 670 } |
| 632 | 671 |
| 633 | 672 |
| 673 void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfComp* comp, |
| 674 BindInstr* instr) { |
| 675 // TODO(regis): Propagate NullType as well and revise the comment and code |
| 676 // below to also eliminate the test for non-null and non-constant value. |
| 677 |
| 678 // We can only eliminate an 'instance of' test when the checked value is |
| 679 // a constant time constant. Indeed, a variable of the proper compile time |
| 680 // type may still hold null at run time and therefore fail the test. |
| 681 // We do not bother checking for Object destination type, since the graph |
| 682 // builder did already. |
| 683 if (FLAG_eliminate_type_checks && |
| 684 comp->value()->BindsToConstant() && |
| 685 !comp->value()->BindsToConstantNull() && |
| 686 comp->value()->CompileTypeIsMoreSpecificThan(comp->type())) { |
| 687 if (is_ssa_) { |
| 688 UseVal* use = comp->value()->AsUse(); |
| 689 ASSERT(use != NULL); |
| 690 Definition* result = use->definition(); |
| 691 ASSERT(result != NULL); |
| 692 // Replace uses and remove the current instructions via the iterator. |
| 693 instr->ReplaceUsesWith(result); |
| 694 ASSERT(current_iterator()->Current() == instr); |
| 695 current_iterator()->RemoveCurrentFromGraph(); |
| 696 if (FLAG_trace_optimization) { |
| 697 OS::Print("Replacing v%d with v%d\n", |
| 698 instr->ssa_temp_index(), |
| 699 result->ssa_temp_index()); |
| 700 } |
| 701 } |
| 702 if (FLAG_trace_type_check_elimination) { |
| 703 const String& name = String::Handle(Symbols::New("InstanceOf")); |
| 704 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 705 comp->token_pos(), |
| 706 comp->value(), |
| 707 comp->type(), |
| 708 name, |
| 709 /* eliminated = */ true); |
| 710 } |
| 711 } |
| 712 } |
| 713 |
| 714 |
| 634 void FlowGraphTypePropagator::VisitGraphEntry(GraphEntryInstr* graph_entry) { | 715 void FlowGraphTypePropagator::VisitGraphEntry(GraphEntryInstr* graph_entry) { |
| 635 if (graph_entry->start_env() == NULL) { | 716 if (graph_entry->start_env() == NULL) { |
| 636 return; | 717 return; |
| 637 } | 718 } |
| 638 // Visit incoming parameters. | 719 // Visit incoming parameters. |
| 639 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { | 720 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { |
| 640 Value* val = graph_entry->start_env()->values()[i]; | 721 Value* val = graph_entry->start_env()->values()[i]; |
| 641 if (val->IsUse()) { | 722 if (val->IsUse()) { |
| 642 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); | 723 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); |
| 643 if (param != NULL) { | 724 if (param != NULL) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 659 } | 740 } |
| 660 } | 741 } |
| 661 } | 742 } |
| 662 | 743 |
| 663 | 744 |
| 664 void FlowGraphTypePropagator::VisitBind(BindInstr* bind) { | 745 void FlowGraphTypePropagator::VisitBind(BindInstr* bind) { |
| 665 // No need to propagate the input types of the bound computation, as long as | 746 // No need to propagate the input types of the bound computation, as long as |
| 666 // PhiInstr's are handled as part of JoinEntryInstr. | 747 // PhiInstr's are handled as part of JoinEntryInstr. |
| 667 // Visit computation and possibly eliminate type check. | 748 // Visit computation and possibly eliminate type check. |
| 668 bind->computation()->Accept(this, bind); | 749 bind->computation()->Accept(this, bind); |
| 669 // Cache propagated computation type. | 750 // The current bind may have been removed from the graph. |
| 670 AbstractType& type = AbstractType::Handle(bind->computation()->CompileType()); | 751 if (current_iterator()->Current() == bind) { |
| 671 bool changed = bind->SetPropagatedType(type); | 752 // Current bind was not removed. |
| 672 if (changed) { | 753 // Cache propagated computation type. |
| 673 still_changing_ = true; | 754 AbstractType& computation_type = |
| 755 AbstractType::Handle(bind->computation()->CompileType()); |
| 756 bool changed = bind->SetPropagatedType(computation_type); |
| 757 if (changed) { |
| 758 still_changing_ = true; |
| 759 } |
| 674 } | 760 } |
| 675 } | 761 } |
| 676 | 762 |
| 677 | 763 |
| 678 void FlowGraphTypePropagator::VisitPhi(PhiInstr* phi) { | 764 void FlowGraphTypePropagator::VisitPhi(PhiInstr* phi) { |
| 679 // We could set the propagated type of the phi to the least upper bound of its | 765 // We could set the propagated type of the phi to the least upper bound of its |
| 680 // input propagated types. However, keeping all propagated types allows us to | 766 // input propagated types. However, keeping all propagated types allows us to |
| 681 // optimize method dispatch. | 767 // optimize method dispatch. |
| 682 // TODO(regis): Support a set of propagated types. For now, we compute the | 768 // TODO(regis): Support a set of propagated types. For now, we compute the |
| 683 // least specific of the input propagated types. | 769 // least specific of the input propagated types. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 LocationSummary* locs = it.Current()->locs(); | 816 LocationSummary* locs = it.Current()->locs(); |
| 731 if ((locs != NULL) && locs->can_call()) { | 817 if ((locs != NULL) && locs->can_call()) { |
| 732 is_leaf_ = false; | 818 is_leaf_ = false; |
| 733 return; | 819 return; |
| 734 } | 820 } |
| 735 } | 821 } |
| 736 } | 822 } |
| 737 } | 823 } |
| 738 | 824 |
| 739 } // namespace dart | 825 } // namespace dart |
| OLD | NEW |