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

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

Issue 10960014: Implement range analysis for smi values. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: cleanup 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
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"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/flow_graph_optimizer.h" 12 #include "vm/flow_graph_optimizer.h"
13 #include "vm/locations.h" 13 #include "vm/locations.h"
14 #include "vm/object.h" 14 #include "vm/object.h"
15 #include "vm/object_store.h" 15 #include "vm/object_store.h"
16 #include "vm/os.h" 16 #include "vm/os.h"
17 #include "vm/scopes.h" 17 #include "vm/scopes.h"
18 #include "vm/stub_code.h" 18 #include "vm/stub_code.h"
19 #include "vm/symbols.h" 19 #include "vm/symbols.h"
20 20
21 #include "vm/il_printer.h"
Florian Schneider 2012/09/21 08:56:44 Why this include?
Kevin Millikin (Google) 2012/09/21 08:59:33 Is there any reason to split this out from all the
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Debugging leftover. Removing.
22
21 namespace dart { 23 namespace dart {
22 24
23 DECLARE_FLAG(bool, enable_type_checks); 25 DECLARE_FLAG(bool, enable_type_checks);
24 26
25 27
26 Definition::Definition() 28 Definition::Definition()
27 : temp_index_(-1), 29 : temp_index_(-1),
28 ssa_temp_index_(-1), 30 ssa_temp_index_(-1),
29 propagated_type_(AbstractType::Handle()), 31 propagated_type_(AbstractType::Handle()),
30 propagated_cid_(kIllegalCid), 32 propagated_cid_(kIllegalCid),
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 definition()->set_input_use_list(this); 565 definition()->set_input_use_list(this);
564 } 566 }
565 567
566 568
567 void Value::AddToEnvUseList() { 569 void Value::AddToEnvUseList() {
568 set_next_use(definition()->env_use_list()); 570 set_next_use(definition()->env_use_list());
569 definition()->set_env_use_list(this); 571 definition()->set_env_use_list(this);
570 } 572 }
571 573
572 574
575 void Value::RemoveFromInputUseList() {
576 if (definition_->input_use_list() == this) {
577 definition_->set_input_use_list(next_use_);
578 return;
579 }
580
581 Value* prev = definition_->input_use_list();
582 while (prev->next_use_ != this) {
583 prev = prev->next_use_;
584 }
585 prev->next_use_ = next_use_;
586 definition_ = NULL;
587 }
588
589
573 void Definition::ReplaceUsesWith(Definition* other) { 590 void Definition::ReplaceUsesWith(Definition* other) {
574 ASSERT(other != NULL); 591 ASSERT(other != NULL);
575 ASSERT(this != other); 592 ASSERT(this != other);
576 while (input_use_list_ != NULL) { 593 while (input_use_list_ != NULL) {
577 Value* current = input_use_list_; 594 Value* current = input_use_list_;
578 input_use_list_ = input_use_list_->next_use(); 595 input_use_list_ = input_use_list_->next_use();
579 current->set_definition(other); 596 current->set_definition(other);
580 current->AddToInputUseList(); 597 current->AddToInputUseList();
581 } 598 }
582 while (env_use_list_ != NULL) { 599 while (env_use_list_ != NULL) {
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 } 1221 }
1205 1222
1206 1223
1207 bool BinarySmiOpInstr::CanDeoptimize() const { 1224 bool BinarySmiOpInstr::CanDeoptimize() const {
1208 switch (op_kind()) { 1225 switch (op_kind()) {
1209 case Token::kBIT_AND: 1226 case Token::kBIT_AND:
1210 case Token::kBIT_OR: 1227 case Token::kBIT_OR:
1211 case Token::kBIT_XOR: 1228 case Token::kBIT_XOR:
1212 return false; 1229 return false;
1213 default: 1230 default:
1214 return true; 1231 return overflow_;
1215 } 1232 }
1216 } 1233 }
1217 1234
1218 1235
1219 RawAbstractType* BinaryMintOpInstr::CompileType() const { 1236 RawAbstractType* BinaryMintOpInstr::CompileType() const {
1220 return Type::MintType(); 1237 return Type::MintType();
1221 } 1238 }
1222 1239
1223 1240
1224 intptr_t BinaryMintOpInstr::ResultCid() const { 1241 intptr_t BinaryMintOpInstr::ResultCid() const {
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1429 LocationSummary* ParallelMoveInstr::MakeLocationSummary() const { 1446 LocationSummary* ParallelMoveInstr::MakeLocationSummary() const {
1430 return NULL; 1447 return NULL;
1431 } 1448 }
1432 1449
1433 1450
1434 void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1451 void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1435 UNREACHABLE(); 1452 UNREACHABLE();
1436 } 1453 }
1437 1454
1438 1455
1456 LocationSummary* ConstraintInstr::MakeLocationSummary() const {
1457 UNREACHABLE();
1458 return NULL;
1459 }
1460
1461
1462 void ConstraintInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1463 UNREACHABLE();
1464 }
1465
1439 LocationSummary* ThrowInstr::MakeLocationSummary() const { 1466 LocationSummary* ThrowInstr::MakeLocationSummary() const {
1440 return new LocationSummary(0, 0, LocationSummary::kCall); 1467 return new LocationSummary(0, 0, LocationSummary::kCall);
1441 } 1468 }
1442 1469
1443 1470
1444 1471
1445 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1472 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1446 compiler->GenerateCallRuntime(token_pos(), 1473 compiler->GenerateCallRuntime(token_pos(),
1447 kThrowRuntimeEntry, 1474 kThrowRuntimeEntry,
1448 locs()); 1475 locs());
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
1836 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 1863 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
1837 Value* value = it.CurrentValue(); 1864 Value* value = it.CurrentValue();
1838 value->set_instruction(instr); 1865 value->set_instruction(instr);
1839 value->set_use_index(use_index++); 1866 value->set_use_index(use_index++);
1840 value->AddToEnvUseList(); 1867 value->AddToEnvUseList();
1841 } 1868 }
1842 instr->env()->outer_ = copy; 1869 instr->env()->outer_ = copy;
1843 } 1870 }
1844 1871
1845 1872
1873 Range* Instruction::range() {
1874 if (range_ == NULL) {
1875 range_ = Range::Unknown();
1876 }
1877 return range_;
1878 }
1879
1880
1881 RangeBoundary RangeBoundary::LowerBound() const {
1882 if (IsConstant()) return *this;
1883 if (symbol()->range() == NULL) return MinSmi();
1884 return Add(symbol()->range()->min().LowerBound(),
1885 RangeBoundary::FromConstant(offs_),
1886 MinSmi());
1887 }
1888
1889
1890 RangeBoundary RangeBoundary::UpperBound() const {
1891 if (IsConstant()) return *this;
1892 if (symbol()->range() == NULL) return MaxSmi();
1893 return Add(symbol()->range()->max().UpperBound(),
1894 RangeBoundary::FromConstant(offs_),
1895 MaxSmi());
1896 }
1897
1898
1899 bool ConstraintInstr::InferRange() {
1900 Range* value_range = value()->definition()->range();
1901
1902 // Compute intersection of constraint and value ranges.
1903 return Range::Update(&range_,
1904 RangeBoundary::Max(Range::ConstantMin(value_range),
1905 Range::ConstantMin(constraint())),
1906 RangeBoundary::Min(Range::ConstantMax(value_range),
1907 Range::ConstantMax(constraint())));
1908 }
1909
1910
1911 bool PhiInstr::InferRange() {
1912 RangeBoundary new_min;
1913 RangeBoundary new_max;
1914
1915 bool has_unranged_inputs = false;
1916 for (intptr_t i = 0; i < InputCount(); i++) {
1917 Range* input_range = InputAt(i)->definition()->range();
1918 if (input_range == NULL) {
1919 has_unranged_inputs = true;
1920 continue;
1921 }
1922
1923 if (new_min.IsUnknown()) {
1924 new_min = Range::ConstantMin(input_range);
1925 } else {
1926 new_min = RangeBoundary::Min(new_min, Range::ConstantMin(input_range));
1927 }
1928
1929 if (new_max.IsUnknown()) {
1930 new_max = Range::ConstantMax(input_range);
1931 } else {
1932 new_max = RangeBoundary::Max(new_max, Range::ConstantMax(input_range));
1933 }
1934 }
1935
1936 ASSERT(new_min.IsUnknown() == new_max.IsUnknown());
1937 if (new_min.IsUnknown()) {
1938 ASSERT(range_ == NULL);
1939 return false;
1940 }
1941
1942 bool had_unranged_inputs = has_unranged_inputs_;
Kevin Millikin (Google) 2012/09/21 08:59:33 Simpler to test the old value before changing it:
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Agreed. The control flow in this function was prev
1943 if (!has_unranged_inputs) has_unranged_inputs_ = false;
1944
1945 if ((range_ != NULL) && !had_unranged_inputs) {
1946 // If phi's range is growing widen it in the direction of growth to
1947 // speedup convergence.
1948 new_min = RangeBoundary::WidenMin(range_->min(), new_min);
1949 new_max = RangeBoundary::WidenMax(range_->max(), new_max);
1950 }
1951
1952 return Range::Update(&range_, new_min, new_max);
1953 }
1954
1955
1956 bool BinarySmiOpInstr::InferRange() {
1957 Range* lrange = left()->definition()->range();
Florian Schneider 2012/09/21 08:56:44 lrange and rrange are easy to confuse. How about j
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1958 Range* rrange = right()->definition()->range();
1959
1960 if ((lrange == NULL) || (rrange == NULL)) {
1961 return Range::Update(&range_,
1962 RangeBoundary::MinSmi(),
1963 RangeBoundary::MaxSmi());
1964 }
1965
1966 RangeBoundary new_min;
1967 RangeBoundary new_max;
1968 switch (op_kind()) {
1969 case Token::kADD:
1970 new_min =
1971 RangeBoundary::Add(Range::ConstantMin(lrange),
1972 Range::ConstantMin(rrange),
1973 RangeBoundary::OverflowedMinSmi());
1974 new_max =
1975 RangeBoundary::Add(Range::ConstantMax(lrange),
1976 Range::ConstantMax(rrange),
1977 RangeBoundary::OverflowedMaxSmi());
1978 break;
1979
1980 case Token::kSUB:
1981 new_min =
1982 RangeBoundary::Sub(Range::ConstantMin(lrange),
1983 Range::ConstantMax(rrange),
1984 RangeBoundary::OverflowedMinSmi());
1985 new_max =
1986 RangeBoundary::Sub(Range::ConstantMax(lrange),
1987 Range::ConstantMin(rrange),
1988 RangeBoundary::OverflowedMaxSmi());
1989 break;
1990
1991 default:
1992 if (range_ == NULL) {
1993 range_ = Range::Unknown();
1994 return true;
1995 }
1996 return false;
1997 }
1998
1999 ASSERT(!new_min.IsUnknown() && !new_max.IsUnknown());
2000 set_overflow(new_min.Overflowed() || new_max.Overflowed());
2001 return Range::Update(&range_, new_min, new_max);
2002 }
2003
2004
1846 #undef __ 2005 #undef __
1847 2006
1848 } // namespace dart 2007 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698