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

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

Issue 484693002: Don't check for reaching type in the RangeAnalysis::GetRange. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix UnboxIntegerInstr::InferRange Created 6 years, 4 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
« no previous file with comments | « runtime/vm/flow_graph_range_analysis.h ('k') | no next file » | 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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 UNREACHABLE(); 192 UNREACHABLE();
193 return NULL; 193 return NULL;
194 } 194 }
195 } 195 }
196 196
197 197
198 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Value* use, 198 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Value* use,
199 Definition* defn, 199 Definition* defn,
200 Range* constraint_range, 200 Range* constraint_range,
201 Instruction* after) { 201 Instruction* after) {
202 // Avoid constraining inside the dead code.
203 if (!use->IsSmiValue()) return NULL;
204
205 // No need to constrain constants. 202 // No need to constrain constants.
206 if (defn->IsConstant()) return NULL; 203 if (defn->IsConstant()) return NULL;
207 204
208 // Check if the value is already constrained to avoid inserting duplicated 205 // Check if the value is already constrained to avoid inserting duplicated
209 // constraints. 206 // constraints.
210 ConstraintInstr* constraint = after->next()->AsConstraint(); 207 ConstraintInstr* constraint = after->next()->AsConstraint();
211 while (constraint != NULL) { 208 while (constraint != NULL) {
212 if ((constraint->value()->definition() == defn) && 209 if ((constraint->value()->definition() == defn) &&
213 constraint->constraint()->Equals(constraint_range)) { 210 constraint->constraint()->Equals(constraint_range)) {
214 return NULL; 211 return NULL;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 for (intptr_t i = 0; i < values_.length(); i++) { 312 for (intptr_t i = 0; i < values_.length(); i++) {
316 InsertConstraintsFor(values_[i]); 313 InsertConstraintsFor(values_[i]);
317 } 314 }
318 315
319 for (intptr_t i = 0; i < constraints_.length(); i++) { 316 for (intptr_t i = 0; i < constraints_.length(); i++) {
320 InsertConstraintsFor(constraints_[i]); 317 InsertConstraintsFor(constraints_[i]);
321 } 318 }
322 } 319 }
323 320
324 321
325 const Range* RangeAnalysis::GetRange(Value* value) const { 322 const Range* RangeAnalysis::GetSmiRange(Value* value) const {
326 Definition* defn = value->definition(); 323 Definition* defn = value->definition();
327 const Range* range = defn->range(); 324 const Range* range = defn->range();
328 325
329 if ((range == NULL) && 326 if ((range == NULL) && (defn->Type()->ToCid() != kSmiCid)) {
330 (value->Type()->ToCid() == kSmiCid) &&
331 (defn->Type()->ToCid() != kSmiCid)) {
332 // Type propagator determined that reaching type for this use is Smi. 327 // Type propagator determined that reaching type for this use is Smi.
333 // However the definition itself is not a smi-definition and 328 // However the definition itself is not a smi-definition and
334 // thus it will never have range assigned to it. Just return the widest 329 // thus it will never have range assigned to it. Just return the widest
335 // range possible for this value. 330 // range possible for this value.
336 // We don't need to handle kMintCid here because all external mints 331 // We don't need to handle kMintCid here because all external mints
337 // (e.g. results of loads or function call) can be used only after they 332 // (e.g. results of loads or function call) can be used only after they
338 // pass through UnboxIntegerInstr which is considered as mint-definition 333 // pass through UnboxIntegerInstr which is considered as mint-definition
339 // and will have a range assigned to it. 334 // and will have a range assigned to it.
340 // Note: that we can't return NULL here because it is used as lattice's 335 // Note: that we can't return NULL here because it is used as lattice's
341 // bottom element to indicate that the range was not computed *yet*. 336 // bottom element to indicate that the range was not computed *yet*.
(...skipping 1414 matching lines...) Expand 10 before | Expand all | Expand 10 after
1756 } 1751 }
1757 1752
1758 return limit; 1753 return limit;
1759 } 1754 }
1760 1755
1761 1756
1762 void PhiInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1757 void PhiInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1763 ASSERT(Type()->ToCid() == kSmiCid); 1758 ASSERT(Type()->ToCid() == kSmiCid);
1764 for (intptr_t i = 0; i < InputCount(); i++) { 1759 for (intptr_t i = 0; i < InputCount(); i++) {
1765 Value* input = InputAt(i); 1760 Value* input = InputAt(i);
1766 Join(range, input->definition(), analysis->GetRange(input)); 1761 Join(range, input->definition(), analysis->GetSmiRange(input));
1767 } 1762 }
1768 1763
1769 BlockEntryInstr* phi_block = GetBlock(); 1764 BlockEntryInstr* phi_block = GetBlock();
1770 range->set_min(EnsureAcyclicSymbol( 1765 range->set_min(EnsureAcyclicSymbol(
1771 phi_block, range->min(), RangeBoundary::MinSmi())); 1766 phi_block, range->min(), RangeBoundary::MinSmi()));
1772 range->set_max(EnsureAcyclicSymbol( 1767 range->set_max(EnsureAcyclicSymbol(
1773 phi_block, range->max(), RangeBoundary::MaxSmi())); 1768 phi_block, range->max(), RangeBoundary::MaxSmi()));
1774 } 1769 }
1775 1770
1776 1771
1777 void ConstantInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1772 void ConstantInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1778 if (value_.IsSmi()) { 1773 if (value_.IsSmi()) {
1779 int64_t value = Smi::Cast(value_).Value(); 1774 int64_t value = Smi::Cast(value_).Value();
1780 *range = Range(RangeBoundary::FromConstant(value), 1775 *range = Range(RangeBoundary::FromConstant(value),
1781 RangeBoundary::FromConstant(value)); 1776 RangeBoundary::FromConstant(value));
1782 } else if (value_.IsMint()) { 1777 } else if (value_.IsMint()) {
1783 int64_t value = Mint::Cast(value_).value(); 1778 int64_t value = Mint::Cast(value_).value();
1784 *range = Range(RangeBoundary::FromConstant(value), 1779 *range = Range(RangeBoundary::FromConstant(value),
1785 RangeBoundary::FromConstant(value)); 1780 RangeBoundary::FromConstant(value));
1786 } else { 1781 } else {
1787 // Only Smi and Mint supported. 1782 // Only Smi and Mint supported.
1788 UNREACHABLE(); 1783 UNREACHABLE();
1789 } 1784 }
1790 } 1785 }
1791 1786
1792 1787
1793 void ConstraintInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1788 void ConstraintInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1794 // Only constraining smi values. 1789 const Range* value_range = analysis->GetSmiRange(value());
1795 ASSERT(value()->IsSmiValue());
1796
1797 const Range* value_range = analysis->GetRange(value());
1798 if (Range::IsUnknown(value_range)) { 1790 if (Range::IsUnknown(value_range)) {
1799 return; 1791 return;
1800 } 1792 }
1801 1793
1802 // TODO(vegorov) check if precision of the analysis can be improved by 1794 // TODO(vegorov) check if precision of the analysis can be improved by
1803 // recognizing intersections of the form: 1795 // recognizing intersections of the form:
1804 // 1796 //
1805 // (..., S+x] ^ [S+x, ...) = [S+x, S+x] 1797 // (..., S+x] ^ [S+x, ...) = [S+x, S+x]
1806 // 1798 //
1807 Range result = value_range->Intersect(constraint()); 1799 Range result = value_range->Intersect(constraint());
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1896 *range = Range(RangeBoundary::FromConstant(min), 1888 *range = Range(RangeBoundary::FromConstant(min),
1897 RangeBoundary::FromConstant(max)); 1889 RangeBoundary::FromConstant(max));
1898 } 1890 }
1899 1891
1900 1892
1901 void BinarySmiOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1893 void BinarySmiOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1902 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the 1894 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the
1903 // right and a non-constant on the left. 1895 // right and a non-constant on the left.
1904 Definition* left_defn = left()->definition(); 1896 Definition* left_defn = left()->definition();
1905 1897
1906 const Range* left_range = analysis->GetRange(left()); 1898 const Range* left_range = analysis->GetSmiRange(left());
1907 const Range* right_range = analysis->GetRange(right()); 1899 const Range* right_range = analysis->GetSmiRange(right());
1908 1900
1909 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) { 1901 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
1910 return; 1902 return;
1911 } 1903 }
1912 1904
1913 Range::BinaryOp(op_kind(), 1905 Range::BinaryOp(op_kind(),
1914 left_range, 1906 left_range,
1915 right_range, 1907 right_range,
1916 left_defn, 1908 left_defn,
1917 range); 1909 range);
1918 ASSERT(!Range::IsUnknown(range)); 1910 ASSERT(!Range::IsUnknown(range));
1919 1911
1920 // Calculate overflowed status before clamping. 1912 // Calculate overflowed status before clamping.
1921 const bool overflowed = range->min().LowerBound().OverflowedSmi() || 1913 const bool overflowed = range->min().LowerBound().OverflowedSmi() ||
1922 range->max().UpperBound().OverflowedSmi(); 1914 range->max().UpperBound().OverflowedSmi();
1923 set_overflow(overflowed); 1915 set_overflow(overflowed);
1924 1916
1925 // Clamp value to be within smi range. 1917 // Clamp value to be within smi range.
1926 range->Clamp(RangeBoundary::kRangeBoundarySmi); 1918 range->Clamp(RangeBoundary::kRangeBoundarySmi);
1927 } 1919 }
1928 1920
1929 1921
1930 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1922 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1931 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on 1923 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on
1932 // the right and a non-constant on the left. 1924 // the right and a non-constant on the left.
1933 Definition* left_defn = left()->definition(); 1925 Definition* left_defn = left()->definition();
1934 1926
1935 const Range* left_range = analysis->GetRange(left()); 1927 const Range* left_range = left_defn->range();
1936 const Range* right_range = analysis->GetRange(right()); 1928 const Range* right_range = right()->definition()->range();
1937 1929
1938 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) { 1930 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
1939 return; 1931 return;
1940 } 1932 }
1941 1933
1942 Range::BinaryOp(op_kind(), 1934 Range::BinaryOp(op_kind(),
1943 left_range, 1935 left_range,
1944 right_range, 1936 right_range,
1945 left_defn, 1937 left_defn,
1946 range); 1938 range);
1947 ASSERT(!Range::IsUnknown(range)); 1939 ASSERT(!Range::IsUnknown(range));
1948 1940
1949 // Calculate overflowed status before clamping. 1941 // Calculate overflowed status before clamping.
1950 const bool overflowed = range->min().LowerBound().OverflowedMint() || 1942 const bool overflowed = range->min().LowerBound().OverflowedMint() ||
1951 range->max().UpperBound().OverflowedMint(); 1943 range->max().UpperBound().OverflowedMint();
1952 set_can_overflow(overflowed); 1944 set_can_overflow(overflowed);
1953 1945
1954 // Clamp value to be within mint range. 1946 // Clamp value to be within mint range.
1955 range->Clamp(RangeBoundary::kRangeBoundaryInt64); 1947 range->Clamp(RangeBoundary::kRangeBoundaryInt64);
1956 } 1948 }
1957 1949
1958 1950
1959 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1951 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1960 Definition* left_defn = left()->definition(); 1952 Definition* left_defn = left()->definition();
1961 1953
1962 const Range* left_range = analysis->GetRange(left()); 1954 const Range* left_range = left_defn->range();
1963 const Range* right_range = analysis->GetRange(right()); 1955 const Range* right_range = right()->definition()->range();
1964 1956
1965 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) { 1957 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
1966 return; 1958 return;
1967 } 1959 }
1968 1960
1969 Range::BinaryOp(op_kind(), 1961 Range::BinaryOp(op_kind(),
1970 left_range, 1962 left_range,
1971 right_range, 1963 right_range,
1972 left_defn, 1964 left_defn,
1973 range); 1965 range);
1974 ASSERT(!Range::IsUnknown(range)); 1966 ASSERT(!Range::IsUnknown(range));
1975 1967
1976 // Calculate overflowed status before clamping. 1968 // Calculate overflowed status before clamping.
1977 const bool overflowed = range->min().LowerBound().OverflowedMint() || 1969 const bool overflowed = range->min().LowerBound().OverflowedMint() ||
1978 range->max().UpperBound().OverflowedMint(); 1970 range->max().UpperBound().OverflowedMint();
1979 set_can_overflow(overflowed); 1971 set_can_overflow(overflowed);
1980 1972
1981 // Clamp value to be within mint range. 1973 // Clamp value to be within mint range.
1982 range->Clamp(RangeBoundary::kRangeBoundaryInt64); 1974 range->Clamp(RangeBoundary::kRangeBoundaryInt64);
1983 } 1975 }
1984 1976
1985 1977
1986 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1978 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1987 const Range* input_range = analysis->GetRange(value()); 1979 const Range* input_range = value()->definition()->range();
1988 if (input_range != NULL) { 1980 if (input_range != NULL) {
1989 bool is_smi = !input_range->min().LowerBound().OverflowedSmi() && 1981 bool is_smi = !input_range->min().LowerBound().OverflowedSmi() &&
1990 !input_range->max().UpperBound().OverflowedSmi(); 1982 !input_range->max().UpperBound().OverflowedSmi();
1991 set_is_smi(is_smi); 1983 set_is_smi(is_smi);
1992 // The output range is the same as the input range. 1984 // The output range is the same as the input range.
1993 *range = *input_range; 1985 *range = *input_range;
1994 } 1986 }
1995 } 1987 }
1996 1988
1997 1989
1998 void UnboxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1990 void UnboxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1999 const Range* value_range = analysis->GetRange(value()); 1991 const Range* value_range = value()->definition()->range();
2000 if (value_range != NULL) { 1992 if (value_range != NULL) {
2001 *range = *value_range; 1993 *range = *value_range;
2002 } else if (!value()->definition()->IsMintDefinition() && 1994 } else if (!value()->definition()->IsMintDefinition() &&
2003 (value()->Type()->ToCid() != kSmiCid)) { 1995 (value()->definition()->Type()->ToCid() != kSmiCid)) {
2004 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64); 1996 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64);
2005 } 1997 }
2006 } 1998 }
2007 1999
2008 2000
2009 bool CheckArrayBoundInstr::IsRedundant(const RangeBoundary& length) { 2001 bool CheckArrayBoundInstr::IsRedundant(const RangeBoundary& length) {
2010 Range* index_range = index()->definition()->range(); 2002 Range* index_range = index()->definition()->range();
2011 2003
2012 // Range of the index is unknown can't decide if the check is redundant. 2004 // Range of the index is unknown can't decide if the check is redundant.
2013 if (index_range == NULL) { 2005 if (index_range == NULL) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2052 } 2044 }
2053 } while (CanonicalizeMaxBoundary(&max) || 2045 } while (CanonicalizeMaxBoundary(&max) ||
2054 CanonicalizeMinBoundary(&canonical_length)); 2046 CanonicalizeMinBoundary(&canonical_length));
2055 2047
2056 // Failed to prove that maximum is bounded with array length. 2048 // Failed to prove that maximum is bounded with array length.
2057 return false; 2049 return false;
2058 } 2050 }
2059 2051
2060 2052
2061 } // namespace dart 2053 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_range_analysis.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698