| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_range_analysis.h" | 5 #include "vm/flow_graph_range_analysis.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
| 9 | 9 |
| 10 namespace dart { | 10 namespace dart { |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 JoinEntryInstr* join = block->AsJoinEntry(); | 176 JoinEntryInstr* join = block->AsJoinEntry(); |
| 177 if (join != NULL && join->loop_info() != NULL) { | 177 if (join != NULL && join->loop_info() != NULL) { |
| 178 loop_variables.Clear(); | 178 loop_variables.Clear(); |
| 179 | 179 |
| 180 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { | 180 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { |
| 181 PhiInstr* current = phi_it.Current(); | 181 PhiInstr* current = phi_it.Current(); |
| 182 | 182 |
| 183 InductionVariableInfo* info = DetectSimpleInductionVariable(current); | 183 InductionVariableInfo* info = DetectSimpleInductionVariable(current); |
| 184 if (info != NULL) { | 184 if (info != NULL) { |
| 185 if (FLAG_trace_range_analysis) { | 185 if (FLAG_trace_range_analysis) { |
| 186 OS::Print("Simple loop variable: %s bound <%s>\n", | 186 ISL_Print("Simple loop variable: %s bound <%s>\n", |
| 187 current->ToCString(), | 187 current->ToCString(), |
| 188 info->limit() != NULL ? | 188 info->limit() != NULL ? |
| 189 info->limit()->ToCString() : "?"); | 189 info->limit()->ToCString() : "?"); |
| 190 } | 190 } |
| 191 | 191 |
| 192 loop_variables.Add(info); | 192 loop_variables.Add(info); |
| 193 } | 193 } |
| 194 } | 194 } |
| 195 } | 195 } |
| 196 | 196 |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 range = Range(WidenMin(defn->range(), &range, size), | 688 range = Range(WidenMin(defn->range(), &range, size), |
| 689 WidenMax(defn->range(), &range, size)); | 689 WidenMax(defn->range(), &range, size)); |
| 690 } else if (op == NARROW) { | 690 } else if (op == NARROW) { |
| 691 range = Range(NarrowMin(defn->range(), &range, size), | 691 range = Range(NarrowMin(defn->range(), &range, size), |
| 692 NarrowMax(defn->range(), &range, size)); | 692 NarrowMax(defn->range(), &range, size)); |
| 693 } | 693 } |
| 694 } | 694 } |
| 695 | 695 |
| 696 if (!range.Equals(defn->range())) { | 696 if (!range.Equals(defn->range())) { |
| 697 if (FLAG_trace_range_analysis) { | 697 if (FLAG_trace_range_analysis) { |
| 698 OS::Print("%c [%" Pd "] %s: %s => %s\n", | 698 ISL_Print("%c [%" Pd "] %s: %s => %s\n", |
| 699 OpPrefix(op), | 699 OpPrefix(op), |
| 700 iteration, | 700 iteration, |
| 701 defn->ToCString(), | 701 defn->ToCString(), |
| 702 Range::ToCString(defn->range()), | 702 Range::ToCString(defn->range()), |
| 703 Range::ToCString(&range)); | 703 Range::ToCString(&range)); |
| 704 } | 704 } |
| 705 defn->set_range(range); | 705 defn->set_range(range); |
| 706 return true; | 706 return true; |
| 707 } | 707 } |
| 708 } | 708 } |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 991 flow_graph_(flow_graph), | 991 flow_graph_(flow_graph), |
| 992 scheduler_(flow_graph) { } | 992 scheduler_(flow_graph) { } |
| 993 | 993 |
| 994 void TryGeneralize(CheckArrayBoundInstr* check, | 994 void TryGeneralize(CheckArrayBoundInstr* check, |
| 995 const RangeBoundary& array_length) { | 995 const RangeBoundary& array_length) { |
| 996 Definition* upper_bound = | 996 Definition* upper_bound = |
| 997 ConstructUpperBound(check->index()->definition(), check); | 997 ConstructUpperBound(check->index()->definition(), check); |
| 998 if (upper_bound == UnwrapConstraint(check->index()->definition())) { | 998 if (upper_bound == UnwrapConstraint(check->index()->definition())) { |
| 999 // Unable to construct upper bound for the index. | 999 // Unable to construct upper bound for the index. |
| 1000 if (FLAG_trace_range_analysis) { | 1000 if (FLAG_trace_range_analysis) { |
| 1001 OS::Print("Failed to construct upper bound for %s index\n", | 1001 ISL_Print("Failed to construct upper bound for %s index\n", |
| 1002 check->ToCString()); | 1002 check->ToCString()); |
| 1003 } | 1003 } |
| 1004 return; | 1004 return; |
| 1005 } | 1005 } |
| 1006 | 1006 |
| 1007 // Re-associate subexpressions inside upper_bound to collect all constants | 1007 // Re-associate subexpressions inside upper_bound to collect all constants |
| 1008 // together. This will expose more redundancies when we are going to emit | 1008 // together. This will expose more redundancies when we are going to emit |
| 1009 // upper bound through scheduler. | 1009 // upper bound through scheduler. |
| 1010 if (!Simplify(&upper_bound, NULL)) { | 1010 if (!Simplify(&upper_bound, NULL)) { |
| 1011 if (FLAG_trace_range_analysis) { | 1011 if (FLAG_trace_range_analysis) { |
| 1012 OS::Print("Failed to simplify upper bound for %s index\n", | 1012 ISL_Print("Failed to simplify upper bound for %s index\n", |
| 1013 check->ToCString()); | 1013 check->ToCString()); |
| 1014 } | 1014 } |
| 1015 return; | 1015 return; |
| 1016 } | 1016 } |
| 1017 upper_bound = ApplyConstraints(upper_bound, check); | 1017 upper_bound = ApplyConstraints(upper_bound, check); |
| 1018 range_analysis_->AssignRangesRecursively(upper_bound); | 1018 range_analysis_->AssignRangesRecursively(upper_bound); |
| 1019 | 1019 |
| 1020 // We are going to constrain any symbols participating in + and * operations | 1020 // We are going to constrain any symbols participating in + and * operations |
| 1021 // to guarantee that they are positive. Find all symbols that need | 1021 // to guarantee that they are positive. Find all symbols that need |
| 1022 // constraining. If there is a subtraction subexpression with non-positive | 1022 // constraining. If there is a subtraction subexpression with non-positive |
| 1023 // range give up on generalization for simplicity. | 1023 // range give up on generalization for simplicity. |
| 1024 GrowableArray<Definition*> non_positive_symbols; | 1024 GrowableArray<Definition*> non_positive_symbols; |
| 1025 if (!FindNonPositiveSymbols(&non_positive_symbols, upper_bound)) { | 1025 if (!FindNonPositiveSymbols(&non_positive_symbols, upper_bound)) { |
| 1026 if (FLAG_trace_range_analysis) { | 1026 if (FLAG_trace_range_analysis) { |
| 1027 OS::Print("Failed to generalize %s index to %s" | 1027 ISL_Print("Failed to generalize %s index to %s" |
| 1028 " (can't ensure positivity)\n", | 1028 " (can't ensure positivity)\n", |
| 1029 check->ToCString(), | 1029 check->ToCString(), |
| 1030 IndexBoundToCString(upper_bound)); | 1030 IndexBoundToCString(upper_bound)); |
| 1031 } | 1031 } |
| 1032 return; | 1032 return; |
| 1033 } | 1033 } |
| 1034 | 1034 |
| 1035 // Check that we can statically prove that lower bound of the index is | 1035 // Check that we can statically prove that lower bound of the index is |
| 1036 // non-negative under the assumption that all potentially non-positive | 1036 // non-negative under the assumption that all potentially non-positive |
| 1037 // symbols are positive. | 1037 // symbols are positive. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1051 ConstructLowerBound(check->index()->definition(), check); | 1051 ConstructLowerBound(check->index()->definition(), check); |
| 1052 // No need to simplify lower bound before applying constraints as | 1052 // No need to simplify lower bound before applying constraints as |
| 1053 // we are not going to emit it. | 1053 // we are not going to emit it. |
| 1054 lower_bound = ApplyConstraints(lower_bound, check, &positive_constraints); | 1054 lower_bound = ApplyConstraints(lower_bound, check, &positive_constraints); |
| 1055 range_analysis_->AssignRangesRecursively(lower_bound); | 1055 range_analysis_->AssignRangesRecursively(lower_bound); |
| 1056 | 1056 |
| 1057 if (!RangeUtils::IsPositive(lower_bound->range())) { | 1057 if (!RangeUtils::IsPositive(lower_bound->range())) { |
| 1058 // Can't prove that lower bound is positive even with additional checks | 1058 // Can't prove that lower bound is positive even with additional checks |
| 1059 // against potentially non-positive symbols. Give up. | 1059 // against potentially non-positive symbols. Give up. |
| 1060 if (FLAG_trace_range_analysis) { | 1060 if (FLAG_trace_range_analysis) { |
| 1061 OS::Print("Failed to generalize %s index to %s" | 1061 ISL_Print("Failed to generalize %s index to %s" |
| 1062 " (lower bound is not positive)\n", | 1062 " (lower bound is not positive)\n", |
| 1063 check->ToCString(), | 1063 check->ToCString(), |
| 1064 IndexBoundToCString(upper_bound)); | 1064 IndexBoundToCString(upper_bound)); |
| 1065 } | 1065 } |
| 1066 return; | 1066 return; |
| 1067 } | 1067 } |
| 1068 | 1068 |
| 1069 if (FLAG_trace_range_analysis) { | 1069 if (FLAG_trace_range_analysis) { |
| 1070 OS::Print("For %s computed index bounds [%s, %s]\n", | 1070 ISL_Print("For %s computed index bounds [%s, %s]\n", |
| 1071 check->ToCString(), | 1071 check->ToCString(), |
| 1072 IndexBoundToCString(lower_bound), | 1072 IndexBoundToCString(lower_bound), |
| 1073 IndexBoundToCString(upper_bound)); | 1073 IndexBoundToCString(upper_bound)); |
| 1074 } | 1074 } |
| 1075 | 1075 |
| 1076 // At this point we know that 0 <= index < UpperBound(index) under | 1076 // At this point we know that 0 <= index < UpperBound(index) under |
| 1077 // certain preconditions. Start by emitting this preconditions. | 1077 // certain preconditions. Start by emitting this preconditions. |
| 1078 scheduler_.Start(); | 1078 scheduler_.Start(); |
| 1079 | 1079 |
| 1080 ConstantInstr* max_smi = | 1080 ConstantInstr* max_smi = |
| 1081 flow_graph_->GetConstant(Smi::Handle(Smi::New(Smi::kMaxValue))); | 1081 flow_graph_->GetConstant(Smi::Handle(Smi::New(Smi::kMaxValue))); |
| 1082 for (intptr_t i = 0; i < non_positive_symbols.length(); i++) { | 1082 for (intptr_t i = 0; i < non_positive_symbols.length(); i++) { |
| 1083 CheckArrayBoundInstr* precondition = new CheckArrayBoundInstr( | 1083 CheckArrayBoundInstr* precondition = new CheckArrayBoundInstr( |
| 1084 new Value(max_smi), | 1084 new Value(max_smi), |
| 1085 new Value(non_positive_symbols[i]), | 1085 new Value(non_positive_symbols[i]), |
| 1086 Isolate::kNoDeoptId); | 1086 Isolate::kNoDeoptId); |
| 1087 precondition->mark_generalized(); | 1087 precondition->mark_generalized(); |
| 1088 precondition = scheduler_.Emit(precondition, check); | 1088 precondition = scheduler_.Emit(precondition, check); |
| 1089 if (precondition == NULL) { | 1089 if (precondition == NULL) { |
| 1090 if (FLAG_trace_range_analysis) { | 1090 if (FLAG_trace_range_analysis) { |
| 1091 OS::Print(" => failed to insert positivity constraint\n"); | 1091 ISL_Print(" => failed to insert positivity constraint\n"); |
| 1092 } | 1092 } |
| 1093 scheduler_.Rollback(); | 1093 scheduler_.Rollback(); |
| 1094 return; | 1094 return; |
| 1095 } | 1095 } |
| 1096 } | 1096 } |
| 1097 | 1097 |
| 1098 CheckArrayBoundInstr* new_check = new CheckArrayBoundInstr( | 1098 CheckArrayBoundInstr* new_check = new CheckArrayBoundInstr( |
| 1099 new Value(UnwrapConstraint(check->length()->definition())), | 1099 new Value(UnwrapConstraint(check->length()->definition())), |
| 1100 new Value(upper_bound), | 1100 new Value(upper_bound), |
| 1101 Isolate::kNoDeoptId); | 1101 Isolate::kNoDeoptId); |
| 1102 new_check->mark_generalized(); | 1102 new_check->mark_generalized(); |
| 1103 if (new_check->IsRedundant(array_length)) { | 1103 if (new_check->IsRedundant(array_length)) { |
| 1104 if (FLAG_trace_range_analysis) { | 1104 if (FLAG_trace_range_analysis) { |
| 1105 OS::Print(" => generalized check is redundant\n"); | 1105 ISL_Print(" => generalized check is redundant\n"); |
| 1106 } | 1106 } |
| 1107 RemoveGeneralizedCheck(check); | 1107 RemoveGeneralizedCheck(check); |
| 1108 return; | 1108 return; |
| 1109 } | 1109 } |
| 1110 | 1110 |
| 1111 new_check = scheduler_.Emit(new_check, check); | 1111 new_check = scheduler_.Emit(new_check, check); |
| 1112 if (new_check != NULL) { | 1112 if (new_check != NULL) { |
| 1113 if (FLAG_trace_range_analysis) { | 1113 if (FLAG_trace_range_analysis) { |
| 1114 OS::Print(" => generalized check was hoisted into B%" Pd "\n", | 1114 ISL_Print(" => generalized check was hoisted into B%" Pd "\n", |
| 1115 new_check->GetBlock()->block_id()); | 1115 new_check->GetBlock()->block_id()); |
| 1116 } | 1116 } |
| 1117 RemoveGeneralizedCheck(check); | 1117 RemoveGeneralizedCheck(check); |
| 1118 } else { | 1118 } else { |
| 1119 if (FLAG_trace_range_analysis) { | 1119 if (FLAG_trace_range_analysis) { |
| 1120 OS::Print(" => generalized check can't be hoisted\n"); | 1120 ISL_Print(" => generalized check can't be hoisted\n"); |
| 1121 } | 1121 } |
| 1122 scheduler_.Rollback(); | 1122 scheduler_.Rollback(); |
| 1123 } | 1123 } |
| 1124 } | 1124 } |
| 1125 | 1125 |
| 1126 static void RemoveGeneralizedCheck(CheckArrayBoundInstr* check) { | 1126 static void RemoveGeneralizedCheck(CheckArrayBoundInstr* check) { |
| 1127 BinarySmiOpInstr* binary_op = | 1127 BinarySmiOpInstr* binary_op = |
| 1128 check->index()->definition()->AsBinarySmiOp(); | 1128 check->index()->definition()->AsBinarySmiOp(); |
| 1129 if (binary_op != NULL) { | 1129 if (binary_op != NULL) { |
| 1130 binary_op->set_can_overflow(false); | 1130 binary_op->set_can_overflow(false); |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 // TODO(vegorov): replace Constraint with an uncoditional | 1560 // TODO(vegorov): replace Constraint with an uncoditional |
| 1561 // deoptimization and kill all dominated dead code. | 1561 // deoptimization and kill all dominated dead code. |
| 1562 continue; | 1562 continue; |
| 1563 } | 1563 } |
| 1564 | 1564 |
| 1565 BranchInstr* branch = | 1565 BranchInstr* branch = |
| 1566 target->PredecessorAt(0)->last_instruction()->AsBranch(); | 1566 target->PredecessorAt(0)->last_instruction()->AsBranch(); |
| 1567 if (target == branch->true_successor()) { | 1567 if (target == branch->true_successor()) { |
| 1568 // True unreachable. | 1568 // True unreachable. |
| 1569 if (FLAG_trace_constant_propagation) { | 1569 if (FLAG_trace_constant_propagation) { |
| 1570 OS::Print("Range analysis: True unreachable (B%" Pd ")\n", | 1570 ISL_Print("Range analysis: True unreachable (B%" Pd ")\n", |
| 1571 branch->true_successor()->block_id()); | 1571 branch->true_successor()->block_id()); |
| 1572 } | 1572 } |
| 1573 branch->set_constant_target(branch->false_successor()); | 1573 branch->set_constant_target(branch->false_successor()); |
| 1574 } else { | 1574 } else { |
| 1575 ASSERT(target == branch->false_successor()); | 1575 ASSERT(target == branch->false_successor()); |
| 1576 // False unreachable. | 1576 // False unreachable. |
| 1577 if (FLAG_trace_constant_propagation) { | 1577 if (FLAG_trace_constant_propagation) { |
| 1578 OS::Print("Range analysis: False unreachable (B%" Pd ")\n", | 1578 ISL_Print("Range analysis: False unreachable (B%" Pd ")\n", |
| 1579 branch->false_successor()->block_id()); | 1579 branch->false_successor()->block_id()); |
| 1580 } | 1580 } |
| 1581 branch->set_constant_target(branch->true_successor()); | 1581 branch->set_constant_target(branch->true_successor()); |
| 1582 } | 1582 } |
| 1583 } | 1583 } |
| 1584 } | 1584 } |
| 1585 } | 1585 } |
| 1586 | 1586 |
| 1587 | 1587 |
| 1588 void RangeAnalysis::RemoveConstraints() { | 1588 void RangeAnalysis::RemoveConstraints() { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1659 isolate_ = flow_graph_->isolate(); | 1659 isolate_ = flow_graph_->isolate(); |
| 1660 ASSERT(isolate_ != NULL); | 1660 ASSERT(isolate_ != NULL); |
| 1661 Zone* zone = flow_graph_->zone(); | 1661 Zone* zone = flow_graph_->zone(); |
| 1662 selected_uint32_defs_ = | 1662 selected_uint32_defs_ = |
| 1663 new(zone) BitVector(zone, flow_graph_->current_ssa_temp_index()); | 1663 new(zone) BitVector(zone, flow_graph_->current_ssa_temp_index()); |
| 1664 } | 1664 } |
| 1665 | 1665 |
| 1666 | 1666 |
| 1667 void IntegerInstructionSelector::Select() { | 1667 void IntegerInstructionSelector::Select() { |
| 1668 if (FLAG_trace_integer_ir_selection) { | 1668 if (FLAG_trace_integer_ir_selection) { |
| 1669 OS::Print("---- starting integer ir selection -------\n"); | 1669 ISL_Print("---- starting integer ir selection -------\n"); |
| 1670 } | 1670 } |
| 1671 FindPotentialUint32Definitions(); | 1671 FindPotentialUint32Definitions(); |
| 1672 FindUint32NarrowingDefinitions(); | 1672 FindUint32NarrowingDefinitions(); |
| 1673 Propagate(); | 1673 Propagate(); |
| 1674 ReplaceInstructions(); | 1674 ReplaceInstructions(); |
| 1675 if (FLAG_trace_integer_ir_selection) { | 1675 if (FLAG_trace_integer_ir_selection) { |
| 1676 OS::Print("---- after integer ir selection -------\n"); | 1676 ISL_Print("---- after integer ir selection -------\n"); |
| 1677 FlowGraphPrinter printer(*flow_graph_); | 1677 FlowGraphPrinter printer(*flow_graph_); |
| 1678 printer.PrintBlocks(); | 1678 printer.PrintBlocks(); |
| 1679 } | 1679 } |
| 1680 } | 1680 } |
| 1681 | 1681 |
| 1682 | 1682 |
| 1683 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) { | 1683 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) { |
| 1684 // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging | 1684 // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging |
| 1685 // & untagged of intermediate results. | 1685 // & untagged of intermediate results. |
| 1686 // TODO(johnmccutchan): Consider phis. | 1686 // TODO(johnmccutchan): Consider phis. |
| 1687 return def->IsBoxInt64() || | 1687 return def->IsBoxInt64() || |
| 1688 def->IsUnboxInt64() || | 1688 def->IsUnboxInt64() || |
| 1689 def->IsBinaryMintOp() || | 1689 def->IsBinaryMintOp() || |
| 1690 def->IsShiftMintOp() || | 1690 def->IsShiftMintOp() || |
| 1691 def->IsUnaryMintOp(); | 1691 def->IsUnaryMintOp(); |
| 1692 } | 1692 } |
| 1693 | 1693 |
| 1694 | 1694 |
| 1695 void IntegerInstructionSelector::FindPotentialUint32Definitions() { | 1695 void IntegerInstructionSelector::FindPotentialUint32Definitions() { |
| 1696 if (FLAG_trace_integer_ir_selection) { | 1696 if (FLAG_trace_integer_ir_selection) { |
| 1697 OS::Print("++++ Finding potential Uint32 definitions:\n"); | 1697 ISL_Print("++++ Finding potential Uint32 definitions:\n"); |
| 1698 } | 1698 } |
| 1699 | 1699 |
| 1700 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); | 1700 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 1701 !block_it.Done(); | 1701 !block_it.Done(); |
| 1702 block_it.Advance()) { | 1702 block_it.Advance()) { |
| 1703 BlockEntryInstr* block = block_it.Current(); | 1703 BlockEntryInstr* block = block_it.Current(); |
| 1704 | 1704 |
| 1705 for (ForwardInstructionIterator instr_it(block); | 1705 for (ForwardInstructionIterator instr_it(block); |
| 1706 !instr_it.Done(); | 1706 !instr_it.Done(); |
| 1707 instr_it.Advance()) { | 1707 instr_it.Advance()) { |
| 1708 Instruction* current = instr_it.Current(); | 1708 Instruction* current = instr_it.Current(); |
| 1709 Definition* defn = current->AsDefinition(); | 1709 Definition* defn = current->AsDefinition(); |
| 1710 if ((defn != NULL) && defn->HasSSATemp()) { | 1710 if ((defn != NULL) && defn->HasSSATemp()) { |
| 1711 if (IsPotentialUint32Definition(defn)) { | 1711 if (IsPotentialUint32Definition(defn)) { |
| 1712 if (FLAG_trace_integer_ir_selection) { | 1712 if (FLAG_trace_integer_ir_selection) { |
| 1713 OS::Print("Adding %s\n", current->ToCString()); | 1713 ISL_Print("Adding %s\n", current->ToCString()); |
| 1714 } | 1714 } |
| 1715 potential_uint32_defs_.Add(defn); | 1715 potential_uint32_defs_.Add(defn); |
| 1716 } | 1716 } |
| 1717 } | 1717 } |
| 1718 } | 1718 } |
| 1719 } | 1719 } |
| 1720 } | 1720 } |
| 1721 | 1721 |
| 1722 | 1722 |
| 1723 // BinaryMintOp masks and stores into unsigned typed arrays that truncate the | 1723 // BinaryMintOp masks and stores into unsigned typed arrays that truncate the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1737 return true; | 1737 return true; |
| 1738 } | 1738 } |
| 1739 // TODO(johnmccutchan): Add typed array stores. | 1739 // TODO(johnmccutchan): Add typed array stores. |
| 1740 return false; | 1740 return false; |
| 1741 } | 1741 } |
| 1742 | 1742 |
| 1743 | 1743 |
| 1744 void IntegerInstructionSelector::FindUint32NarrowingDefinitions() { | 1744 void IntegerInstructionSelector::FindUint32NarrowingDefinitions() { |
| 1745 ASSERT(selected_uint32_defs_ != NULL); | 1745 ASSERT(selected_uint32_defs_ != NULL); |
| 1746 if (FLAG_trace_integer_ir_selection) { | 1746 if (FLAG_trace_integer_ir_selection) { |
| 1747 OS::Print("++++ Selecting Uint32 definitions:\n"); | 1747 ISL_Print("++++ Selecting Uint32 definitions:\n"); |
| 1748 OS::Print("++++ Initial set:\n"); | 1748 ISL_Print("++++ Initial set:\n"); |
| 1749 } | 1749 } |
| 1750 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | 1750 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { |
| 1751 Definition* defn = potential_uint32_defs_[i]; | 1751 Definition* defn = potential_uint32_defs_[i]; |
| 1752 if (IsUint32NarrowingDefinition(defn)) { | 1752 if (IsUint32NarrowingDefinition(defn)) { |
| 1753 if (FLAG_trace_integer_ir_selection) { | 1753 if (FLAG_trace_integer_ir_selection) { |
| 1754 OS::Print("Adding %s\n", defn->ToCString()); | 1754 ISL_Print("Adding %s\n", defn->ToCString()); |
| 1755 } | 1755 } |
| 1756 selected_uint32_defs_->Add(defn->ssa_temp_index()); | 1756 selected_uint32_defs_->Add(defn->ssa_temp_index()); |
| 1757 } | 1757 } |
| 1758 } | 1758 } |
| 1759 } | 1759 } |
| 1760 | 1760 |
| 1761 | 1761 |
| 1762 bool IntegerInstructionSelector::AllUsesAreUint32Narrowing(Value* list_head) { | 1762 bool IntegerInstructionSelector::AllUsesAreUint32Narrowing(Value* list_head) { |
| 1763 for (Value::Iterator it(list_head); | 1763 for (Value::Iterator it(list_head); |
| 1764 !it.Done(); | 1764 !it.Done(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1804 AllUsesAreUint32Narrowing(def->env_use_list()); | 1804 AllUsesAreUint32Narrowing(def->env_use_list()); |
| 1805 } | 1805 } |
| 1806 | 1806 |
| 1807 | 1807 |
| 1808 void IntegerInstructionSelector::Propagate() { | 1808 void IntegerInstructionSelector::Propagate() { |
| 1809 ASSERT(selected_uint32_defs_ != NULL); | 1809 ASSERT(selected_uint32_defs_ != NULL); |
| 1810 bool changed = true; | 1810 bool changed = true; |
| 1811 intptr_t iteration = 0; | 1811 intptr_t iteration = 0; |
| 1812 while (changed) { | 1812 while (changed) { |
| 1813 if (FLAG_trace_integer_ir_selection) { | 1813 if (FLAG_trace_integer_ir_selection) { |
| 1814 OS::Print("+++ Iteration: %" Pd "\n", iteration++); | 1814 ISL_Print("+++ Iteration: %" Pd "\n", iteration++); |
| 1815 } | 1815 } |
| 1816 changed = false; | 1816 changed = false; |
| 1817 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | 1817 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { |
| 1818 Definition* defn = potential_uint32_defs_[i]; | 1818 Definition* defn = potential_uint32_defs_[i]; |
| 1819 if (selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | 1819 if (selected_uint32_defs_->Contains(defn->ssa_temp_index())) { |
| 1820 // Already marked as a candidate, skip. | 1820 // Already marked as a candidate, skip. |
| 1821 continue; | 1821 continue; |
| 1822 } | 1822 } |
| 1823 if (defn->IsConstant()) { | 1823 if (defn->IsConstant()) { |
| 1824 // Skip constants. | 1824 // Skip constants. |
| 1825 continue; | 1825 continue; |
| 1826 } | 1826 } |
| 1827 if (CanBecomeUint32(defn)) { | 1827 if (CanBecomeUint32(defn)) { |
| 1828 if (FLAG_trace_integer_ir_selection) { | 1828 if (FLAG_trace_integer_ir_selection) { |
| 1829 OS::Print("Adding %s\n", defn->ToCString()); | 1829 ISL_Print("Adding %s\n", defn->ToCString()); |
| 1830 } | 1830 } |
| 1831 // Found a new candidate. | 1831 // Found a new candidate. |
| 1832 selected_uint32_defs_->Add(defn->ssa_temp_index()); | 1832 selected_uint32_defs_->Add(defn->ssa_temp_index()); |
| 1833 // Haven't reached fixed point yet. | 1833 // Haven't reached fixed point yet. |
| 1834 changed = true; | 1834 changed = true; |
| 1835 } | 1835 } |
| 1836 } | 1836 } |
| 1837 } | 1837 } |
| 1838 if (FLAG_trace_integer_ir_selection) { | 1838 if (FLAG_trace_integer_ir_selection) { |
| 1839 OS::Print("Reached fixed point\n"); | 1839 ISL_Print("Reached fixed point\n"); |
| 1840 } | 1840 } |
| 1841 } | 1841 } |
| 1842 | 1842 |
| 1843 | 1843 |
| 1844 Definition* IntegerInstructionSelector::ConstructReplacementFor( | 1844 Definition* IntegerInstructionSelector::ConstructReplacementFor( |
| 1845 Definition* def) { | 1845 Definition* def) { |
| 1846 // Should only see mint definitions. | 1846 // Should only see mint definitions. |
| 1847 ASSERT(IsPotentialUint32Definition(def)); | 1847 ASSERT(IsPotentialUint32Definition(def)); |
| 1848 // Should not see constant instructions. | 1848 // Should not see constant instructions. |
| 1849 ASSERT(!def->IsConstant()); | 1849 ASSERT(!def->IsConstant()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1876 intptr_t deopt_id = op->DeoptimizationTarget(); | 1876 intptr_t deopt_id = op->DeoptimizationTarget(); |
| 1877 return new(I) ShiftUint32OpInstr(op_kind, left, right, deopt_id); | 1877 return new(I) ShiftUint32OpInstr(op_kind, left, right, deopt_id); |
| 1878 } | 1878 } |
| 1879 UNREACHABLE(); | 1879 UNREACHABLE(); |
| 1880 return NULL; | 1880 return NULL; |
| 1881 } | 1881 } |
| 1882 | 1882 |
| 1883 | 1883 |
| 1884 void IntegerInstructionSelector::ReplaceInstructions() { | 1884 void IntegerInstructionSelector::ReplaceInstructions() { |
| 1885 if (FLAG_trace_integer_ir_selection) { | 1885 if (FLAG_trace_integer_ir_selection) { |
| 1886 OS::Print("++++ Replacing instructions:\n"); | 1886 ISL_Print("++++ Replacing instructions:\n"); |
| 1887 } | 1887 } |
| 1888 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | 1888 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { |
| 1889 Definition* defn = potential_uint32_defs_[i]; | 1889 Definition* defn = potential_uint32_defs_[i]; |
| 1890 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | 1890 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) { |
| 1891 // Not a candidate. | 1891 // Not a candidate. |
| 1892 continue; | 1892 continue; |
| 1893 } | 1893 } |
| 1894 Definition* replacement = ConstructReplacementFor(defn); | 1894 Definition* replacement = ConstructReplacementFor(defn); |
| 1895 ASSERT(replacement != NULL); | 1895 ASSERT(replacement != NULL); |
| 1896 if (FLAG_trace_integer_ir_selection) { | 1896 if (FLAG_trace_integer_ir_selection) { |
| 1897 OS::Print("Replacing %s with %s\n", defn->ToCString(), | 1897 ISL_Print("Replacing %s with %s\n", defn->ToCString(), |
| 1898 replacement->ToCString()); | 1898 replacement->ToCString()); |
| 1899 } | 1899 } |
| 1900 if (!Range::IsUnknown(defn->range())) { | 1900 if (!Range::IsUnknown(defn->range())) { |
| 1901 replacement->set_range(*defn->range()); | 1901 replacement->set_range(*defn->range()); |
| 1902 } | 1902 } |
| 1903 defn->ReplaceWith(replacement, NULL); | 1903 defn->ReplaceWith(replacement, NULL); |
| 1904 ASSERT(flow_graph_->VerifyUseLists()); | 1904 ASSERT(flow_graph_->VerifyUseLists()); |
| 1905 } | 1905 } |
| 1906 } | 1906 } |
| 1907 | 1907 |
| (...skipping 1235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3143 } | 3143 } |
| 3144 } while (CanonicalizeMaxBoundary(&max) || | 3144 } while (CanonicalizeMaxBoundary(&max) || |
| 3145 CanonicalizeMinBoundary(&canonical_length)); | 3145 CanonicalizeMinBoundary(&canonical_length)); |
| 3146 | 3146 |
| 3147 // Failed to prove that maximum is bounded with array length. | 3147 // Failed to prove that maximum is bounded with array length. |
| 3148 return false; | 3148 return false; |
| 3149 } | 3149 } |
| 3150 | 3150 |
| 3151 | 3151 |
| 3152 } // namespace dart | 3152 } // namespace dart |
| OLD | NEW |