Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: runtime/vm/flow_graph_range_analysis.cc

Issue 670263007: IR refactoring: consolidate all boxing and unboxing instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 Definition* defn = value->definition(); 499 Definition* defn = value->definition();
500 const Range* range = defn->range(); 500 const Range* range = defn->range();
501 501
502 if ((range == NULL) && (defn->Type()->ToCid() != kSmiCid)) { 502 if ((range == NULL) && (defn->Type()->ToCid() != kSmiCid)) {
503 // Type propagator determined that reaching type for this use is Smi. 503 // Type propagator determined that reaching type for this use is Smi.
504 // However the definition itself is not a smi-definition and 504 // However the definition itself is not a smi-definition and
505 // thus it will never have range assigned to it. Just return the widest 505 // thus it will never have range assigned to it. Just return the widest
506 // range possible for this value. 506 // range possible for this value.
507 // We don't need to handle kMintCid here because all external mints 507 // We don't need to handle kMintCid here because all external mints
508 // (e.g. results of loads or function call) can be used only after they 508 // (e.g. results of loads or function call) can be used only after they
509 // pass through UnboxIntegerInstr which is considered as mint-definition 509 // pass through UnboxInt64Instr which is considered as mint-definition
510 // and will have a range assigned to it. 510 // and will have a range assigned to it.
511 // Note: that we can't return NULL here because it is used as lattice's 511 // Note: that we can't return NULL here because it is used as lattice's
512 // bottom element to indicate that the range was not computed *yet*. 512 // bottom element to indicate that the range was not computed *yet*.
513 return &smi_range_; 513 return &smi_range_;
514 } 514 }
515 515
516 return range; 516 return range;
517 } 517 }
518 518
519 519
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 FlowGraphPrinter printer(*flow_graph_); 1640 FlowGraphPrinter printer(*flow_graph_);
1641 printer.PrintBlocks(); 1641 printer.PrintBlocks();
1642 } 1642 }
1643 } 1643 }
1644 1644
1645 1645
1646 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) { 1646 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) {
1647 // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging 1647 // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging
1648 // & untagged of intermediate results. 1648 // & untagged of intermediate results.
1649 // TODO(johnmccutchan): Consider phis. 1649 // TODO(johnmccutchan): Consider phis.
1650 return def->IsBoxInteger() || // BoxMint. 1650 return def->IsBoxInt64() ||
1651 def->IsUnboxInteger() || // UnboxMint. 1651 def->IsUnboxInt64() ||
1652 def->IsBinaryMintOp() || 1652 def->IsBinaryMintOp() ||
1653 def->IsShiftMintOp() || 1653 def->IsShiftMintOp() ||
1654 def->IsUnaryMintOp(); 1654 def->IsUnaryMintOp();
1655 } 1655 }
1656 1656
1657 1657
1658 void IntegerInstructionSelector::FindPotentialUint32Definitions() { 1658 void IntegerInstructionSelector::FindPotentialUint32Definitions() {
1659 if (FLAG_trace_integer_ir_selection) { 1659 if (FLAG_trace_integer_ir_selection) {
1660 OS::Print("++++ Finding potential Uint32 definitions:\n"); 1660 OS::Print("++++ Finding potential Uint32 definitions:\n");
1661 } 1661 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 !selected_uint32_defs_->Contains(defn->ssa_temp_index())) { 1733 !selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
1734 return false; 1734 return false;
1735 } 1735 }
1736 } 1736 }
1737 return true; 1737 return true;
1738 } 1738 }
1739 1739
1740 1740
1741 bool IntegerInstructionSelector::CanBecomeUint32(Definition* def) { 1741 bool IntegerInstructionSelector::CanBecomeUint32(Definition* def) {
1742 ASSERT(IsPotentialUint32Definition(def)); 1742 ASSERT(IsPotentialUint32Definition(def));
1743 if (def->IsBoxInteger()) { 1743 if (def->IsBoxInt64()) {
1744 // If a BoxInteger's input is a candidate, the box is a candidate. 1744 // If a BoxInt64's input is a candidate, the box is a candidate.
1745 BoxIntegerInstr* box = def->AsBoxInteger(); 1745 Definition* box_input = def->AsBoxInt64()->value()->definition();
1746 Definition* box_input = box->value()->definition();
1747 return selected_uint32_defs_->Contains(box_input->ssa_temp_index()); 1746 return selected_uint32_defs_->Contains(box_input->ssa_temp_index());
1748 } 1747 }
1749 // A right shift with an input outside of Uint32 range cannot be converted 1748 // A right shift with an input outside of Uint32 range cannot be converted
1750 // because we need the high bits. 1749 // because we need the high bits.
1751 if (def->IsShiftMintOp()) { 1750 if (def->IsShiftMintOp()) {
1752 ShiftMintOpInstr* op = def->AsShiftMintOp(); 1751 ShiftMintOpInstr* op = def->AsShiftMintOp();
1753 if (op->op_kind() == Token::kSHR) { 1752 if (op->op_kind() == Token::kSHR) {
1754 Definition* shift_input = op->left()->definition(); 1753 Definition* shift_input = op->left()->definition();
1755 ASSERT(shift_input != NULL); 1754 ASSERT(shift_input != NULL);
1756 Range* range = shift_input->range(); 1755 Range* range = shift_input->range();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 ASSERT(IsPotentialUint32Definition(def)); 1810 ASSERT(IsPotentialUint32Definition(def));
1812 // Should not see constant instructions. 1811 // Should not see constant instructions.
1813 ASSERT(!def->IsConstant()); 1812 ASSERT(!def->IsConstant());
1814 if (def->IsBinaryMintOp()) { 1813 if (def->IsBinaryMintOp()) {
1815 BinaryMintOpInstr* op = def->AsBinaryMintOp(); 1814 BinaryMintOpInstr* op = def->AsBinaryMintOp();
1816 Token::Kind op_kind = op->op_kind(); 1815 Token::Kind op_kind = op->op_kind();
1817 Value* left = op->left()->CopyWithType(); 1816 Value* left = op->left()->CopyWithType();
1818 Value* right = op->right()->CopyWithType(); 1817 Value* right = op->right()->CopyWithType();
1819 intptr_t deopt_id = op->DeoptimizationTarget(); 1818 intptr_t deopt_id = op->DeoptimizationTarget();
1820 return new(I) BinaryUint32OpInstr(op_kind, left, right, deopt_id); 1819 return new(I) BinaryUint32OpInstr(op_kind, left, right, deopt_id);
1821 } else if (def->IsBoxInteger()) { 1820 } else if (def->IsBoxInt64()) {
1822 BoxIntegerInstr* box = def->AsBoxInteger(); 1821 Value* value = def->AsBoxInt64()->value()->CopyWithType();
1823 Value* value = box->value()->CopyWithType();
1824 return new(I) BoxUint32Instr(value); 1822 return new(I) BoxUint32Instr(value);
1825 } else if (def->IsUnboxInteger()) { 1823 } else if (def->IsUnboxInt64()) {
1826 UnboxIntegerInstr* unbox = def->AsUnboxInteger(); 1824 UnboxInstr* unbox = def->AsUnboxInt64();
1827 Value* value = unbox->value()->CopyWithType(); 1825 Value* value = unbox->value()->CopyWithType();
1828 intptr_t deopt_id = unbox->deopt_id(); 1826 intptr_t deopt_id = unbox->DeoptimizationTarget();
1829 return new(I) UnboxUint32Instr(value, deopt_id); 1827 return new(I) UnboxUint32Instr(value, deopt_id);
1830 } else if (def->IsUnaryMintOp()) { 1828 } else if (def->IsUnaryMintOp()) {
1831 UnaryMintOpInstr* op = def->AsUnaryMintOp(); 1829 UnaryMintOpInstr* op = def->AsUnaryMintOp();
1832 Token::Kind op_kind = op->op_kind(); 1830 Token::Kind op_kind = op->op_kind();
1833 Value* value = op->value()->CopyWithType(); 1831 Value* value = op->value()->CopyWithType();
1834 intptr_t deopt_id = op->DeoptimizationTarget(); 1832 intptr_t deopt_id = op->DeoptimizationTarget();
1835 return new(I) UnaryUint32OpInstr(op_kind, value, deopt_id); 1833 return new(I) UnaryUint32OpInstr(op_kind, value, deopt_id);
1836 } else if (def->IsShiftMintOp()) { 1834 } else if (def->IsShiftMintOp()) {
1837 ShiftMintOpInstr* op = def->AsShiftMintOp(); 1835 ShiftMintOpInstr* op = def->AsShiftMintOp();
1838 Token::Kind op_kind = op->op_kind(); 1836 Token::Kind op_kind = op->op_kind();
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after
2901 } 2899 }
2902 2900
2903 2901
2904 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2902 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2905 InferRangeHelper(left()->definition()->range(), 2903 InferRangeHelper(left()->definition()->range(),
2906 right()->definition()->range(), 2904 right()->definition()->range(),
2907 range); 2905 range);
2908 } 2906 }
2909 2907
2910 2908
2911 void BoxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) { 2909 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2912 const Range* value_range = value()->definition()->range(); 2910 const Range* value_range = value()->definition()->range();
2913 if (!Range::IsUnknown(value_range)) { 2911 if (!Range::IsUnknown(value_range)) {
2914 *range = *value_range; 2912 *range = *value_range;
2915 } 2913 }
2916 } 2914 }
2917 2915
2918 2916
2919 void UnboxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) { 2917 void UnboxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2920 if (value()->definition()->Type()->ToCid() == kSmiCid) { 2918 if (value()->definition()->Type()->ToCid() == kSmiCid) {
2921 const Range* value_range = analysis->GetSmiRange(value()); 2919 const Range* value_range = analysis->GetSmiRange(value());
2922 if (!Range::IsUnknown(value_range)) { 2920 if (!Range::IsUnknown(value_range)) {
2923 *range = *value_range; 2921 *range = *value_range;
2924 } 2922 }
2925 } else if (value()->definition()->IsMintDefinition() || 2923 } else if (value()->definition()->IsMintDefinition() ||
2926 value()->definition()->IsInt32Definition()) { 2924 value()->definition()->IsInt32Definition()) {
2927 const Range* value_range = value()->definition()->range(); 2925 const Range* value_range = value()->definition()->range();
2928 if (!Range::IsUnknown(value_range)) { 2926 if (!Range::IsUnknown(value_range)) {
2929 *range = *value_range; 2927 *range = *value_range;
2930 } 2928 }
2931 } else if (value()->Type()->ToCid() == kSmiCid) { 2929 } else if (value()->Type()->ToCid() == kSmiCid) {
2932 *range = Range::Full(RangeBoundary::kRangeBoundarySmi); 2930 *range = Range::Full(RangeBoundary::kRangeBoundarySmi);
2933 } else { 2931 } else {
2934 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32); 2932 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32);
2935 } 2933 }
2936 } 2934 }
2937 2935
2938 2936
2937 void UnboxInt64Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2938 const Range* value_range = value()->definition()->range();
2939 if (value_range != NULL) {
2940 *range = *value_range;
2941 } else if (!value()->definition()->IsMintDefinition() &&
2942 (value()->definition()->Type()->ToCid() != kSmiCid)) {
2943 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64);
2944 }
2945 }
2946
2947
2939 void UnboxedIntConverterInstr::InferRange(RangeAnalysis* analysis, 2948 void UnboxedIntConverterInstr::InferRange(RangeAnalysis* analysis,
2940 Range* range) { 2949 Range* range) {
2941 ASSERT((from() == kUnboxedInt32) || 2950 ASSERT((from() == kUnboxedInt32) ||
2942 (from() == kUnboxedMint) || 2951 (from() == kUnboxedMint) ||
2943 (from() == kUnboxedUint32)); 2952 (from() == kUnboxedUint32));
2944 ASSERT((to() == kUnboxedInt32) || 2953 ASSERT((to() == kUnboxedInt32) ||
2945 (to() == kUnboxedMint) || 2954 (to() == kUnboxedMint) ||
2946 (to() == kUnboxedUint32)); 2955 (to() == kUnboxedUint32));
2947 const Range* value_range = value()->definition()->range(); 2956 const Range* value_range = value()->definition()->range();
2948 if (Range::IsUnknown(value_range)) { 2957 if (Range::IsUnknown(value_range)) {
2949 return; 2958 return;
2950 } 2959 }
2951 2960
2952 if (to() == kUnboxedUint32) { 2961 if (to() == kUnboxedUint32) {
2953 // TODO(vegorov): improve range information for unboxing to Uint32. 2962 // TODO(vegorov): improve range information for unboxing to Uint32.
2954 *range = Range( 2963 *range = Range(
2955 RangeBoundary::FromConstant(0), 2964 RangeBoundary::FromConstant(0),
2956 RangeBoundary::FromConstant(static_cast<int64_t>(kMaxUint32))); 2965 RangeBoundary::FromConstant(static_cast<int64_t>(kMaxUint32)));
2957 } else { 2966 } else {
2958 *range = *value_range; 2967 *range = *value_range;
2959 if (to() == kUnboxedInt32) { 2968 if (to() == kUnboxedInt32) {
2960 range->Clamp(RangeBoundary::kRangeBoundaryInt32); 2969 range->Clamp(RangeBoundary::kRangeBoundaryInt32);
2961 } 2970 }
2962 } 2971 }
2963 } 2972 }
2964 2973
2965 2974
2966 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2967 const Range* input_range = value()->definition()->range();
2968 if (input_range != NULL) {
2969 bool is_smi = input_range->Fits(RangeBoundary::kRangeBoundarySmi);
2970 set_is_smi(is_smi);
2971 // The output range is the same as the input range.
2972 *range = *input_range;
2973 }
2974 }
2975
2976
2977 void UnboxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2978 const Range* value_range = value()->definition()->range();
2979 if (value_range != NULL) {
2980 *range = *value_range;
2981 } else if (!value()->definition()->IsMintDefinition() &&
2982 (value()->definition()->Type()->ToCid() != kSmiCid)) {
2983 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64);
2984 }
2985 }
2986
2987
2988 bool CheckArrayBoundInstr::IsRedundant(const RangeBoundary& length) { 2975 bool CheckArrayBoundInstr::IsRedundant(const RangeBoundary& length) {
2989 Range* index_range = index()->definition()->range(); 2976 Range* index_range = index()->definition()->range();
2990 2977
2991 // Range of the index is unknown can't decide if the check is redundant. 2978 // Range of the index is unknown can't decide if the check is redundant.
2992 if (index_range == NULL) { 2979 if (index_range == NULL) {
2993 if (!(index()->BindsToConstant() && index()->BoundConstant().IsSmi())) { 2980 if (!(index()->BindsToConstant() && index()->BoundConstant().IsSmi())) {
2994 return false; 2981 return false;
2995 } 2982 }
2996 2983
2997 Range range; 2984 Range range;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3040 } 3027 }
3041 } while (CanonicalizeMaxBoundary(&max) || 3028 } while (CanonicalizeMaxBoundary(&max) ||
3042 CanonicalizeMinBoundary(&canonical_length)); 3029 CanonicalizeMinBoundary(&canonical_length));
3043 3030
3044 // Failed to prove that maximum is bounded with array length. 3031 // Failed to prove that maximum is bounded with array length.
3045 return false; 3032 return false;
3046 } 3033 }
3047 3034
3048 3035
3049 } // namespace dart 3036 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.cc ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698