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

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

Issue 564843002: Initial steps towards cleaning up integer arithmetic IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months 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
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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 RangeBoundary::kRangeBoundaryInt32) && 694 RangeBoundary::kRangeBoundaryInt32) &&
695 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(), 695 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(),
696 mint_op->left(), 696 mint_op->left(),
697 mint_op->right())) { 697 mint_op->right())) {
698 BinaryInt32OpInstr* int32_op = 698 BinaryInt32OpInstr* int32_op =
699 new BinaryInt32OpInstr(mint_op->op_kind(), 699 new BinaryInt32OpInstr(mint_op->op_kind(),
700 mint_op->left()->CopyWithType(), 700 mint_op->left()->CopyWithType(),
701 mint_op->right()->CopyWithType(), 701 mint_op->right()->CopyWithType(),
702 mint_op->DeoptimizationTarget()); 702 mint_op->DeoptimizationTarget());
703 int32_op->set_range(*mint_op->range()); 703 int32_op->set_range(*mint_op->range());
704 int32_op->set_overflow(false); 704 int32_op->set_can_overflow(false);
705 mint_op->ReplaceWith(int32_op, NULL); 705 mint_op->ReplaceWith(int32_op, NULL);
706 } 706 }
707 } 707 }
708 708
709 709
710 static void NarrowShiftMintOp(ShiftMintOpInstr* mint_op) { 710 static void NarrowShiftMintOp(ShiftMintOpInstr* mint_op) {
711 if (RangeUtils::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) && 711 if (RangeUtils::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) &&
712 RangeUtils::Fits(mint_op->left()->definition()->range(), 712 RangeUtils::Fits(mint_op->left()->definition()->range(),
713 RangeBoundary::kRangeBoundaryInt32) && 713 RangeBoundary::kRangeBoundaryInt32) &&
714 RangeUtils::Fits(mint_op->right()->definition()->range(), 714 RangeUtils::Fits(mint_op->right()->definition()->range(),
715 RangeBoundary::kRangeBoundaryInt32) && 715 RangeBoundary::kRangeBoundaryInt32) &&
716 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(), 716 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(),
717 mint_op->left(), 717 mint_op->left(),
718 mint_op->right())) { 718 mint_op->right())) {
719 BinaryInt32OpInstr* int32_op = 719 BinaryInt32OpInstr* int32_op =
720 new BinaryInt32OpInstr(mint_op->op_kind(), 720 new BinaryInt32OpInstr(mint_op->op_kind(),
721 mint_op->left()->CopyWithType(), 721 mint_op->left()->CopyWithType(),
722 mint_op->right()->CopyWithType(), 722 mint_op->right()->CopyWithType(),
723 mint_op->DeoptimizationTarget()); 723 mint_op->DeoptimizationTarget());
724 int32_op->set_range(*mint_op->range()); 724 int32_op->set_range(*mint_op->range());
725 int32_op->set_overflow(false); 725 int32_op->set_can_overflow(false);
726 mint_op->ReplaceWith(int32_op, NULL); 726 mint_op->ReplaceWith(int32_op, NULL);
727 } 727 }
728 } 728 }
729 729
730 730
731 void RangeAnalysis::NarrowMintToInt32() { 731 void RangeAnalysis::NarrowMintToInt32() {
732 for (intptr_t i = 0; i < binary_mint_ops_.length(); i++) { 732 for (intptr_t i = 0; i < binary_mint_ops_.length(); i++) {
733 NarrowBinaryMintOp(binary_mint_ops_[i]); 733 NarrowBinaryMintOp(binary_mint_ops_[i]);
734 } 734 }
735 735
(...skipping 1250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1986 1986
1987 1987
1988 void IfThenElseInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1988 void IfThenElseInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1989 const intptr_t min = Utils::Minimum(if_true_, if_false_); 1989 const intptr_t min = Utils::Minimum(if_true_, if_false_);
1990 const intptr_t max = Utils::Maximum(if_true_, if_false_); 1990 const intptr_t max = Utils::Maximum(if_true_, if_false_);
1991 *range = Range(RangeBoundary::FromConstant(min), 1991 *range = Range(RangeBoundary::FromConstant(min),
1992 RangeBoundary::FromConstant(max)); 1992 RangeBoundary::FromConstant(max));
1993 } 1993 }
1994 1994
1995 1995
1996 void BinarySmiOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1996 static RangeBoundary::RangeSize RepresentationToRangeSize(Representation r) {
1997 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the 1997 switch (r) {
1998 case kTagged:
1999 return RangeBoundary::kRangeBoundarySmi;
2000 case kUnboxedInt32:
2001 return RangeBoundary::kRangeBoundaryInt32;
2002 case kUnboxedMint:
2003 return RangeBoundary::kRangeBoundaryInt64;
2004 default:
2005 UNREACHABLE();
2006 return RangeBoundary::kRangeBoundarySmi;
2007 }
2008 }
2009
2010
2011 void BinaryIntegerOpInstr::InferRangeHelper(const Range* left_range,
2012 const Range* right_range,
2013 Range* range) {
2014 // TODO(vegorov): canonicalize BinaryIntegerOp to always have constant on the
1998 // right and a non-constant on the left. 2015 // right and a non-constant on the left.
1999 Definition* left_defn = left()->definition(); 2016 if (Range::IsUnknown(left_range) ||
2000 2017 Range::IsUnknown(right_range)) {
srdjan 2014/09/11 17:38:11 One line?
2001 const Range* left_range = analysis->GetSmiRange(left());
2002 const Range* right_range = analysis->GetSmiRange(right());
2003
2004 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
2005 return; 2018 return;
2006 } 2019 }
2007 2020
2008 Range::BinaryOp(op_kind(), 2021 Range::BinaryOp(op_kind(),
2009 left_range, 2022 left_range,
2010 right_range, 2023 right_range,
2011 left_defn, 2024 left()->definition(),
2012 range); 2025 range);
2013 ASSERT(!Range::IsUnknown(range)); 2026 ASSERT(!Range::IsUnknown(range));
2014 2027
2015 // Calculate overflowed status before clamping. 2028 const RangeBoundary::RangeSize range_size =
2016 const bool overflowed = range->min().LowerBound().OverflowedSmi() || 2029 RepresentationToRangeSize(representation());
2017 range->max().UpperBound().OverflowedSmi();
2018 set_overflow(overflowed);
2019 2030
2020 // Clamp value to be within smi range. 2031 // Calculate overflowed status before clamping if operation is
2021 range->Clamp(RangeBoundary::kRangeBoundarySmi); 2032 // not truncating.
2033 if (!is_truncating()) {
2034 set_can_overflow(!range->Fits(range_size));
2035 }
2036
2037 range->Clamp(range_size);
2022 } 2038 }
2023 2039
2024 2040
2041 void BinarySmiOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2042 // TODO(vegorov) completely remove this once GetSmiRange is eliminated.
2043 InferRangeHelper(analysis->GetSmiRange(left()),
2044 analysis->GetSmiRange(right()),
2045 range);
2046 }
2047
2048
2049 void BinaryInt32OpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2050 InferRangeHelper(analysis->GetSmiRange(left()),
2051 analysis->GetSmiRange(right()),
2052 range);
2053 }
2054
2055
2056 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2057 InferRangeHelper(left()->definition()->range(),
2058 right()->definition()->range(),
2059 range);
2060 }
2061
2062
2063 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2064 InferRangeHelper(left()->definition()->range(),
2065 right()->definition()->range(),
2066 range);
2067 }
2068
2069
2025 void BoxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) { 2070 void BoxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2026 const Range* value_range = value()->definition()->range(); 2071 const Range* value_range = value()->definition()->range();
2027 if (!Range::IsUnknown(value_range)) { 2072 if (!Range::IsUnknown(value_range)) {
2028 *range = *value_range; 2073 *range = *value_range;
2029 } 2074 }
2030 } 2075 }
2031 2076
2032 2077
2033 void UnboxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) { 2078 void UnboxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2034 if (value()->definition()->Type()->ToCid() == kSmiCid) { 2079 if (value()->definition()->Type()->ToCid() == kSmiCid) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 RangeBoundary::FromConstant(static_cast<int64_t>(kMaxUint32))); 2115 RangeBoundary::FromConstant(static_cast<int64_t>(kMaxUint32)));
2071 } else { 2116 } else {
2072 *range = *value_range; 2117 *range = *value_range;
2073 if (to() == kUnboxedInt32) { 2118 if (to() == kUnboxedInt32) {
2074 range->Clamp(RangeBoundary::kRangeBoundaryInt32); 2119 range->Clamp(RangeBoundary::kRangeBoundaryInt32);
2075 } 2120 }
2076 } 2121 }
2077 } 2122 }
2078 2123
2079 2124
2080 void BinaryInt32OpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2081 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the
2082 // right and a non-constant on the left.
2083 Definition* left_defn = left()->definition();
2084
2085 const Range* left_range = analysis->GetSmiRange(left());
2086 const Range* right_range = analysis->GetSmiRange(right());
2087
2088 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
2089 return;
2090 }
2091
2092 Range::BinaryOp(op_kind(),
2093 left_range,
2094 right_range,
2095 left_defn,
2096 range);
2097 ASSERT(!Range::IsUnknown(range));
2098
2099 // Calculate overflowed status before clamping.
2100 set_overflow(!range->Fits(RangeBoundary::kRangeBoundaryInt32));
2101
2102 // Clamp value to be within smi range.
2103 range->Clamp(RangeBoundary::kRangeBoundaryInt32);
2104 }
2105
2106 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2107 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on
2108 // the right and a non-constant on the left.
2109 Definition* left_defn = left()->definition();
2110
2111 const Range* left_range = left_defn->range();
2112 const Range* right_range = right()->definition()->range();
2113
2114 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
2115 return;
2116 }
2117
2118 Range::BinaryOp(op_kind(),
2119 left_range,
2120 right_range,
2121 left_defn,
2122 range);
2123 ASSERT(!Range::IsUnknown(range));
2124
2125 // Calculate overflowed status before clamping.
2126 set_can_overflow(!range->Fits(RangeBoundary::kRangeBoundaryInt64));
2127
2128 // Clamp value to be within mint range.
2129 range->Clamp(RangeBoundary::kRangeBoundaryInt64);
2130 }
2131
2132
2133 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2134 Definition* left_defn = left()->definition();
2135
2136 const Range* left_range = left_defn->range();
2137 const Range* right_range = right()->definition()->range();
2138
2139 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
2140 return;
2141 }
2142
2143 Range::BinaryOp(op_kind(),
2144 left_range,
2145 right_range,
2146 left_defn,
2147 range);
2148 ASSERT(!Range::IsUnknown(range));
2149
2150 // Calculate overflowed status before clamping.
2151 const bool overflowed = range->min().LowerBound().OverflowedMint() ||
2152 range->max().UpperBound().OverflowedMint();
2153 set_can_overflow(overflowed);
2154
2155 // Clamp value to be within mint range.
2156 range->Clamp(RangeBoundary::kRangeBoundaryInt64);
2157 }
2158
2159
2160 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2125 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2161 const Range* input_range = value()->definition()->range(); 2126 const Range* input_range = value()->definition()->range();
2162 if (input_range != NULL) { 2127 if (input_range != NULL) {
2163 bool is_smi = input_range->Fits(RangeBoundary::kRangeBoundarySmi); 2128 bool is_smi = input_range->Fits(RangeBoundary::kRangeBoundarySmi);
2164 set_is_smi(is_smi); 2129 set_is_smi(is_smi);
2165 // The output range is the same as the input range. 2130 // The output range is the same as the input range.
2166 *range = *input_range; 2131 *range = *input_range;
2167 } 2132 }
2168 } 2133 }
2169 2134
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2225 } 2190 }
2226 } while (CanonicalizeMaxBoundary(&max) || 2191 } while (CanonicalizeMaxBoundary(&max) ||
2227 CanonicalizeMinBoundary(&canonical_length)); 2192 CanonicalizeMinBoundary(&canonical_length));
2228 2193
2229 // Failed to prove that maximum is bounded with array length. 2194 // Failed to prove that maximum is bounded with array length.
2230 return false; 2195 return false;
2231 } 2196 }
2232 2197
2233 2198
2234 } // namespace dart 2199 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698