Chromium Code Reviews| 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 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 | 577 |
| 578 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 578 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
| 579 instr->computation()->Accept(this, instr); | 579 instr->computation()->Accept(this, instr); |
| 580 } | 580 } |
| 581 | 581 |
| 582 | 582 |
| 583 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, | 583 void FlowGraphTypePropagator::VisitAssertAssignable(AssertAssignableComp* comp, |
| 584 BindInstr* instr) { | 584 BindInstr* instr) { |
| 585 if (FLAG_eliminate_type_checks && | 585 if (FLAG_eliminate_type_checks && |
| 586 !comp->is_eliminated() && | 586 !comp->is_eliminated() && |
| 587 !comp->dst_type().IsMalformed() && | |
| 588 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { | 587 comp->value()->CompileTypeIsMoreSpecificThan(comp->dst_type())) { |
| 589 comp->eliminate(); | 588 comp->eliminate(); |
| 589 #if 0 | |
| 590 UseVal* use = comp->value()->AsUse(); | |
| 591 // TODO(regis): Handle constant input value (not a definition). | |
| 592 if (use != NULL) { | |
| 593 Definition* result = use->definition(); | |
| 594 ASSERT(result != NULL); | |
| 595 // Replace uses and remove the current instructions via the iterator. | |
| 596 instr->ReplaceUsesWith(result); | |
| 597 ASSERT(current_iterator()->Current()->AsBind() == instr); | |
| 598 current_iterator()->RemoveCurrentFromGraph(); | |
| 599 instr->RemoveInputUses(); | |
| 600 if (result->use_list() == NULL) { | |
| 601 // Remove the definition of the input as well, since it has no uses. | |
|
Kevin Millikin (Google)
2012/08/15 09:04:25
This is not really safe if it happens, because it
regis
2012/08/15 17:25:27
Thanks! I removed the code removing the unused inp
| |
| 602 current_iterator()->RemoveCurrentFromGraph(); | |
| 603 } | |
| 604 | |
| 605 // TODO(regis): The above instruction removal results in an assert fault: | |
|
Kevin Millikin (Google)
2012/08/15 09:04:25
We should just skip this optimization if we're usi
regis
2012/08/15 17:25:27
Done. That takes care of the assert fault.
| |
| 606 // ../runtime/vm/flow_graph_compiler.cc:754: error: expected: | |
| 607 // val->AsUse()->definition() == registers_[src] | |
| 608 | |
| 609 if (FLAG_trace_optimization) { | |
| 610 OS::Print("Replacing v%d with v%d\n", | |
| 611 instr->ssa_temp_index(), | |
| 612 result->ssa_temp_index()); | |
| 613 } | |
| 614 } | |
| 615 #endif | |
|
srdjan
2012/08/15 02:07:31
Removed dead code before submitting
regis
2012/08/15 17:25:27
The code is now enabled and working.
| |
| 590 if (FLAG_trace_type_check_elimination) { | 616 if (FLAG_trace_type_check_elimination) { |
| 591 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 617 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 592 comp->token_pos(), | 618 comp->token_pos(), |
| 593 comp->value(), | 619 comp->value(), |
| 594 comp->dst_type(), | 620 comp->dst_type(), |
| 595 comp->dst_name(), | 621 comp->dst_name(), |
| 596 comp->is_eliminated()); | 622 comp->is_eliminated()); |
| 597 } | 623 } |
| 598 } | 624 } |
| 599 } | 625 } |
| 600 | 626 |
| 601 | 627 |
| 602 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp, | 628 void FlowGraphTypePropagator::VisitAssertBoolean(AssertBooleanComp* comp, |
| 603 BindInstr* instr) { | 629 BindInstr* instr) { |
| 604 if (FLAG_eliminate_type_checks && | 630 if (FLAG_eliminate_type_checks && |
| 605 !comp->is_eliminated() && | 631 !comp->is_eliminated() && |
| 632 !comp->value()->IsConstantNull() && | |
| 606 comp->value()->CompileTypeIsMoreSpecificThan( | 633 comp->value()->CompileTypeIsMoreSpecificThan( |
| 607 Type::Handle(Type::BoolInterface()))) { | 634 Type::Handle(Type::BoolInterface()))) { |
| 635 // TODO(regis): This optimization may not be correct, since a value of | |
| 636 // compile time type bool may still be null at run time. In this case, | |
| 637 // the bool expression will evaluate to false without throwing a dynamic | |
| 638 // type error. | |
| 608 comp->eliminate(); | 639 comp->eliminate(); |
| 609 if (FLAG_trace_type_check_elimination) { | 640 if (FLAG_trace_type_check_elimination) { |
| 610 const String& name = String::Handle(Symbols::New("boolean expression")); | 641 const String& name = String::Handle(Symbols::New("boolean expression")); |
| 611 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | 642 FlowGraphPrinter::PrintTypeCheck(parsed_function(), |
| 612 comp->token_pos(), | 643 comp->token_pos(), |
| 613 comp->value(), | 644 comp->value(), |
| 614 Type::Handle(Type::BoolInterface()), | 645 Type::Handle(Type::BoolInterface()), |
| 615 name, | 646 name, |
| 616 comp->is_eliminated()); | 647 comp->is_eliminated()); |
| 617 } | 648 } |
| 618 } | 649 } |
| 619 } | 650 } |
| 620 | 651 |
| 621 | 652 |
| 653 void FlowGraphTypePropagator::VisitInstanceOf(InstanceOfComp* comp, | |
| 654 BindInstr* instr) { | |
| 655 // We can only eliminate an 'instance of' test when the checked value is | |
| 656 // a constant time constant. Indeed, a variable of the proper compile time | |
| 657 // type may still hold null at run time and therefore fail the test. | |
| 658 // We do not bother checking for Object destination type, since the graph | |
| 659 // builder did already. | |
| 660 if (FLAG_eliminate_type_checks && | |
| 661 comp->value()->IsConstant() && | |
| 662 !comp->value()->IsConstantNull() && | |
| 663 comp->value()->CompileTypeIsMoreSpecificThan(comp->type())) { | |
| 664 // Remove instr from graph and replace uses with use of true or false. | |
| 665 UNIMPLEMENTED(); // TODO(regis): We never encounter this case so far. | |
| 666 if (FLAG_trace_type_check_elimination) { | |
| 667 const String& name = String::Handle(Symbols::New("InstanceOf")); | |
| 668 FlowGraphPrinter::PrintTypeCheck(parsed_function(), | |
| 669 comp->token_pos(), | |
| 670 comp->value(), | |
| 671 comp->type(), | |
| 672 name, | |
| 673 /* eliminated = */ true); | |
|
srdjan
2012/08/15 02:07:31
You cannot eliminate instance of using CompileType
regis
2012/08/15 17:25:27
I will be able to remove a non-constant value once
| |
| 674 } | |
| 675 } | |
| 676 } | |
| 677 | |
| 678 | |
| 622 void FlowGraphTypePropagator::VisitGraphEntry(GraphEntryInstr* graph_entry) { | 679 void FlowGraphTypePropagator::VisitGraphEntry(GraphEntryInstr* graph_entry) { |
| 623 if (graph_entry->start_env() == NULL) { | 680 if (graph_entry->start_env() == NULL) { |
| 624 return; | 681 return; |
| 625 } | 682 } |
| 626 // Visit incoming parameters. | 683 // Visit incoming parameters. |
| 627 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { | 684 for (intptr_t i = 0; i < graph_entry->start_env()->values().length(); i++) { |
| 628 Value* val = graph_entry->start_env()->values()[i]; | 685 Value* val = graph_entry->start_env()->values()[i]; |
| 629 if (val->IsUse()) { | 686 if (val->IsUse()) { |
| 630 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); | 687 ParameterInstr* param = val->AsUse()->definition()->AsParameter(); |
| 631 if (param != NULL) { | 688 if (param != NULL) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 647 } | 704 } |
| 648 } | 705 } |
| 649 } | 706 } |
| 650 | 707 |
| 651 | 708 |
| 652 void FlowGraphTypePropagator::VisitBind(BindInstr* bind) { | 709 void FlowGraphTypePropagator::VisitBind(BindInstr* bind) { |
| 653 // No need to propagate the input types of the bound computation, as long as | 710 // No need to propagate the input types of the bound computation, as long as |
| 654 // PhiInstr's are handled as part of JoinEntryInstr. | 711 // PhiInstr's are handled as part of JoinEntryInstr. |
| 655 // Visit computation and possibly eliminate type check. | 712 // Visit computation and possibly eliminate type check. |
| 656 bind->computation()->Accept(this, bind); | 713 bind->computation()->Accept(this, bind); |
| 657 // Cache propagated computation type. | 714 // The current bind may have been removed from the graph. |
|
srdjan
2012/08/15 02:07:31
Can this happen, since you are not removing instru
regis
2012/08/15 17:25:27
I am now.
| |
| 658 AbstractType& type = AbstractType::Handle(bind->computation()->CompileType()); | 715 if (current_iterator()->Current()->AsBind() == bind) { |
| 659 bool changed = bind->SetPropagatedType(type); | 716 // Current bind was not removed. |
| 660 if (changed) { | 717 // Cache propagated computation type. |
| 661 still_changing_ = true; | 718 AbstractType& computation_type = |
| 719 AbstractType::Handle(bind->computation()->CompileType()); | |
| 720 bool changed = bind->SetPropagatedType(computation_type); | |
| 721 if (changed) { | |
| 722 still_changing_ = true; | |
| 723 } | |
| 662 } | 724 } |
| 663 } | 725 } |
| 664 | 726 |
| 665 | 727 |
| 666 void FlowGraphTypePropagator::VisitPhi(PhiInstr* phi) { | 728 void FlowGraphTypePropagator::VisitPhi(PhiInstr* phi) { |
| 667 // We could set the propagated type of the phi to the least upper bound of its | 729 // We could set the propagated type of the phi to the least upper bound of its |
| 668 // input propagated types. However, keeping all propagated types allows us to | 730 // input propagated types. However, keeping all propagated types allows us to |
| 669 // optimize method dispatch. | 731 // optimize method dispatch. |
| 670 // TODO(regis): Support a set of propagated types. For now, we compute the | 732 // TODO(regis): Support a set of propagated types. For now, we compute the |
| 671 // least specific of the input propagated types. | 733 // least specific of the input propagated types. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 718 LocationSummary* locs = it.Current()->locs(); | 780 LocationSummary* locs = it.Current()->locs(); |
| 719 if ((locs != NULL) && locs->contains_call()) { | 781 if ((locs != NULL) && locs->contains_call()) { |
| 720 is_leaf_ = false; | 782 is_leaf_ = false; |
| 721 return; | 783 return; |
| 722 } | 784 } |
| 723 } | 785 } |
| 724 } | 786 } |
| 725 } | 787 } |
| 726 | 788 |
| 727 } // namespace dart | 789 } // namespace dart |
| OLD | NEW |