| Index: runtime/vm/flow_graph_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
|
| index ee6d051e1b1616f827db37787b91165e3209ac42..e012f598b5297a1b80fe2611b22f48a5c2d6cf6f 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/flow_graph_optimizer.cc
|
| @@ -4541,7 +4541,7 @@ class RangeAnalysis : public ValueObject {
|
| private:
|
| // Collect all values that were proven to be smi in smi_values_ array and all
|
| // CheckSmi instructions in smi_check_ array.
|
| - void CollectSmiValues();
|
| + void CollectValues();
|
|
|
| // Iterate over smi values and constrain them at branch successors.
|
| // Additionally constraint values after CheckSmi instructions.
|
| @@ -4612,15 +4612,17 @@ class RangeAnalysis : public ValueObject {
|
|
|
| FlowGraph* flow_graph_;
|
|
|
| - GrowableArray<Definition*> smi_values_; // Value that are known to be smi.
|
| - GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions.
|
| + // Value that are known to be smi or mint.
|
| + GrowableArray<Definition*> values_;
|
| + // All CheckSmi instructions.
|
| + GrowableArray<CheckSmiInstr*> smi_checks_;
|
|
|
| // All Constraints inserted during InsertConstraints phase. They are treated
|
| // as smi values.
|
| GrowableArray<ConstraintInstr*> constraints_;
|
|
|
| - // Bitvector for a quick filtering of known smi values.
|
| - BitVector* smi_definitions_;
|
| + // Bitvector for a quick filtering of known smi or mint values.
|
| + BitVector* definitions_;
|
|
|
| // Worklist for induction variables analysis.
|
| GrowableArray<Definition*> worklist_;
|
| @@ -4631,20 +4633,22 @@ class RangeAnalysis : public ValueObject {
|
|
|
|
|
| void RangeAnalysis::Analyze() {
|
| - CollectSmiValues();
|
| + CollectValues();
|
| InsertConstraints();
|
| InferRanges();
|
| RemoveConstraints();
|
| }
|
|
|
|
|
| -void RangeAnalysis::CollectSmiValues() {
|
| +void RangeAnalysis::CollectValues() {
|
| const GrowableArray<Definition*>& initial =
|
| *flow_graph_->graph_entry()->initial_definitions();
|
| for (intptr_t i = 0; i < initial.length(); ++i) {
|
| Definition* current = initial[i];
|
| if (current->Type()->ToCid() == kSmiCid) {
|
| - smi_values_.Add(current);
|
| + values_.Add(current);
|
| + } else if (current->IsMintDefinition()) {
|
| + values_.Add(current);
|
| }
|
| }
|
|
|
| @@ -4661,7 +4665,9 @@ void RangeAnalysis::CollectSmiValues() {
|
| for (intptr_t i = 0; i < initial.length(); ++i) {
|
| Definition* current = initial[i];
|
| if (current->Type()->ToCid() == kSmiCid) {
|
| - smi_values_.Add(current);
|
| + values_.Add(current);
|
| + } else if (current->IsMintDefinition()) {
|
| + values_.Add(current);
|
| }
|
| }
|
| }
|
| @@ -4671,7 +4677,7 @@ void RangeAnalysis::CollectSmiValues() {
|
| for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
|
| PhiInstr* current = phi_it.Current();
|
| if (current->Type()->ToCid() == kSmiCid) {
|
| - smi_values_.Add(current);
|
| + values_.Add(current);
|
| }
|
| }
|
| }
|
| @@ -4684,7 +4690,10 @@ void RangeAnalysis::CollectSmiValues() {
|
| if (defn != NULL) {
|
| if ((defn->Type()->ToCid() == kSmiCid) &&
|
| (defn->ssa_temp_index() != -1)) {
|
| - smi_values_.Add(defn);
|
| + values_.Add(defn);
|
| + } else if ((defn->IsMintDefinition()) &&
|
| + (defn->ssa_temp_index() != -1)) {
|
| + values_.Add(defn);
|
| }
|
| } else if (current->IsCheckSmi()) {
|
| smi_checks_.Add(current->AsCheckSmi());
|
| @@ -4849,6 +4858,7 @@ void RangeAnalysis::ConstrainValueAfterBranch(Definition* defn, Value* use) {
|
| }
|
| }
|
|
|
| +
|
| void RangeAnalysis::InsertConstraintsFor(Definition* defn) {
|
| for (Value* use = defn->input_use_list();
|
| use != NULL;
|
| @@ -4887,11 +4897,22 @@ void RangeAnalysis::ConstrainValueAfterCheckArrayBound(
|
| void RangeAnalysis::InsertConstraints() {
|
| for (intptr_t i = 0; i < smi_checks_.length(); i++) {
|
| CheckSmiInstr* check = smi_checks_[i];
|
| - InsertConstraintFor(check->value()->definition(), Range::Unknown(), check);
|
| + ConstraintInstr* constraint =
|
| + InsertConstraintFor(check->value()->definition(),
|
| + Range::UnknownSmi(),
|
| + check);
|
| + if (constraint == NULL) {
|
| + // No constraint was needed.
|
| + continue;
|
| + }
|
| + // Mark the constraint's value's reaching type as smi.
|
| + CompileType* smi_compile_type =
|
| + ZoneCompileType::Wrap(CompileType::FromCid(kSmiCid));
|
| + constraint->value()->SetReachingType(smi_compile_type);
|
| }
|
|
|
| - for (intptr_t i = 0; i < smi_values_.length(); i++) {
|
| - InsertConstraintsFor(smi_values_[i]);
|
| + for (intptr_t i = 0; i < values_.length(); i++) {
|
| + InsertConstraintsFor(values_[i]);
|
| }
|
|
|
| for (intptr_t i = 0; i < constraints_.length(); i++) {
|
| @@ -4929,9 +4950,9 @@ RangeAnalysis::Direction RangeAnalysis::ToDirection(Value* val) {
|
| : kNegative;
|
| } else if (val->definition()->range() != NULL) {
|
| Range* range = val->definition()->range();
|
| - if (Range::ConstantMin(range).value() >= 0) {
|
| + if (Range::ConstantMin(range).ConstantValue() >= 0) {
|
| return kPositive;
|
| - } else if (Range::ConstantMax(range).value() <= 0) {
|
| + } else if (Range::ConstantMax(range).ConstantValue() <= 0) {
|
| return kNegative;
|
| }
|
| }
|
| @@ -5029,7 +5050,7 @@ Range* RangeAnalysis::InferInductionVariableRange(JoinEntryInstr* loop_header,
|
|
|
| case kUnknown:
|
| case kBoth:
|
| - return Range::Unknown();
|
| + return Range::UnknownSmi();
|
| }
|
|
|
| UNREACHABLE();
|
| @@ -5043,7 +5064,7 @@ void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) {
|
| const bool is_loop_header = (join->loop_info() != NULL);
|
| for (PhiIterator it(join); !it.Done(); it.Advance()) {
|
| PhiInstr* phi = it.Current();
|
| - if (smi_definitions_->Contains(phi->ssa_temp_index())) {
|
| + if (definitions_->Contains(phi->ssa_temp_index())) {
|
| if (is_loop_header) {
|
| // Try recognizing simple induction variables.
|
| Range* range = InferInductionVariableRange(join, phi);
|
| @@ -5064,7 +5085,7 @@ void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) {
|
| Definition* defn = current->AsDefinition();
|
| if ((defn != NULL) &&
|
| (defn->ssa_temp_index() != -1) &&
|
| - smi_definitions_->Contains(defn->ssa_temp_index())) {
|
| + definitions_->Contains(defn->ssa_temp_index())) {
|
| defn->InferRange();
|
| } else if (FLAG_array_bounds_check_elimination &&
|
| current->IsCheckArrayBound()) {
|
| @@ -5084,13 +5105,19 @@ void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) {
|
|
|
|
|
| void RangeAnalysis::InferRanges() {
|
| - // Initialize bitvector for quick filtering of smi values.
|
| - smi_definitions_ = new(I) BitVector(flow_graph_->current_ssa_temp_index());
|
| - for (intptr_t i = 0; i < smi_values_.length(); i++) {
|
| - smi_definitions_->Add(smi_values_[i]->ssa_temp_index());
|
| + if (FLAG_trace_range_analysis) {
|
| + OS::Print("---- before range analysis -------\n");
|
| + FlowGraphPrinter printer(*flow_graph_);
|
| + printer.PrintBlocks();
|
| + }
|
| + // Initialize bitvector for quick filtering of int values.
|
| + definitions_ =
|
| + new(I) BitVector(flow_graph_->current_ssa_temp_index());
|
| + for (intptr_t i = 0; i < values_.length(); i++) {
|
| + definitions_->Add(values_[i]->ssa_temp_index());
|
| }
|
| for (intptr_t i = 0; i < constraints_.length(); i++) {
|
| - smi_definitions_->Add(constraints_[i]->ssa_temp_index());
|
| + definitions_->Add(constraints_[i]->ssa_temp_index());
|
| }
|
|
|
| // Infer initial values of ranges.
|
| @@ -5098,7 +5125,7 @@ void RangeAnalysis::InferRanges() {
|
| *flow_graph_->graph_entry()->initial_definitions();
|
| for (intptr_t i = 0; i < initial.length(); ++i) {
|
| Definition* definition = initial[i];
|
| - if (smi_definitions_->Contains(definition->ssa_temp_index())) {
|
| + if (definitions_->Contains(definition->ssa_temp_index())) {
|
| definition->InferRange();
|
| }
|
| }
|
| @@ -5126,7 +5153,7 @@ void RangeAnalysis::RemoveConstraints() {
|
| }
|
|
|
|
|
| -void FlowGraphOptimizer::InferSmiRanges() {
|
| +void FlowGraphOptimizer::InferIntRanges() {
|
| RangeAnalysis range_analysis(flow_graph_);
|
| range_analysis.Analyze();
|
| }
|
|
|