| 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 4563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4574 : flow_graph_(flow_graph), | 4574 : flow_graph_(flow_graph), |
| 4575 marked_defns_(NULL) { } | 4575 marked_defns_(NULL) { } |
| 4576 | 4576 |
| 4577 // Infer ranges for all values and remove overflow checks from binary smi | 4577 // Infer ranges for all values and remove overflow checks from binary smi |
| 4578 // operations when proven redundant. | 4578 // operations when proven redundant. |
| 4579 void Analyze(); | 4579 void Analyze(); |
| 4580 | 4580 |
| 4581 private: | 4581 private: |
| 4582 // Collect all values that were proven to be smi in smi_values_ array and all | 4582 // Collect all values that were proven to be smi in smi_values_ array and all |
| 4583 // CheckSmi instructions in smi_check_ array. | 4583 // CheckSmi instructions in smi_check_ array. |
| 4584 void CollectSmiValues(); | 4584 void CollectValues(); |
| 4585 | 4585 |
| 4586 // Iterate over smi values and constrain them at branch successors. | 4586 // Iterate over smi values and constrain them at branch successors. |
| 4587 // Additionally constraint values after CheckSmi instructions. | 4587 // Additionally constraint values after CheckSmi instructions. |
| 4588 void InsertConstraints(); | 4588 void InsertConstraints(); |
| 4589 | 4589 |
| 4590 // Iterate over uses of the given definition and discover branches that | 4590 // Iterate over uses of the given definition and discover branches that |
| 4591 // constrain it. Insert appropriate Constraint instructions at true | 4591 // constrain it. Insert appropriate Constraint instructions at true |
| 4592 // and false successor and rename all dominated uses to refer to a | 4592 // and false successor and rename all dominated uses to refer to a |
| 4593 // Constraint instead of this definition. | 4593 // Constraint instead of this definition. |
| 4594 void InsertConstraintsFor(Definition* defn); | 4594 void InsertConstraintsFor(Definition* defn); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4645 // Remove artificial Constraint instructions and replace them with actual | 4645 // Remove artificial Constraint instructions and replace them with actual |
| 4646 // unconstrained definitions. | 4646 // unconstrained definitions. |
| 4647 void RemoveConstraints(); | 4647 void RemoveConstraints(); |
| 4648 | 4648 |
| 4649 Range* ConstraintRange(Token::Kind op, Definition* boundary); | 4649 Range* ConstraintRange(Token::Kind op, Definition* boundary); |
| 4650 | 4650 |
| 4651 Isolate* isolate() const { return flow_graph_->isolate(); } | 4651 Isolate* isolate() const { return flow_graph_->isolate(); } |
| 4652 | 4652 |
| 4653 FlowGraph* flow_graph_; | 4653 FlowGraph* flow_graph_; |
| 4654 | 4654 |
| 4655 GrowableArray<Definition*> smi_values_; // Value that are known to be smi. | 4655 // Value that are known to be smi or mint. |
| 4656 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions. | 4656 GrowableArray<Definition*> values_; |
| 4657 // All CheckSmi instructions. |
| 4658 GrowableArray<CheckSmiInstr*> smi_checks_; |
| 4657 | 4659 |
| 4658 // All Constraints inserted during InsertConstraints phase. They are treated | 4660 // All Constraints inserted during InsertConstraints phase. They are treated |
| 4659 // as smi values. | 4661 // as smi values. |
| 4660 GrowableArray<ConstraintInstr*> constraints_; | 4662 GrowableArray<ConstraintInstr*> constraints_; |
| 4661 | 4663 |
| 4662 // Bitvector for a quick filtering of known smi values. | 4664 // Bitvector for a quick filtering of known smi or mint values. |
| 4663 BitVector* smi_definitions_; | 4665 BitVector* definitions_; |
| 4664 | 4666 |
| 4665 // Worklist for induction variables analysis. | 4667 // Worklist for induction variables analysis. |
| 4666 GrowableArray<Definition*> worklist_; | 4668 GrowableArray<Definition*> worklist_; |
| 4667 BitVector* marked_defns_; | 4669 BitVector* marked_defns_; |
| 4668 | 4670 |
| 4669 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); | 4671 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); |
| 4670 }; | 4672 }; |
| 4671 | 4673 |
| 4672 | 4674 |
| 4673 void RangeAnalysis::Analyze() { | 4675 void RangeAnalysis::Analyze() { |
| 4674 CollectSmiValues(); | 4676 CollectValues(); |
| 4675 InsertConstraints(); | 4677 InsertConstraints(); |
| 4676 InferRanges(); | 4678 InferRanges(); |
| 4677 RemoveConstraints(); | 4679 RemoveConstraints(); |
| 4678 } | 4680 } |
| 4679 | 4681 |
| 4680 | 4682 |
| 4681 void RangeAnalysis::CollectSmiValues() { | 4683 void RangeAnalysis::CollectValues() { |
| 4682 const GrowableArray<Definition*>& initial = | 4684 const GrowableArray<Definition*>& initial = |
| 4683 *flow_graph_->graph_entry()->initial_definitions(); | 4685 *flow_graph_->graph_entry()->initial_definitions(); |
| 4684 for (intptr_t i = 0; i < initial.length(); ++i) { | 4686 for (intptr_t i = 0; i < initial.length(); ++i) { |
| 4685 Definition* current = initial[i]; | 4687 Definition* current = initial[i]; |
| 4686 if (current->Type()->ToCid() == kSmiCid) { | 4688 if (current->Type()->ToCid() == kSmiCid) { |
| 4687 smi_values_.Add(current); | 4689 values_.Add(current); |
| 4690 } else if (current->IsMintDefinition()) { |
| 4691 values_.Add(current); |
| 4688 } | 4692 } |
| 4689 } | 4693 } |
| 4690 | 4694 |
| 4691 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); | 4695 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 4692 !block_it.Done(); | 4696 !block_it.Done(); |
| 4693 block_it.Advance()) { | 4697 block_it.Advance()) { |
| 4694 BlockEntryInstr* block = block_it.Current(); | 4698 BlockEntryInstr* block = block_it.Current(); |
| 4695 | 4699 |
| 4696 | 4700 |
| 4697 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) { | 4701 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) { |
| 4698 const GrowableArray<Definition*>& initial = block->IsGraphEntry() | 4702 const GrowableArray<Definition*>& initial = block->IsGraphEntry() |
| 4699 ? *block->AsGraphEntry()->initial_definitions() | 4703 ? *block->AsGraphEntry()->initial_definitions() |
| 4700 : *block->AsCatchBlockEntry()->initial_definitions(); | 4704 : *block->AsCatchBlockEntry()->initial_definitions(); |
| 4701 for (intptr_t i = 0; i < initial.length(); ++i) { | 4705 for (intptr_t i = 0; i < initial.length(); ++i) { |
| 4702 Definition* current = initial[i]; | 4706 Definition* current = initial[i]; |
| 4703 if (current->Type()->ToCid() == kSmiCid) { | 4707 if (current->Type()->ToCid() == kSmiCid) { |
| 4704 smi_values_.Add(current); | 4708 values_.Add(current); |
| 4709 } else if (current->IsMintDefinition()) { |
| 4710 values_.Add(current); |
| 4705 } | 4711 } |
| 4706 } | 4712 } |
| 4707 } | 4713 } |
| 4708 | 4714 |
| 4709 JoinEntryInstr* join = block->AsJoinEntry(); | 4715 JoinEntryInstr* join = block->AsJoinEntry(); |
| 4710 if (join != NULL) { | 4716 if (join != NULL) { |
| 4711 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { | 4717 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { |
| 4712 PhiInstr* current = phi_it.Current(); | 4718 PhiInstr* current = phi_it.Current(); |
| 4713 if (current->Type()->ToCid() == kSmiCid) { | 4719 if (current->Type()->ToCid() == kSmiCid) { |
| 4714 smi_values_.Add(current); | 4720 values_.Add(current); |
| 4721 } else if (current->IsMintDefinition()) { |
| 4722 values_.Add(current); |
| 4715 } | 4723 } |
| 4716 } | 4724 } |
| 4717 } | 4725 } |
| 4718 | 4726 |
| 4719 for (ForwardInstructionIterator instr_it(block); | 4727 for (ForwardInstructionIterator instr_it(block); |
| 4720 !instr_it.Done(); | 4728 !instr_it.Done(); |
| 4721 instr_it.Advance()) { | 4729 instr_it.Advance()) { |
| 4722 Instruction* current = instr_it.Current(); | 4730 Instruction* current = instr_it.Current(); |
| 4723 Definition* defn = current->AsDefinition(); | 4731 Definition* defn = current->AsDefinition(); |
| 4724 if (defn != NULL) { | 4732 if (defn != NULL) { |
| 4725 if ((defn->Type()->ToCid() == kSmiCid) && | 4733 if ((defn->Type()->ToCid() == kSmiCid) && |
| 4726 (defn->ssa_temp_index() != -1)) { | 4734 (defn->ssa_temp_index() != -1)) { |
| 4727 smi_values_.Add(defn); | 4735 values_.Add(defn); |
| 4736 } else if ((defn->IsMintDefinition()) && |
| 4737 (defn->ssa_temp_index() != -1)) { |
| 4738 values_.Add(defn); |
| 4728 } | 4739 } |
| 4729 } else if (current->IsCheckSmi()) { | 4740 } else if (current->IsCheckSmi()) { |
| 4730 smi_checks_.Add(current->AsCheckSmi()); | 4741 smi_checks_.Add(current->AsCheckSmi()); |
| 4731 } | 4742 } |
| 4732 } | 4743 } |
| 4733 } | 4744 } |
| 4734 } | 4745 } |
| 4735 | 4746 |
| 4736 | 4747 |
| 4737 // Returns true if use is dominated by the given instruction. | 4748 // Returns true if use is dominated by the given instruction. |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4882 branch->false_successor()); | 4893 branch->false_successor()); |
| 4883 // Mark false_constraint an artificial use of boundary. This ensures | 4894 // Mark false_constraint an artificial use of boundary. This ensures |
| 4884 // that constraint's range is recalculated if boundary's range changes. | 4895 // that constraint's range is recalculated if boundary's range changes. |
| 4885 if (false_constraint != NULL) { | 4896 if (false_constraint != NULL) { |
| 4886 false_constraint->AddDependency(boundary); | 4897 false_constraint->AddDependency(boundary); |
| 4887 false_constraint->set_target(branch->false_successor()); | 4898 false_constraint->set_target(branch->false_successor()); |
| 4888 } | 4899 } |
| 4889 } | 4900 } |
| 4890 } | 4901 } |
| 4891 | 4902 |
| 4903 |
| 4892 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { | 4904 void RangeAnalysis::InsertConstraintsFor(Definition* defn) { |
| 4893 for (Value* use = defn->input_use_list(); | 4905 for (Value* use = defn->input_use_list(); |
| 4894 use != NULL; | 4906 use != NULL; |
| 4895 use = use->next_use()) { | 4907 use = use->next_use()) { |
| 4896 if (use->instruction()->IsBranch()) { | 4908 if (use->instruction()->IsBranch()) { |
| 4897 ConstrainValueAfterBranch(defn, use); | 4909 ConstrainValueAfterBranch(defn, use); |
| 4898 } else if (use->instruction()->IsCheckArrayBound()) { | 4910 } else if (use->instruction()->IsCheckArrayBound()) { |
| 4899 ConstrainValueAfterCheckArrayBound( | 4911 ConstrainValueAfterCheckArrayBound( |
| 4900 defn, | 4912 defn, |
| 4901 use->instruction()->AsCheckArrayBound(), | 4913 use->instruction()->AsCheckArrayBound(), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4920 RangeBoundary::FromDefinition(index, 1), | 4932 RangeBoundary::FromDefinition(index, 1), |
| 4921 RangeBoundary::MaxSmi()); | 4933 RangeBoundary::MaxSmi()); |
| 4922 } | 4934 } |
| 4923 InsertConstraintFor(defn, constraint_range, check); | 4935 InsertConstraintFor(defn, constraint_range, check); |
| 4924 } | 4936 } |
| 4925 | 4937 |
| 4926 | 4938 |
| 4927 void RangeAnalysis::InsertConstraints() { | 4939 void RangeAnalysis::InsertConstraints() { |
| 4928 for (intptr_t i = 0; i < smi_checks_.length(); i++) { | 4940 for (intptr_t i = 0; i < smi_checks_.length(); i++) { |
| 4929 CheckSmiInstr* check = smi_checks_[i]; | 4941 CheckSmiInstr* check = smi_checks_[i]; |
| 4930 InsertConstraintFor(check->value()->definition(), Range::Unknown(), check); | 4942 InsertConstraintFor(check->value()->definition(), |
| 4943 Range::UnknownSmi(), |
| 4944 check); |
| 4931 } | 4945 } |
| 4932 | 4946 |
| 4933 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 4947 for (intptr_t i = 0; i < values_.length(); i++) { |
| 4934 InsertConstraintsFor(smi_values_[i]); | 4948 InsertConstraintsFor(values_[i]); |
| 4935 } | 4949 } |
| 4936 | 4950 |
| 4937 for (intptr_t i = 0; i < constraints_.length(); i++) { | 4951 for (intptr_t i = 0; i < constraints_.length(); i++) { |
| 4938 InsertConstraintsFor(constraints_[i]); | 4952 InsertConstraintsFor(constraints_[i]); |
| 4939 } | 4953 } |
| 4940 } | 4954 } |
| 4941 | 4955 |
| 4942 | 4956 |
| 4943 void RangeAnalysis::ResetWorklist() { | 4957 void RangeAnalysis::ResetWorklist() { |
| 4944 if (marked_defns_ == NULL) { | 4958 if (marked_defns_ == NULL) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4963 } | 4977 } |
| 4964 } | 4978 } |
| 4965 | 4979 |
| 4966 | 4980 |
| 4967 RangeAnalysis::Direction RangeAnalysis::ToDirection(Value* val) { | 4981 RangeAnalysis::Direction RangeAnalysis::ToDirection(Value* val) { |
| 4968 if (val->BindsToConstant()) { | 4982 if (val->BindsToConstant()) { |
| 4969 return (Smi::Cast(val->BoundConstant()).Value() >= 0) ? kPositive | 4983 return (Smi::Cast(val->BoundConstant()).Value() >= 0) ? kPositive |
| 4970 : kNegative; | 4984 : kNegative; |
| 4971 } else if (val->definition()->range() != NULL) { | 4985 } else if (val->definition()->range() != NULL) { |
| 4972 Range* range = val->definition()->range(); | 4986 Range* range = val->definition()->range(); |
| 4973 if (Range::ConstantMin(range).value() >= 0) { | 4987 if (Range::ConstantMin(range).ConstantValue() >= 0) { |
| 4974 return kPositive; | 4988 return kPositive; |
| 4975 } else if (Range::ConstantMax(range).value() <= 0) { | 4989 } else if (Range::ConstantMax(range).ConstantValue() <= 0) { |
| 4976 return kNegative; | 4990 return kNegative; |
| 4977 } | 4991 } |
| 4978 } | 4992 } |
| 4979 return kUnknown; | 4993 return kUnknown; |
| 4980 } | 4994 } |
| 4981 | 4995 |
| 4982 | 4996 |
| 4983 Range* RangeAnalysis::InferInductionVariableRange(JoinEntryInstr* loop_header, | 4997 Range* RangeAnalysis::InferInductionVariableRange(JoinEntryInstr* loop_header, |
| 4984 PhiInstr* var) { | 4998 PhiInstr* var) { |
| 4985 BitVector* loop_info = loop_header->loop_info(); | 4999 BitVector* loop_info = loop_header->loop_info(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5063 case kPositive: | 5077 case kPositive: |
| 5064 return new(isolate()) Range(RangeBoundary::FromDefinition(initial_value), | 5078 return new(isolate()) Range(RangeBoundary::FromDefinition(initial_value), |
| 5065 RangeBoundary::MaxSmi()); | 5079 RangeBoundary::MaxSmi()); |
| 5066 | 5080 |
| 5067 case kNegative: | 5081 case kNegative: |
| 5068 return new(isolate()) Range(RangeBoundary::MinSmi(), | 5082 return new(isolate()) Range(RangeBoundary::MinSmi(), |
| 5069 RangeBoundary::FromDefinition(initial_value)); | 5083 RangeBoundary::FromDefinition(initial_value)); |
| 5070 | 5084 |
| 5071 case kUnknown: | 5085 case kUnknown: |
| 5072 case kBoth: | 5086 case kBoth: |
| 5073 return Range::Unknown(); | 5087 return Range::UnknownSmi(); |
| 5074 } | 5088 } |
| 5075 | 5089 |
| 5076 UNREACHABLE(); | 5090 UNREACHABLE(); |
| 5077 return NULL; | 5091 return NULL; |
| 5078 } | 5092 } |
| 5079 | 5093 |
| 5080 | 5094 |
| 5081 void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) { | 5095 void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) { |
| 5082 JoinEntryInstr* join = block->AsJoinEntry(); | 5096 JoinEntryInstr* join = block->AsJoinEntry(); |
| 5083 if (join != NULL) { | 5097 if (join != NULL) { |
| 5084 const bool is_loop_header = (join->loop_info() != NULL); | 5098 const bool is_loop_header = (join->loop_info() != NULL); |
| 5085 for (PhiIterator it(join); !it.Done(); it.Advance()) { | 5099 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
| 5086 PhiInstr* phi = it.Current(); | 5100 PhiInstr* phi = it.Current(); |
| 5087 if (smi_definitions_->Contains(phi->ssa_temp_index())) { | 5101 if (definitions_->Contains(phi->ssa_temp_index())) { |
| 5088 if (is_loop_header) { | 5102 if (is_loop_header) { |
| 5089 // Try recognizing simple induction variables. | 5103 // Try recognizing simple induction variables. |
| 5090 Range* range = InferInductionVariableRange(join, phi); | 5104 Range* range = InferInductionVariableRange(join, phi); |
| 5091 if (range != NULL) { | 5105 if (range != NULL) { |
| 5092 phi->range_ = range; | 5106 phi->range_ = range; |
| 5093 continue; | 5107 continue; |
| 5094 } | 5108 } |
| 5095 } | 5109 } |
| 5096 | 5110 |
| 5097 phi->InferRange(); | 5111 phi->InferRange(); |
| 5098 } | 5112 } |
| 5099 } | 5113 } |
| 5100 } | 5114 } |
| 5101 | 5115 |
| 5102 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 5116 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 5103 Instruction* current = it.Current(); | 5117 Instruction* current = it.Current(); |
| 5104 | 5118 |
| 5105 Definition* defn = current->AsDefinition(); | 5119 Definition* defn = current->AsDefinition(); |
| 5106 if ((defn != NULL) && | 5120 if ((defn != NULL) && |
| 5107 (defn->ssa_temp_index() != -1) && | 5121 (defn->ssa_temp_index() != -1) && |
| 5108 smi_definitions_->Contains(defn->ssa_temp_index())) { | 5122 definitions_->Contains(defn->ssa_temp_index())) { |
| 5109 defn->InferRange(); | 5123 defn->InferRange(); |
| 5110 } else if (FLAG_array_bounds_check_elimination && | 5124 } else if (FLAG_array_bounds_check_elimination && |
| 5111 current->IsCheckArrayBound()) { | 5125 current->IsCheckArrayBound()) { |
| 5112 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); | 5126 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); |
| 5113 RangeBoundary array_length = | 5127 RangeBoundary array_length = |
| 5114 RangeBoundary::FromDefinition(check->length()->definition()); | 5128 RangeBoundary::FromDefinition(check->length()->definition()); |
| 5115 if (check->IsRedundant(array_length)) { | 5129 if (check->IsRedundant(array_length)) { |
| 5116 it.RemoveCurrentFromGraph(); | 5130 it.RemoveCurrentFromGraph(); |
| 5117 } | 5131 } |
| 5118 } | 5132 } |
| 5119 } | 5133 } |
| 5120 | 5134 |
| 5121 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { | 5135 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
| 5122 InferRangesRecursive(block->dominated_blocks()[i]); | 5136 InferRangesRecursive(block->dominated_blocks()[i]); |
| 5123 } | 5137 } |
| 5124 } | 5138 } |
| 5125 | 5139 |
| 5126 | 5140 |
| 5127 void RangeAnalysis::InferRanges() { | 5141 void RangeAnalysis::InferRanges() { |
| 5142 if (FLAG_trace_range_analysis) { |
| 5143 OS::Print("---- before range analysis -------\n"); |
| 5144 FlowGraphPrinter printer(*flow_graph_); |
| 5145 printer.PrintBlocks(); |
| 5146 } |
| 5128 // Initialize bitvector for quick filtering of smi values. | 5147 // Initialize bitvector for quick filtering of smi values. |
| 5129 smi_definitions_ = | 5148 definitions_ = |
| 5130 new(isolate()) BitVector(flow_graph_->current_ssa_temp_index()); | 5149 new(isolate()) BitVector(flow_graph_->current_ssa_temp_index()); |
| 5131 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 5150 for (intptr_t i = 0; i < values_.length(); i++) { |
| 5132 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); | 5151 definitions_->Add(values_[i]->ssa_temp_index()); |
| 5133 } | 5152 } |
| 5134 for (intptr_t i = 0; i < constraints_.length(); i++) { | 5153 for (intptr_t i = 0; i < constraints_.length(); i++) { |
| 5135 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); | 5154 definitions_->Add(constraints_[i]->ssa_temp_index()); |
| 5136 } | 5155 } |
| 5137 | 5156 |
| 5138 // Infer initial values of ranges. | 5157 // Infer initial values of ranges. |
| 5139 const GrowableArray<Definition*>& initial = | 5158 const GrowableArray<Definition*>& initial = |
| 5140 *flow_graph_->graph_entry()->initial_definitions(); | 5159 *flow_graph_->graph_entry()->initial_definitions(); |
| 5141 for (intptr_t i = 0; i < initial.length(); ++i) { | 5160 for (intptr_t i = 0; i < initial.length(); ++i) { |
| 5142 Definition* definition = initial[i]; | 5161 Definition* definition = initial[i]; |
| 5143 if (smi_definitions_->Contains(definition->ssa_temp_index())) { | 5162 if (definitions_->Contains(definition->ssa_temp_index())) { |
| 5144 definition->InferRange(); | 5163 definition->InferRange(); |
| 5145 } | 5164 } |
| 5146 } | 5165 } |
| 5147 InferRangesRecursive(flow_graph_->graph_entry()); | 5166 InferRangesRecursive(flow_graph_->graph_entry()); |
| 5148 | 5167 |
| 5149 if (FLAG_trace_range_analysis) { | 5168 if (FLAG_trace_range_analysis) { |
| 5150 OS::Print("---- after range analysis -------\n"); | 5169 OS::Print("---- after range analysis -------\n"); |
| 5151 FlowGraphPrinter printer(*flow_graph_); | 5170 FlowGraphPrinter printer(*flow_graph_); |
| 5152 printer.PrintBlocks(); | 5171 printer.PrintBlocks(); |
| 5153 } | 5172 } |
| 5154 } | 5173 } |
| 5155 | 5174 |
| 5156 | 5175 |
| 5157 void RangeAnalysis::RemoveConstraints() { | 5176 void RangeAnalysis::RemoveConstraints() { |
| 5158 for (intptr_t i = 0; i < constraints_.length(); i++) { | 5177 for (intptr_t i = 0; i < constraints_.length(); i++) { |
| 5159 Definition* def = constraints_[i]->value()->definition(); | 5178 Definition* def = constraints_[i]->value()->definition(); |
| 5160 // Some constraints might be constraining constraints. Unwind the chain of | 5179 // Some constraints might be constraining constraints. Unwind the chain of |
| 5161 // constraints until we reach the actual definition. | 5180 // constraints until we reach the actual definition. |
| 5162 while (def->IsConstraint()) { | 5181 while (def->IsConstraint()) { |
| 5163 def = def->AsConstraint()->value()->definition(); | 5182 def = def->AsConstraint()->value()->definition(); |
| 5164 } | 5183 } |
| 5165 constraints_[i]->ReplaceUsesWith(def); | 5184 constraints_[i]->ReplaceUsesWith(def); |
| 5166 constraints_[i]->RemoveFromGraph(); | 5185 constraints_[i]->RemoveFromGraph(); |
| 5167 } | 5186 } |
| 5168 } | 5187 } |
| 5169 | 5188 |
| 5170 | 5189 |
| 5171 void FlowGraphOptimizer::InferSmiRanges() { | 5190 void FlowGraphOptimizer::InferIntRanges() { |
| 5172 RangeAnalysis range_analysis(flow_graph_); | 5191 RangeAnalysis range_analysis(flow_graph_); |
| 5173 range_analysis.Analyze(); | 5192 range_analysis.Analyze(); |
| 5174 } | 5193 } |
| 5175 | 5194 |
| 5176 | 5195 |
| 5177 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { | 5196 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { |
| 5178 // For every catch-block: Iterate over all call instructions inside the | 5197 // For every catch-block: Iterate over all call instructions inside the |
| 5179 // corresponding try-block and figure out for each environment value if it | 5198 // corresponding try-block and figure out for each environment value if it |
| 5180 // is the same constant at all calls. If yes, replace the initial definition | 5199 // is the same constant at all calls. If yes, replace the initial definition |
| 5181 // at the catch-entry with this constant. | 5200 // at the catch-entry with this constant. |
| (...skipping 4671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9853 } | 9872 } |
| 9854 | 9873 |
| 9855 // Insert materializations at environment uses. | 9874 // Insert materializations at environment uses. |
| 9856 for (intptr_t i = 0; i < exits.length(); i++) { | 9875 for (intptr_t i = 0; i < exits.length(); i++) { |
| 9857 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 9876 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
| 9858 } | 9877 } |
| 9859 } | 9878 } |
| 9860 | 9879 |
| 9861 | 9880 |
| 9862 } // namespace dart | 9881 } // namespace dart |
| OLD | NEW |