| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/branch_optimizer.h" | 8 #include "vm/branch_optimizer.h" |
| 9 #include "vm/cha.h" | 9 #include "vm/cha.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 | 81 |
| 82 | 82 |
| 83 // Optimize instance calls using ICData. | 83 // Optimize instance calls using ICData. |
| 84 void FlowGraphOptimizer::ApplyICData() { | 84 void FlowGraphOptimizer::ApplyICData() { |
| 85 VisitBlocks(); | 85 VisitBlocks(); |
| 86 } | 86 } |
| 87 | 87 |
| 88 | 88 |
| 89 void FlowGraphOptimizer::PopulateWithICData() { | 89 void FlowGraphOptimizer::PopulateWithICData() { |
| 90 ASSERT(current_iterator_ == NULL); | 90 ASSERT(current_iterator_ == NULL); |
| 91 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 91 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 92 BlockEntryInstr* entry = block_order_[i]; | 92 !block_it.Done(); |
| 93 ForwardInstructionIterator it(entry); | 93 block_it.Advance()) { |
| 94 ForwardInstructionIterator it(block_it.Current()); |
| 94 for (; !it.Done(); it.Advance()) { | 95 for (; !it.Done(); it.Advance()) { |
| 95 Instruction* instr = it.Current(); | 96 Instruction* instr = it.Current(); |
| 96 if (instr->IsInstanceCall()) { | 97 if (instr->IsInstanceCall()) { |
| 97 InstanceCallInstr* call = instr->AsInstanceCall(); | 98 InstanceCallInstr* call = instr->AsInstanceCall(); |
| 98 if (!call->HasICData()) { | 99 if (!call->HasICData()) { |
| 99 const Array& arguments_descriptor = | 100 const Array& arguments_descriptor = |
| 100 Array::Handle(zone(), | 101 Array::Handle(zone(), |
| 101 ArgumentsDescriptor::New(call->ArgumentCount(), | 102 ArgumentsDescriptor::New(call->ArgumentCount(), |
| 102 call->argument_names())); | 103 call->argument_names())); |
| 103 const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New( | 104 const ICData& ic_data = ICData::ZoneHandle(zone(), ICData::New( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 114 | 115 |
| 115 | 116 |
| 116 // Optimize instance calls using cid. This is called after optimizer | 117 // Optimize instance calls using cid. This is called after optimizer |
| 117 // converted instance calls to instructions. Any remaining | 118 // converted instance calls to instructions. Any remaining |
| 118 // instance calls are either megamorphic calls, cannot be optimized or | 119 // instance calls are either megamorphic calls, cannot be optimized or |
| 119 // have no runtime type feedback collected. | 120 // have no runtime type feedback collected. |
| 120 // Attempts to convert an instance call (IC call) using propagated class-ids, | 121 // Attempts to convert an instance call (IC call) using propagated class-ids, |
| 121 // e.g., receiver class id, guarded-cid, or by guessing cid-s. | 122 // e.g., receiver class id, guarded-cid, or by guessing cid-s. |
| 122 void FlowGraphOptimizer::ApplyClassIds() { | 123 void FlowGraphOptimizer::ApplyClassIds() { |
| 123 ASSERT(current_iterator_ == NULL); | 124 ASSERT(current_iterator_ == NULL); |
| 124 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 125 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 125 BlockEntryInstr* entry = block_order_[i]; | 126 !block_it.Done(); |
| 126 ForwardInstructionIterator it(entry); | 127 block_it.Advance()) { |
| 128 ForwardInstructionIterator it(block_it.Current()); |
| 127 current_iterator_ = ⁢ | 129 current_iterator_ = ⁢ |
| 128 for (; !it.Done(); it.Advance()) { | 130 for (; !it.Done(); it.Advance()) { |
| 129 Instruction* instr = it.Current(); | 131 Instruction* instr = it.Current(); |
| 130 if (instr->IsInstanceCall()) { | 132 if (instr->IsInstanceCall()) { |
| 131 InstanceCallInstr* call = instr->AsInstanceCall(); | 133 InstanceCallInstr* call = instr->AsInstanceCall(); |
| 132 if (call->HasICData()) { | 134 if (call->HasICData()) { |
| 133 if (TryCreateICData(call)) { | 135 if (TryCreateICData(call)) { |
| 134 VisitInstanceCall(call); | 136 VisitInstanceCall(call); |
| 135 } | 137 } |
| 136 } | 138 } |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 | 551 |
| 550 | 552 |
| 551 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the | 553 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the |
| 552 // shift can be a truncating Smi shift-left and result is always Smi. | 554 // shift can be a truncating Smi shift-left and result is always Smi. |
| 553 // Merging occurs only per basic-block. | 555 // Merging occurs only per basic-block. |
| 554 void FlowGraphOptimizer::TryOptimizePatterns() { | 556 void FlowGraphOptimizer::TryOptimizePatterns() { |
| 555 if (!FLAG_truncating_left_shift) return; | 557 if (!FLAG_truncating_left_shift) return; |
| 556 ASSERT(current_iterator_ == NULL); | 558 ASSERT(current_iterator_ == NULL); |
| 557 GrowableArray<BinarySmiOpInstr*> div_mod_merge; | 559 GrowableArray<BinarySmiOpInstr*> div_mod_merge; |
| 558 GrowableArray<MathUnaryInstr*> sin_cos_merge; | 560 GrowableArray<MathUnaryInstr*> sin_cos_merge; |
| 559 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 561 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 562 !block_it.Done(); |
| 563 block_it.Advance()) { |
| 560 // Merging only per basic-block. | 564 // Merging only per basic-block. |
| 561 div_mod_merge.Clear(); | 565 div_mod_merge.Clear(); |
| 562 sin_cos_merge.Clear(); | 566 sin_cos_merge.Clear(); |
| 563 BlockEntryInstr* entry = block_order_[i]; | 567 ForwardInstructionIterator it(block_it.Current()); |
| 564 ForwardInstructionIterator it(entry); | |
| 565 current_iterator_ = ⁢ | 568 current_iterator_ = ⁢ |
| 566 for (; !it.Done(); it.Advance()) { | 569 for (; !it.Done(); it.Advance()) { |
| 567 if (it.Current()->IsBinarySmiOp()) { | 570 if (it.Current()->IsBinarySmiOp()) { |
| 568 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); | 571 BinarySmiOpInstr* binop = it.Current()->AsBinarySmiOp(); |
| 569 if (binop->op_kind() == Token::kBIT_AND) { | 572 if (binop->op_kind() == Token::kBIT_AND) { |
| 570 OptimizeLeftShiftBitAndSmiOp(binop, | 573 OptimizeLeftShiftBitAndSmiOp(binop, |
| 571 binop->left()->definition(), | 574 binop->left()->definition(), |
| 572 binop->right()->definition()); | 575 binop->right()->definition()); |
| 573 } else if ((binop->op_kind() == Token::kTRUNCDIV) || | 576 } else if ((binop->op_kind() == Token::kTRUNCDIV) || |
| 574 (binop->op_kind() == Token::kMOD)) { | 577 (binop->op_kind() == Token::kMOD)) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 595 } | 598 } |
| 596 TryMergeTruncDivMod(&div_mod_merge); | 599 TryMergeTruncDivMod(&div_mod_merge); |
| 597 TryMergeMathUnary(&sin_cos_merge); | 600 TryMergeMathUnary(&sin_cos_merge); |
| 598 current_iterator_ = NULL; | 601 current_iterator_ = NULL; |
| 599 } | 602 } |
| 600 } | 603 } |
| 601 | 604 |
| 602 | 605 |
| 603 bool FlowGraphOptimizer::Canonicalize() { | 606 bool FlowGraphOptimizer::Canonicalize() { |
| 604 bool changed = false; | 607 bool changed = false; |
| 605 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 608 |
| 606 BlockEntryInstr* entry = block_order_[i]; | 609 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 607 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 610 !block_it.Done(); |
| 611 block_it.Advance()) { |
| 612 for (ForwardInstructionIterator it(block_it.Current()); |
| 613 !it.Done(); |
| 614 it.Advance()) { |
| 608 Instruction* current = it.Current(); | 615 Instruction* current = it.Current(); |
| 609 if (current->HasUnmatchedInputRepresentations()) { | 616 if (current->HasUnmatchedInputRepresentations()) { |
| 610 // Can't canonicalize this instruction until all conversions for its | 617 // Can't canonicalize this instruction until all conversions for its |
| 611 // inputs are inserted. | 618 // inputs are inserted. |
| 612 continue; | 619 continue; |
| 613 } | 620 } |
| 614 | 621 |
| 615 Instruction* replacement = current->Canonicalize(flow_graph()); | 622 Instruction* replacement = current->Canonicalize(flow_graph()); |
| 616 | 623 |
| 617 if (replacement != current) { | 624 if (replacement != current) { |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 } | 836 } |
| 830 } | 837 } |
| 831 | 838 |
| 832 phi->set_representation(unboxed); | 839 phi->set_representation(unboxed); |
| 833 } | 840 } |
| 834 | 841 |
| 835 | 842 |
| 836 void FlowGraphOptimizer::SelectRepresentations() { | 843 void FlowGraphOptimizer::SelectRepresentations() { |
| 837 // Conservatively unbox all phis that were proven to be of Double, | 844 // Conservatively unbox all phis that were proven to be of Double, |
| 838 // Float32x4, or Int32x4 type. | 845 // Float32x4, or Int32x4 type. |
| 839 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 846 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 840 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); | 847 !block_it.Done(); |
| 848 block_it.Advance()) { |
| 849 JoinEntryInstr* join_entry = block_it.Current()->AsJoinEntry(); |
| 841 if (join_entry != NULL) { | 850 if (join_entry != NULL) { |
| 842 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { | 851 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { |
| 843 PhiInstr* phi = it.Current(); | 852 PhiInstr* phi = it.Current(); |
| 844 UnboxPhi(phi); | 853 UnboxPhi(phi); |
| 845 } | 854 } |
| 846 } | 855 } |
| 847 } | 856 } |
| 848 | 857 |
| 849 // Process all instructions and insert conversions where needed. | 858 // Process all instructions and insert conversions where needed. |
| 850 GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry(); | 859 GraphEntryInstr* graph_entry = flow_graph_->graph_entry(); |
| 851 | 860 |
| 852 // Visit incoming parameters and constants. | 861 // Visit incoming parameters and constants. |
| 853 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { | 862 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { |
| 854 InsertConversionsFor((*graph_entry->initial_definitions())[i]); | 863 InsertConversionsFor((*graph_entry->initial_definitions())[i]); |
| 855 } | 864 } |
| 856 | 865 |
| 857 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 866 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 858 BlockEntryInstr* entry = block_order_[i]; | 867 !block_it.Done(); |
| 868 block_it.Advance()) { |
| 869 BlockEntryInstr* entry = block_it.Current(); |
| 859 JoinEntryInstr* join_entry = entry->AsJoinEntry(); | 870 JoinEntryInstr* join_entry = entry->AsJoinEntry(); |
| 860 if (join_entry != NULL) { | 871 if (join_entry != NULL) { |
| 861 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { | 872 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { |
| 862 PhiInstr* phi = it.Current(); | 873 PhiInstr* phi = it.Current(); |
| 863 ASSERT(phi != NULL); | 874 ASSERT(phi != NULL); |
| 864 ASSERT(phi->is_alive()); | 875 ASSERT(phi->is_alive()); |
| 865 InsertConversionsFor(phi); | 876 InsertConversionsFor(phi); |
| 866 } | 877 } |
| 867 } | 878 } |
| 868 CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry(); | 879 CatchBlockEntryInstr* catch_entry = entry->AsCatchBlockEntry(); |
| (...skipping 3069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3938 // save enough range information in the ICData to drive this decision. | 3949 // save enough range information in the ICData to drive this decision. |
| 3939 } | 3950 } |
| 3940 #endif | 3951 #endif |
| 3941 | 3952 |
| 3942 | 3953 |
| 3943 void FlowGraphOptimizer::EliminateEnvironments() { | 3954 void FlowGraphOptimizer::EliminateEnvironments() { |
| 3944 // After this pass we can no longer perform LICM and hoist instructions | 3955 // After this pass we can no longer perform LICM and hoist instructions |
| 3945 // that can deoptimize. | 3956 // that can deoptimize. |
| 3946 | 3957 |
| 3947 flow_graph_->disallow_licm(); | 3958 flow_graph_->disallow_licm(); |
| 3948 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 3959 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 3949 BlockEntryInstr* block = block_order_[i]; | 3960 !block_it.Done(); |
| 3961 block_it.Advance()) { |
| 3962 BlockEntryInstr* block = block_it.Current(); |
| 3950 block->RemoveEnvironment(); | 3963 block->RemoveEnvironment(); |
| 3951 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 3964 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 3952 Instruction* current = it.Current(); | 3965 Instruction* current = it.Current(); |
| 3953 if (!current->CanDeoptimize()) { | 3966 if (!current->CanDeoptimize()) { |
| 3954 // TODO(srdjan): --source-lines needs deopt environments to get at | 3967 // TODO(srdjan): --source-lines needs deopt environments to get at |
| 3955 // the code for this instruction, however, leaving the environment | 3968 // the code for this instruction, however, leaving the environment |
| 3956 // changes code. | 3969 // changes code. |
| 3957 current->RemoveEnvironment(); | 3970 current->RemoveEnvironment(); |
| 3958 } | 3971 } |
| 3959 } | 3972 } |
| 3960 } | 3973 } |
| 3961 } | 3974 } |
| 3962 | 3975 |
| 3963 | 3976 |
| 3964 } // namespace dart | 3977 } // namespace dart |
| OLD | NEW |