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/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 4523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4534 : flow_graph_(flow_graph), | 4534 : flow_graph_(flow_graph), |
4535 marked_defns_(NULL) { } | 4535 marked_defns_(NULL) { } |
4536 | 4536 |
4537 // Infer ranges for all values and remove overflow checks from binary smi | 4537 // Infer ranges for all values and remove overflow checks from binary smi |
4538 // operations when proven redundant. | 4538 // operations when proven redundant. |
4539 void Analyze(); | 4539 void Analyze(); |
4540 | 4540 |
4541 private: | 4541 private: |
4542 // Collect all values that were proven to be smi in smi_values_ array and all | 4542 // Collect all values that were proven to be smi in smi_values_ array and all |
4543 // CheckSmi instructions in smi_check_ array. | 4543 // CheckSmi instructions in smi_check_ array. |
4544 void CollectSmiValues(); | 4544 void CollectValues(); |
4545 | 4545 |
4546 // Iterate over smi values and constrain them at branch successors. | 4546 // Iterate over smi values and constrain them at branch successors. |
4547 // Additionally constraint values after CheckSmi instructions. | 4547 // Additionally constraint values after CheckSmi instructions. |
4548 void InsertConstraints(); | 4548 void InsertConstraints(); |
4549 | 4549 |
4550 // Iterate over uses of the given definition and discover branches that | 4550 // Iterate over uses of the given definition and discover branches that |
4551 // constrain it. Insert appropriate Constraint instructions at true | 4551 // constrain it. Insert appropriate Constraint instructions at true |
4552 // and false successor and rename all dominated uses to refer to a | 4552 // and false successor and rename all dominated uses to refer to a |
4553 // Constraint instead of this definition. | 4553 // Constraint instead of this definition. |
4554 void InsertConstraintsFor(Definition* defn); | 4554 void InsertConstraintsFor(Definition* defn); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4605 // Remove artificial Constraint instructions and replace them with actual | 4605 // Remove artificial Constraint instructions and replace them with actual |
4606 // unconstrained definitions. | 4606 // unconstrained definitions. |
4607 void RemoveConstraints(); | 4607 void RemoveConstraints(); |
4608 | 4608 |
4609 Range* ConstraintRange(Token::Kind op, Definition* boundary); | 4609 Range* ConstraintRange(Token::Kind op, Definition* boundary); |
4610 | 4610 |
4611 Isolate* isolate() const { return flow_graph_->isolate(); } | 4611 Isolate* isolate() const { return flow_graph_->isolate(); } |
4612 | 4612 |
4613 FlowGraph* flow_graph_; | 4613 FlowGraph* flow_graph_; |
4614 | 4614 |
4615 GrowableArray<Definition*> smi_values_; // Value that are known to be smi. | 4615 // Value that are known to be smi or mint. |
4616 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions. | 4616 GrowableArray<Definition*> values_; |
| 4617 // All CheckSmi instructions. |
| 4618 GrowableArray<CheckSmiInstr*> smi_checks_; |
4617 | 4619 |
4618 // All Constraints inserted during InsertConstraints phase. They are treated | 4620 // All Constraints inserted during InsertConstraints phase. They are treated |
4619 // as smi values. | 4621 // as smi values. |
4620 GrowableArray<ConstraintInstr*> constraints_; | 4622 GrowableArray<ConstraintInstr*> constraints_; |
4621 | 4623 |
4622 // Bitvector for a quick filtering of known smi values. | 4624 // Bitvector for a quick filtering of known smi or mint values. |
4623 BitVector* smi_definitions_; | 4625 BitVector* definitions_; |
4624 | 4626 |
4625 // Worklist for induction variables analysis. | 4627 // Worklist for induction variables analysis. |
4626 GrowableArray<Definition*> worklist_; | 4628 GrowableArray<Definition*> worklist_; |
4627 BitVector* marked_defns_; | 4629 BitVector* marked_defns_; |
4628 | 4630 |
4629 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); | 4631 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); |
4630 }; | 4632 }; |
4631 | 4633 |
4632 | 4634 |
4633 void RangeAnalysis::Analyze() { | 4635 void RangeAnalysis::Analyze() { |
4634 CollectSmiValues(); | 4636 CollectValues(); |
4635 InsertConstraints(); | 4637 InsertConstraints(); |
4636 InferRanges(); | 4638 InferRanges(); |
4637 RemoveConstraints(); | 4639 RemoveConstraints(); |
4638 } | 4640 } |
4639 | 4641 |
4640 | 4642 |
4641 void RangeAnalysis::CollectSmiValues() { | 4643 void RangeAnalysis::CollectValues() { |
4642 const GrowableArray<Definition*>& initial = | 4644 const GrowableArray<Definition*>& initial = |
4643 *flow_graph_->graph_entry()->initial_definitions(); | 4645 *flow_graph_->graph_entry()->initial_definitions(); |
4644 for (intptr_t i = 0; i < initial.length(); ++i) { | 4646 for (intptr_t i = 0; i < initial.length(); ++i) { |
4645 Definition* current = initial[i]; | 4647 Definition* current = initial[i]; |
4646 if (current->Type()->ToCid() == kSmiCid) { | 4648 if (current->Type()->ToCid() == kSmiCid) { |
4647 smi_values_.Add(current); | 4649 values_.Add(current); |
| 4650 } else if (current->IsMintDefinition()) { |
| 4651 values_.Add(current); |
4648 } | 4652 } |
4649 } | 4653 } |
4650 | 4654 |
4651 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); | 4655 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
4652 !block_it.Done(); | 4656 !block_it.Done(); |
4653 block_it.Advance()) { | 4657 block_it.Advance()) { |
4654 BlockEntryInstr* block = block_it.Current(); | 4658 BlockEntryInstr* block = block_it.Current(); |
4655 | 4659 |
4656 | 4660 |
4657 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) { | 4661 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) { |
4658 const GrowableArray<Definition*>& initial = block->IsGraphEntry() | 4662 const GrowableArray<Definition*>& initial = block->IsGraphEntry() |
4659 ? *block->AsGraphEntry()->initial_definitions() | 4663 ? *block->AsGraphEntry()->initial_definitions() |
4660 : *block->AsCatchBlockEntry()->initial_definitions(); | 4664 : *block->AsCatchBlockEntry()->initial_definitions(); |
4661 for (intptr_t i = 0; i < initial.length(); ++i) { | 4665 for (intptr_t i = 0; i < initial.length(); ++i) { |
4662 Definition* current = initial[i]; | 4666 Definition* current = initial[i]; |
4663 if (current->Type()->ToCid() == kSmiCid) { | 4667 if (current->Type()->ToCid() == kSmiCid) { |
4664 smi_values_.Add(current); | 4668 values_.Add(current); |
| 4669 } else if (current->IsMintDefinition()) { |
| 4670 values_.Add(current); |
4665 } | 4671 } |
4666 } | 4672 } |
4667 } | 4673 } |
4668 | 4674 |
4669 JoinEntryInstr* join = block->AsJoinEntry(); | 4675 JoinEntryInstr* join = block->AsJoinEntry(); |
4670 if (join != NULL) { | 4676 if (join != NULL) { |
4671 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { | 4677 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { |
4672 PhiInstr* current = phi_it.Current(); | 4678 PhiInstr* current = phi_it.Current(); |
4673 if (current->Type()->ToCid() == kSmiCid) { | 4679 if (current->Type()->ToCid() == kSmiCid) { |
4674 smi_values_.Add(current); | 4680 values_.Add(current); |
4675 } | 4681 } |
4676 } | 4682 } |
4677 } | 4683 } |
4678 | 4684 |
4679 for (ForwardInstructionIterator instr_it(block); | 4685 for (ForwardInstructionIterator instr_it(block); |
4680 !instr_it.Done(); | 4686 !instr_it.Done(); |
4681 instr_it.Advance()) { | 4687 instr_it.Advance()) { |
4682 Instruction* current = instr_it.Current(); | 4688 Instruction* current = instr_it.Current(); |
4683 Definition* defn = current->AsDefinition(); | 4689 Definition* defn = current->AsDefinition(); |
4684 if (defn != NULL) { | 4690 if (defn != NULL) { |
4685 if ((defn->Type()->ToCid() == kSmiCid) && | 4691 if ((defn->Type()->ToCid() == kSmiCid) && |
4686 (defn->ssa_temp_index() != -1)) { | 4692 (defn->ssa_temp_index() != -1)) { |
4687 smi_values_.Add(defn); | 4693 values_.Add(defn); |
| 4694 } else if ((defn->IsMintDefinition()) && |
| 4695 (defn->ssa_temp_index() != -1)) { |
| 4696 values_.Add(defn); |
4688 } | 4697 } |
4689 } else if (current->IsCheckSmi()) { | 4698 } else if (current->IsCheckSmi()) { |
4690 smi_checks_.Add(current->AsCheckSmi()); | 4699 smi_checks_.Add(current->AsCheckSmi()); |
4691 } | 4700 } |
4692 } | 4701 } |
4693 } | 4702 } |
4694 } | 4703 } |
4695 | 4704 |
4696 | 4705 |
4697 // Returns true if use is dominated by the given instruction. | 4706 // Returns true if use is dominated by the given instruction. |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4842 branch->false_successor()); | 4851 branch->false_successor()); |
4843 // Mark false_constraint an artificial use of boundary. This ensures | 4852 // Mark false_constraint an artificial use of boundary. This ensures |
4844 // that constraint's range is recalculated if boundary's range changes. | 4853 // that constraint's range is recalculated if boundary's range changes. |
4845 if (false_constraint != NULL) { | 4854 if (false_constraint != NULL) { |
4846 false_constraint->AddDependency(boundary); | 4855 false_constraint->AddDependency(boundary); |
4847 false_constraint->set_target(branch->false_successor()); | 4856 false_constraint->set_target(branch->false_successor()); |
4848 } | 4857 } |
4849 } | 4858 } |
4850 } | 4859 } |
4851 | 4860 |
| 4861 |
4852 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { | 4862 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { |
4853 for (Value* use = defn->input_use_list(); | 4863 for (Value* use = defn->input_use_list(); |
4854 use != NULL; | 4864 use != NULL; |
4855 use = use->next_use()) { | 4865 use = use->next_use()) { |
4856 if (use->instruction()->IsBranch()) { | 4866 if (use->instruction()->IsBranch()) { |
4857 ConstrainValueAfterBranch(defn, use); | 4867 ConstrainValueAfterBranch(defn, use); |
4858 } else if (use->instruction()->IsCheckArrayBound()) { | 4868 } else if (use->instruction()->IsCheckArrayBound()) { |
4859 ConstrainValueAfterCheckArrayBound( | 4869 ConstrainValueAfterCheckArrayBound( |
4860 defn, | 4870 defn, |
4861 use->instruction()->AsCheckArrayBound(), | 4871 use->instruction()->AsCheckArrayBound(), |
(...skipping 18 matching lines...) Expand all Loading... |
4880 RangeBoundary::FromDefinition(index, 1), | 4890 RangeBoundary::FromDefinition(index, 1), |
4881 RangeBoundary::MaxSmi()); | 4891 RangeBoundary::MaxSmi()); |
4882 } | 4892 } |
4883 InsertConstraintFor(defn, constraint_range, check); | 4893 InsertConstraintFor(defn, constraint_range, check); |
4884 } | 4894 } |
4885 | 4895 |
4886 | 4896 |
4887 void RangeAnalysis::InsertConstraints() { | 4897 void RangeAnalysis::InsertConstraints() { |
4888 for (intptr_t i = 0; i < smi_checks_.length(); i++) { | 4898 for (intptr_t i = 0; i < smi_checks_.length(); i++) { |
4889 CheckSmiInstr* check = smi_checks_[i]; | 4899 CheckSmiInstr* check = smi_checks_[i]; |
4890 InsertConstraintFor(check->value()->definition(), Range::Unknown(), check); | 4900 ConstraintInstr* constraint = |
| 4901 InsertConstraintFor(check->value()->definition(), |
| 4902 Range::UnknownSmi(), |
| 4903 check); |
| 4904 if (constraint == NULL) { |
| 4905 // No constraint was needed. |
| 4906 continue; |
| 4907 } |
| 4908 // Mark the constraint's value's reaching type as smi. |
| 4909 CompileType* smi_compile_type = |
| 4910 ZoneCompileType::Wrap(CompileType::FromCid(kSmiCid)); |
| 4911 constraint->value()->SetReachingType(smi_compile_type); |
4891 } | 4912 } |
4892 | 4913 |
4893 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 4914 for (intptr_t i = 0; i < values_.length(); i++) { |
4894 InsertConstraintsFor(smi_values_[i]); | 4915 InsertConstraintsFor(values_[i]); |
4895 } | 4916 } |
4896 | 4917 |
4897 for (intptr_t i = 0; i < constraints_.length(); i++) { | 4918 for (intptr_t i = 0; i < constraints_.length(); i++) { |
4898 InsertConstraintsFor(constraints_[i]); | 4919 InsertConstraintsFor(constraints_[i]); |
4899 } | 4920 } |
4900 } | 4921 } |
4901 | 4922 |
4902 | 4923 |
4903 void RangeAnalysis::ResetWorklist() { | 4924 void RangeAnalysis::ResetWorklist() { |
4904 if (marked_defns_ == NULL) { | 4925 if (marked_defns_ == NULL) { |
(...skipping 17 matching lines...) Expand all Loading... |
4922 } | 4943 } |
4923 } | 4944 } |
4924 | 4945 |
4925 | 4946 |
4926 RangeAnalysis::Direction RangeAnalysis::ToDirection(Value* val) { | 4947 RangeAnalysis::Direction RangeAnalysis::ToDirection(Value* val) { |
4927 if (val->BindsToConstant()) { | 4948 if (val->BindsToConstant()) { |
4928 return (Smi::Cast(val->BoundConstant()).Value() >= 0) ? kPositive | 4949 return (Smi::Cast(val->BoundConstant()).Value() >= 0) ? kPositive |
4929 : kNegative; | 4950 : kNegative; |
4930 } else if (val->definition()->range() != NULL) { | 4951 } else if (val->definition()->range() != NULL) { |
4931 Range* range = val->definition()->range(); | 4952 Range* range = val->definition()->range(); |
4932 if (Range::ConstantMin(range).value() >= 0) { | 4953 if (Range::ConstantMin(range).ConstantValue() >= 0) { |
4933 return kPositive; | 4954 return kPositive; |
4934 } else if (Range::ConstantMax(range).value() <= 0) { | 4955 } else if (Range::ConstantMax(range).ConstantValue() <= 0) { |
4935 return kNegative; | 4956 return kNegative; |
4936 } | 4957 } |
4937 } | 4958 } |
4938 return kUnknown; | 4959 return kUnknown; |
4939 } | 4960 } |
4940 | 4961 |
4941 | 4962 |
4942 Range* RangeAnalysis::InferInductionVariableRange(JoinEntryInstr* loop_header, | 4963 Range* RangeAnalysis::InferInductionVariableRange(JoinEntryInstr* loop_header, |
4943 PhiInstr* var) { | 4964 PhiInstr* var) { |
4944 BitVector* loop_info = loop_header->loop_info(); | 4965 BitVector* loop_info = loop_header->loop_info(); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5022 case kPositive: | 5043 case kPositive: |
5023 return new(I) Range(RangeBoundary::FromDefinition(initial_value), | 5044 return new(I) Range(RangeBoundary::FromDefinition(initial_value), |
5024 RangeBoundary::MaxSmi()); | 5045 RangeBoundary::MaxSmi()); |
5025 | 5046 |
5026 case kNegative: | 5047 case kNegative: |
5027 return new(I) Range(RangeBoundary::MinSmi(), | 5048 return new(I) Range(RangeBoundary::MinSmi(), |
5028 RangeBoundary::FromDefinition(initial_value)); | 5049 RangeBoundary::FromDefinition(initial_value)); |
5029 | 5050 |
5030 case kUnknown: | 5051 case kUnknown: |
5031 case kBoth: | 5052 case kBoth: |
5032 return Range::Unknown(); | 5053 return Range::UnknownSmi(); |
5033 } | 5054 } |
5034 | 5055 |
5035 UNREACHABLE(); | 5056 UNREACHABLE(); |
5036 return NULL; | 5057 return NULL; |
5037 } | 5058 } |
5038 | 5059 |
5039 | 5060 |
5040 void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) { | 5061 void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) { |
5041 JoinEntryInstr* join = block->AsJoinEntry(); | 5062 JoinEntryInstr* join = block->AsJoinEntry(); |
5042 if (join != NULL) { | 5063 if (join != NULL) { |
5043 const bool is_loop_header = (join->loop_info() != NULL); | 5064 const bool is_loop_header = (join->loop_info() != NULL); |
5044 for (PhiIterator it(join); !it.Done(); it.Advance()) { | 5065 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
5045 PhiInstr* phi = it.Current(); | 5066 PhiInstr* phi = it.Current(); |
5046 if (smi_definitions_->Contains(phi->ssa_temp_index())) { | 5067 if (definitions_->Contains(phi->ssa_temp_index())) { |
5047 if (is_loop_header) { | 5068 if (is_loop_header) { |
5048 // Try recognizing simple induction variables. | 5069 // Try recognizing simple induction variables. |
5049 Range* range = InferInductionVariableRange(join, phi); | 5070 Range* range = InferInductionVariableRange(join, phi); |
5050 if (range != NULL) { | 5071 if (range != NULL) { |
5051 phi->range_ = range; | 5072 phi->range_ = range; |
5052 continue; | 5073 continue; |
5053 } | 5074 } |
5054 } | 5075 } |
5055 | 5076 |
5056 phi->InferRange(); | 5077 phi->InferRange(); |
5057 } | 5078 } |
5058 } | 5079 } |
5059 } | 5080 } |
5060 | 5081 |
5061 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 5082 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
5062 Instruction* current = it.Current(); | 5083 Instruction* current = it.Current(); |
5063 | 5084 |
5064 Definition* defn = current->AsDefinition(); | 5085 Definition* defn = current->AsDefinition(); |
5065 if ((defn != NULL) && | 5086 if ((defn != NULL) && |
5066 (defn->ssa_temp_index() != -1) && | 5087 (defn->ssa_temp_index() != -1) && |
5067 smi_definitions_->Contains(defn->ssa_temp_index())) { | 5088 definitions_->Contains(defn->ssa_temp_index())) { |
5068 defn->InferRange(); | 5089 defn->InferRange(); |
5069 } else if (FLAG_array_bounds_check_elimination && | 5090 } else if (FLAG_array_bounds_check_elimination && |
5070 current->IsCheckArrayBound()) { | 5091 current->IsCheckArrayBound()) { |
5071 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); | 5092 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); |
5072 RangeBoundary array_length = | 5093 RangeBoundary array_length = |
5073 RangeBoundary::FromDefinition(check->length()->definition()); | 5094 RangeBoundary::FromDefinition(check->length()->definition()); |
5074 if (check->IsRedundant(array_length)) { | 5095 if (check->IsRedundant(array_length)) { |
5075 it.RemoveCurrentFromGraph(); | 5096 it.RemoveCurrentFromGraph(); |
5076 } | 5097 } |
5077 } | 5098 } |
5078 } | 5099 } |
5079 | 5100 |
5080 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { | 5101 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
5081 InferRangesRecursive(block->dominated_blocks()[i]); | 5102 InferRangesRecursive(block->dominated_blocks()[i]); |
5082 } | 5103 } |
5083 } | 5104 } |
5084 | 5105 |
5085 | 5106 |
5086 void RangeAnalysis::InferRanges() { | 5107 void RangeAnalysis::InferRanges() { |
5087 // Initialize bitvector for quick filtering of smi values. | 5108 if (FLAG_trace_range_analysis) { |
5088 smi_definitions_ = new(I) BitVector(flow_graph_->current_ssa_temp_index()); | 5109 OS::Print("---- before range analysis -------\n"); |
5089 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 5110 FlowGraphPrinter printer(*flow_graph_); |
5090 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); | 5111 printer.PrintBlocks(); |
| 5112 } |
| 5113 // Initialize bitvector for quick filtering of int values. |
| 5114 definitions_ = |
| 5115 new(I) BitVector(flow_graph_->current_ssa_temp_index()); |
| 5116 for (intptr_t i = 0; i < values_.length(); i++) { |
| 5117 definitions_->Add(values_[i]->ssa_temp_index()); |
5091 } | 5118 } |
5092 for (intptr_t i = 0; i < constraints_.length(); i++) { | 5119 for (intptr_t i = 0; i < constraints_.length(); i++) { |
5093 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); | 5120 definitions_->Add(constraints_[i]->ssa_temp_index()); |
5094 } | 5121 } |
5095 | 5122 |
5096 // Infer initial values of ranges. | 5123 // Infer initial values of ranges. |
5097 const GrowableArray<Definition*>& initial = | 5124 const GrowableArray<Definition*>& initial = |
5098 *flow_graph_->graph_entry()->initial_definitions(); | 5125 *flow_graph_->graph_entry()->initial_definitions(); |
5099 for (intptr_t i = 0; i < initial.length(); ++i) { | 5126 for (intptr_t i = 0; i < initial.length(); ++i) { |
5100 Definition* definition = initial[i]; | 5127 Definition* definition = initial[i]; |
5101 if (smi_definitions_->Contains(definition->ssa_temp_index())) { | 5128 if (definitions_->Contains(definition->ssa_temp_index())) { |
5102 definition->InferRange(); | 5129 definition->InferRange(); |
5103 } | 5130 } |
5104 } | 5131 } |
5105 InferRangesRecursive(flow_graph_->graph_entry()); | 5132 InferRangesRecursive(flow_graph_->graph_entry()); |
5106 | 5133 |
5107 if (FLAG_trace_range_analysis) { | 5134 if (FLAG_trace_range_analysis) { |
5108 OS::Print("---- after range analysis -------\n"); | 5135 OS::Print("---- after range analysis -------\n"); |
5109 FlowGraphPrinter printer(*flow_graph_); | 5136 FlowGraphPrinter printer(*flow_graph_); |
5110 printer.PrintBlocks(); | 5137 printer.PrintBlocks(); |
5111 } | 5138 } |
5112 } | 5139 } |
5113 | 5140 |
5114 | 5141 |
5115 void RangeAnalysis::RemoveConstraints() { | 5142 void RangeAnalysis::RemoveConstraints() { |
5116 for (intptr_t i = 0; i < constraints_.length(); i++) { | 5143 for (intptr_t i = 0; i < constraints_.length(); i++) { |
5117 Definition* def = constraints_[i]->value()->definition(); | 5144 Definition* def = constraints_[i]->value()->definition(); |
5118 // Some constraints might be constraining constraints. Unwind the chain of | 5145 // Some constraints might be constraining constraints. Unwind the chain of |
5119 // constraints until we reach the actual definition. | 5146 // constraints until we reach the actual definition. |
5120 while (def->IsConstraint()) { | 5147 while (def->IsConstraint()) { |
5121 def = def->AsConstraint()->value()->definition(); | 5148 def = def->AsConstraint()->value()->definition(); |
5122 } | 5149 } |
5123 constraints_[i]->ReplaceUsesWith(def); | 5150 constraints_[i]->ReplaceUsesWith(def); |
5124 constraints_[i]->RemoveFromGraph(); | 5151 constraints_[i]->RemoveFromGraph(); |
5125 } | 5152 } |
5126 } | 5153 } |
5127 | 5154 |
5128 | 5155 |
5129 void FlowGraphOptimizer::InferSmiRanges() { | 5156 void FlowGraphOptimizer::InferIntRanges() { |
5130 RangeAnalysis range_analysis(flow_graph_); | 5157 RangeAnalysis range_analysis(flow_graph_); |
5131 range_analysis.Analyze(); | 5158 range_analysis.Analyze(); |
5132 } | 5159 } |
5133 | 5160 |
5134 | 5161 |
5135 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { | 5162 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { |
5136 // For every catch-block: Iterate over all call instructions inside the | 5163 // For every catch-block: Iterate over all call instructions inside the |
5137 // corresponding try-block and figure out for each environment value if it | 5164 // corresponding try-block and figure out for each environment value if it |
5138 // is the same constant at all calls. If yes, replace the initial definition | 5165 // is the same constant at all calls. If yes, replace the initial definition |
5139 // at the catch-entry with this constant. | 5166 // at the catch-entry with this constant. |
(...skipping 4663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9803 } | 9830 } |
9804 | 9831 |
9805 // Insert materializations at environment uses. | 9832 // Insert materializations at environment uses. |
9806 for (intptr_t i = 0; i < exits.length(); i++) { | 9833 for (intptr_t i = 0; i < exits.length(); i++) { |
9807 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9834 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
9808 } | 9835 } |
9809 } | 9836 } |
9810 | 9837 |
9811 | 9838 |
9812 } // namespace dart | 9839 } // namespace dart |
OLD | NEW |