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

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

Issue 10972003: Fix convergence issues in range analysis. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address comments Created 8 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
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | tests/language/range_analysis_test.dart » ('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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flow_graph_allocator.h" 9 #include "vm/flow_graph_allocator.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 1852 matching lines...) Expand 10 before | Expand all | Expand 10 after
1863 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 1863 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
1864 Value* value = it.CurrentValue(); 1864 Value* value = it.CurrentValue();
1865 value->set_instruction(instr); 1865 value->set_instruction(instr);
1866 value->set_use_index(use_index++); 1866 value->set_use_index(use_index++);
1867 value->AddToEnvUseList(); 1867 value->AddToEnvUseList();
1868 } 1868 }
1869 instr->env()->outer_ = copy; 1869 instr->env()->outer_ = copy;
1870 } 1870 }
1871 1871
1872 1872
1873 bool Definition::InferRange() { 1873 RangeBoundary RangeBoundary::LowerBound() const {
1874 if (IsConstant()) return *this;
1875 if (symbol()->range() == NULL) return MinSmi();
1876 return Add(symbol()->range()->min().LowerBound(),
1877 RangeBoundary::FromConstant(offset_),
1878 MinSmi());
1879 }
1880
1881
1882 RangeBoundary RangeBoundary::UpperBound() const {
1883 if (IsConstant()) return *this;
1884 if (symbol()->range() == NULL) return MaxSmi();
1885 return Add(symbol()->range()->max().UpperBound(),
1886 RangeBoundary::FromConstant(offset_),
1887 MaxSmi());
1888 }
1889
1890
1891 bool Definition::InferRange(RangeOperator op) {
1874 ASSERT(GetPropagatedCid() == kSmiCid); // Has meaning only for smis. 1892 ASSERT(GetPropagatedCid() == kSmiCid); // Has meaning only for smis.
1875 if (range_ == NULL) { 1893 if (range_ == NULL) {
1876 range_ = Range::Unknown(); 1894 range_ = Range::Unknown();
1877 return true; 1895 return true;
1878 } 1896 }
1879 return false; 1897 return false;
1880 } 1898 }
1881 1899
1882 1900
1883 bool ConstantInstr::InferRange() { 1901 bool ConstantInstr::InferRange(RangeOperator op) {
1884 ASSERT(value_.IsSmi()); 1902 ASSERT(value_.IsSmi());
1885 if (range_ == NULL) { 1903 if (range_ == NULL) {
1886 intptr_t value = Smi::Cast(value_).Value(); 1904 intptr_t value = Smi::Cast(value_).Value();
1887 range_ = new Range(RangeBoundary::FromConstant(value), 1905 range_ = new Range(RangeBoundary::FromConstant(value),
1888 RangeBoundary::FromConstant(value)); 1906 RangeBoundary::FromConstant(value));
1889 return true; 1907 return true;
1890 } 1908 }
1891 return false; 1909 return false;
1892 } 1910 }
1893 1911
1894 1912
1895 RangeBoundary RangeBoundary::LowerBound() const { 1913 bool ConstraintInstr::InferRange(RangeOperator op) {
1896 if (IsConstant()) return *this;
1897 if (symbol()->range() == NULL) return MinSmi();
1898 return Add(symbol()->range()->min().LowerBound(),
1899 RangeBoundary::FromConstant(offset_),
1900 MinSmi());
1901 }
1902
1903
1904 RangeBoundary RangeBoundary::UpperBound() const {
1905 if (IsConstant()) return *this;
1906 if (symbol()->range() == NULL) return MaxSmi();
1907 return Add(symbol()->range()->max().UpperBound(),
1908 RangeBoundary::FromConstant(offset_),
1909 MaxSmi());
1910 }
1911
1912
1913 bool ConstraintInstr::InferRange() {
1914 Range* value_range = value()->definition()->range(); 1914 Range* value_range = value()->definition()->range();
1915 1915
1916 // Compute intersection of constraint and value ranges. 1916 // Compute intersection of constraint and value ranges.
1917 return Range::Update(&range_, 1917 return Range::Update(&range_,
1918 RangeBoundary::Max(Range::ConstantMin(value_range), 1918 RangeBoundary::Max(Range::ConstantMin(value_range),
1919 Range::ConstantMin(constraint())), 1919 Range::ConstantMin(constraint())),
1920 RangeBoundary::Min(Range::ConstantMax(value_range), 1920 RangeBoundary::Min(Range::ConstantMax(value_range),
1921 Range::ConstantMax(constraint()))); 1921 Range::ConstantMax(constraint())));
1922 } 1922 }
1923 1923
1924 1924
1925 bool PhiInstr::InferRange() { 1925 bool PhiInstr::InferRange(RangeOperator op) {
1926 RangeBoundary new_min; 1926 RangeBoundary new_min;
1927 RangeBoundary new_max; 1927 RangeBoundary new_max;
1928 1928
1929 bool has_inputs_without_range = false;
1930 for (intptr_t i = 0; i < InputCount(); i++) { 1929 for (intptr_t i = 0; i < InputCount(); i++) {
1931 Range* input_range = InputAt(i)->definition()->range(); 1930 Range* input_range = InputAt(i)->definition()->range();
1932 if (input_range == NULL) { 1931 if (input_range == NULL) {
1933 has_inputs_without_range = true;
1934 continue; 1932 continue;
1935 } 1933 }
1936 1934
1937 if (new_min.IsUnknown()) { 1935 if (new_min.IsUnknown()) {
1938 new_min = Range::ConstantMin(input_range); 1936 new_min = Range::ConstantMin(input_range);
1939 } else { 1937 } else {
1940 new_min = RangeBoundary::Min(new_min, Range::ConstantMin(input_range)); 1938 new_min = RangeBoundary::Min(new_min, Range::ConstantMin(input_range));
1941 } 1939 }
1942 1940
1943 if (new_max.IsUnknown()) { 1941 if (new_max.IsUnknown()) {
1944 new_max = Range::ConstantMax(input_range); 1942 new_max = Range::ConstantMax(input_range);
1945 } else { 1943 } else {
1946 new_max = RangeBoundary::Max(new_max, Range::ConstantMax(input_range)); 1944 new_max = RangeBoundary::Max(new_max, Range::ConstantMax(input_range));
1947 } 1945 }
1948 } 1946 }
1949 1947
1950 ASSERT(new_min.IsUnknown() == new_max.IsUnknown()); 1948 ASSERT(new_min.IsUnknown() == new_max.IsUnknown());
1951 if (new_min.IsUnknown()) { 1949 if (new_min.IsUnknown()) {
1952 ASSERT(range_ == NULL); 1950 range_ = Range::Unknown();
1953 return false; 1951 return false;
1954 } 1952 }
1955 1953
1956 if ((range_ != NULL) && !has_inputs_without_range_) { 1954 if (op == Definition::kRangeWiden) {
1957 // If phi's range is growing widen it in the direction of growth to 1955 // Apply widening operator.
1958 // speedup convergence.
1959 new_min = RangeBoundary::WidenMin(range_->min(), new_min); 1956 new_min = RangeBoundary::WidenMin(range_->min(), new_min);
1960 new_max = RangeBoundary::WidenMax(range_->max(), new_max); 1957 new_max = RangeBoundary::WidenMax(range_->max(), new_max);
1958 } else if (op == Definition::kRangeNarrow) {
1959 // Apply narrowing operator.
1960 new_min = RangeBoundary::NarrowMin(range_->min(), new_min);
1961 new_max = RangeBoundary::NarrowMax(range_->max(), new_max);
1961 } 1962 }
1962 has_inputs_without_range_ = has_inputs_without_range;
1963 1963
1964 return Range::Update(&range_, new_min, new_max); 1964 return Range::Update(&range_, new_min, new_max);
1965 } 1965 }
1966 1966
1967 1967
1968 bool BinarySmiOpInstr::InferRange() { 1968 bool BinarySmiOpInstr::InferRange(RangeOperator op) {
1969 Range* left_range = left()->definition()->range(); 1969 Range* left_range = left()->definition()->range();
1970 Range* right_range = right()->definition()->range(); 1970 Range* right_range = right()->definition()->range();
1971 1971
1972 if ((left_range == NULL) || (right_range == NULL)) { 1972 if ((left_range == NULL) || (right_range == NULL)) {
1973 return Range::Update(&range_, 1973 return Range::Update(&range_,
1974 RangeBoundary::MinSmi(), 1974 RangeBoundary::MinSmi(),
1975 RangeBoundary::MaxSmi()); 1975 RangeBoundary::MaxSmi());
1976 } 1976 }
1977 1977
1978 RangeBoundary new_min; 1978 RangeBoundary new_min;
(...skipping 24 matching lines...) Expand all
2003 default: 2003 default:
2004 if (range_ == NULL) { 2004 if (range_ == NULL) {
2005 range_ = Range::Unknown(); 2005 range_ = Range::Unknown();
2006 return true; 2006 return true;
2007 } 2007 }
2008 return false; 2008 return false;
2009 } 2009 }
2010 2010
2011 ASSERT(!new_min.IsUnknown() && !new_max.IsUnknown()); 2011 ASSERT(!new_min.IsUnknown() && !new_max.IsUnknown());
2012 set_overflow(new_min.Overflowed() || new_max.Overflowed()); 2012 set_overflow(new_min.Overflowed() || new_max.Overflowed());
2013
2014 if (op == Definition::kRangeNarrow) {
2015 new_min = new_min.Clamp();
2016 new_max = new_max.Clamp();
2017 }
2018
2013 return Range::Update(&range_, new_min, new_max); 2019 return Range::Update(&range_, new_min, new_max);
2014 } 2020 }
2015 2021
2016 2022
2017 #undef __ 2023 #undef __
2018 2024
2019 } // namespace dart 2025 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | tests/language/range_analysis_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698