OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
540 static bool HasOnlyTwoSmis(const ICData& ic_data) { | 540 static bool HasOnlyTwoSmis(const ICData& ic_data) { |
541 return (ic_data.NumberOfChecks() == 1) && | 541 return (ic_data.NumberOfChecks() == 1) && |
542 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); | 542 ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid); |
543 } | 543 } |
544 | 544 |
545 static bool HasOnlyTwoFloat32x4s(const ICData& ic_data) { | 545 static bool HasOnlyTwoFloat32x4s(const ICData& ic_data) { |
546 return (ic_data.NumberOfChecks() == 1) && | 546 return (ic_data.NumberOfChecks() == 1) && |
547 ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid); | 547 ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid); |
548 } | 548 } |
549 | 549 |
550 static bool HasOnlyTwoUint32x4s(const ICData& ic_data) { | |
551 return (ic_data.NumberOfChecks() == 1) && | |
552 ICDataHasReceiverArgumentClassIds(ic_data, kUint32x4Cid, kUint32x4Cid); | |
553 } | |
550 | 554 |
551 // Returns false if the ICData contains anything other than the 4 combinations | 555 // Returns false if the ICData contains anything other than the 4 combinations |
552 // of Mint and Smi for the receiver and argument classes. | 556 // of Mint and Smi for the receiver and argument classes. |
553 static bool HasTwoMintOrSmi(const ICData& ic_data) { | 557 static bool HasTwoMintOrSmi(const ICData& ic_data) { |
554 GrowableArray<intptr_t> class_ids(2); | 558 GrowableArray<intptr_t> class_ids(2); |
555 class_ids.Add(kSmiCid); | 559 class_ids.Add(kSmiCid); |
556 class_ids.Add(kMintCid); | 560 class_ids.Add(kMintCid); |
557 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); | 561 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); |
558 } | 562 } |
559 | 563 |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1018 return false; | 1022 return false; |
1019 } | 1023 } |
1020 break; | 1024 break; |
1021 case Token::kBIT_AND: | 1025 case Token::kBIT_AND: |
1022 case Token::kBIT_OR: | 1026 case Token::kBIT_OR: |
1023 case Token::kBIT_XOR: | 1027 case Token::kBIT_XOR: |
1024 if (HasOnlyTwoSmis(ic_data)) { | 1028 if (HasOnlyTwoSmis(ic_data)) { |
1025 operands_type = kSmiCid; | 1029 operands_type = kSmiCid; |
1026 } else if (HasTwoMintOrSmi(ic_data)) { | 1030 } else if (HasTwoMintOrSmi(ic_data)) { |
1027 operands_type = kMintCid; | 1031 operands_type = kMintCid; |
1032 } else if (HasOnlyTwoUint32x4s(ic_data)) { | |
1033 operands_type = kUint32x4Cid; | |
1028 } else { | 1034 } else { |
1029 return false; | 1035 return false; |
1030 } | 1036 } |
1031 break; | 1037 break; |
1032 case Token::kSHR: | 1038 case Token::kSHR: |
1033 case Token::kSHL: | 1039 case Token::kSHL: |
1034 if (HasOnlyTwoSmis(ic_data)) { | 1040 if (HasOnlyTwoSmis(ic_data)) { |
1035 // Left shift may overflow from smi into mint or big ints. | 1041 // Left shift may overflow from smi into mint or big ints. |
1036 // Don't generate smi code if the IC data is marked because | 1042 // Don't generate smi code if the IC data is marked because |
1037 // of an overflow. | 1043 // of an overflow. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1106 ICData::ZoneHandle( | 1112 ICData::ZoneHandle( |
1107 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 1113 call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
1108 call->deopt_id(), | 1114 call->deopt_id(), |
1109 call->env(), | 1115 call->env(), |
1110 call); | 1116 call); |
1111 // Replace call. | 1117 // Replace call. |
1112 BinaryFloat32x4OpInstr* float32x4_bin_op = | 1118 BinaryFloat32x4OpInstr* float32x4_bin_op = |
1113 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), | 1119 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), |
1114 call); | 1120 call); |
1115 ReplaceCall(call, float32x4_bin_op); | 1121 ReplaceCall(call, float32x4_bin_op); |
1122 } else if (operands_type == kUint32x4Cid) { | |
1123 // Type check left. | |
1124 AddCheckClass(left, | |
1125 ICData::ZoneHandle( | |
1126 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
1127 call->deopt_id(), | |
1128 call->env(), | |
1129 call); | |
1130 // Type check right. | |
1131 AddCheckClass(right, | |
1132 ICData::ZoneHandle( | |
1133 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | |
1134 call->deopt_id(), | |
1135 call->env(), | |
1136 call); | |
1137 // Replace call. | |
1138 BinaryUint32x4OpInstr* uint32x4_bin_op = | |
1139 new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right), | |
1140 call); | |
1141 ReplaceCall(call, uint32x4_bin_op); | |
1116 } else if (op_kind == Token::kMOD) { | 1142 } else if (op_kind == Token::kMOD) { |
1117 // TODO(vegorov): implement fast path code for modulo. | 1143 // TODO(vegorov): implement fast path code for modulo. |
1118 ASSERT(operands_type == kSmiCid); | 1144 ASSERT(operands_type == kSmiCid); |
1119 if (!right->IsConstant()) return false; | 1145 if (!right->IsConstant()) return false; |
1120 const Object& obj = right->AsConstant()->value(); | 1146 const Object& obj = right->AsConstant()->value(); |
1121 if (!obj.IsSmi()) return false; | 1147 if (!obj.IsSmi()) return false; |
1122 const intptr_t value = Smi::Cast(obj).Value(); | 1148 const intptr_t value = Smi::Cast(obj).Value(); |
1123 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; | 1149 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; |
1124 | 1150 |
1125 // Insert smi check and attach a copy of the original environment | 1151 // Insert smi check and attach a copy of the original environment |
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1480 case MethodRecognizer::kFloat32x4ShuffleWWWW: | 1506 case MethodRecognizer::kFloat32x4ShuffleWWWW: |
1481 case MethodRecognizer::kFloat32x4ShuffleX: | 1507 case MethodRecognizer::kFloat32x4ShuffleX: |
1482 case MethodRecognizer::kFloat32x4ShuffleY: | 1508 case MethodRecognizer::kFloat32x4ShuffleY: |
1483 case MethodRecognizer::kFloat32x4ShuffleZ: | 1509 case MethodRecognizer::kFloat32x4ShuffleZ: |
1484 case MethodRecognizer::kFloat32x4ShuffleW: | 1510 case MethodRecognizer::kFloat32x4ShuffleW: |
1485 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || | 1511 if (!ic_data.HasReceiverClassId(kFloat32x4Cid) || |
1486 !ic_data.HasOneTarget()) { | 1512 !ic_data.HasOneTarget()) { |
1487 return false; | 1513 return false; |
1488 } | 1514 } |
1489 return InlineFloat32x4Getter(call, recognized_kind); | 1515 return InlineFloat32x4Getter(call, recognized_kind); |
1516 case MethodRecognizer::kUint32x4GetFlagX: | |
1517 case MethodRecognizer::kUint32x4GetFlagY: | |
1518 case MethodRecognizer::kUint32x4GetFlagZ: | |
1519 case MethodRecognizer::kUint32x4GetFlagW: { | |
1520 if (!ic_data.HasReceiverClassId(kUint32x4Cid) || | |
srdjan
2013/05/10 18:36:58
Bad indent (3 instead of 2)
Cutch
2013/05/13 19:40:24
Done.
| |
1521 !ic_data.HasOneTarget()) { | |
1522 return false; | |
1523 } | |
1524 return false; | |
Florian Schneider
2013/05/13 08:46:20
dbc: Shouldn't this return a Uint32x4GetFlagInstr
Cutch
2013/05/13 19:40:24
Done.
| |
1525 } | |
1490 default: | 1526 default: |
1491 ASSERT(recognized_kind == MethodRecognizer::kUnknown); | 1527 ASSERT(recognized_kind == MethodRecognizer::kUnknown); |
1492 } | 1528 } |
1493 return false; | 1529 return false; |
1494 } | 1530 } |
1495 | 1531 |
1496 | 1532 |
1497 LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt( | 1533 LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt( |
1498 InstanceCallInstr* call, | 1534 InstanceCallInstr* call, |
1499 intptr_t cid) { | 1535 intptr_t cid) { |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1747 call, class_ids[0], kTypedDataFloat32x4ArrayCid); | 1783 call, class_ids[0], kTypedDataFloat32x4ArrayCid); |
1748 default: | 1784 default: |
1749 // Unsupported method. | 1785 // Unsupported method. |
1750 return false; | 1786 return false; |
1751 } | 1787 } |
1752 } | 1788 } |
1753 | 1789 |
1754 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { | 1790 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
1755 return TryInlineFloat32x4Method(call, recognized_kind); | 1791 return TryInlineFloat32x4Method(call, recognized_kind); |
1756 } | 1792 } |
1793 | |
1794 if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) { | |
1795 return TryInlineUint32x4Method(call, recognized_kind); | |
1796 } | |
1757 return false; | 1797 return false; |
1758 } | 1798 } |
1759 | 1799 |
1760 | 1800 |
1761 bool FlowGraphOptimizer::TryInlineFloat32x4Method( | 1801 bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
1762 InstanceCallInstr* call, | 1802 InstanceCallInstr* call, |
1763 MethodRecognizer::Kind recognized_kind) { | 1803 MethodRecognizer::Kind recognized_kind) { |
1764 ASSERT(call->HasICData()); | 1804 ASSERT(call->HasICData()); |
1765 switch (recognized_kind) { | 1805 switch (recognized_kind) { |
1766 case MethodRecognizer::kFloat32x4Equal: | 1806 case MethodRecognizer::kFloat32x4Equal: |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1902 new Float32x4ToUint32x4Instr(new Value(left), call); | 1942 new Float32x4ToUint32x4Instr(new Value(left), call); |
1903 ReplaceCall(call, cast); | 1943 ReplaceCall(call, cast); |
1904 return true; | 1944 return true; |
1905 } | 1945 } |
1906 default: | 1946 default: |
1907 return false; | 1947 return false; |
1908 } | 1948 } |
1909 } | 1949 } |
1910 | 1950 |
1911 | 1951 |
1952 bool FlowGraphOptimizer::TryInlineUint32x4Method( | |
1953 InstanceCallInstr* call, | |
1954 MethodRecognizer::Kind recognized_kind) { | |
1955 ASSERT(call->HasICData()); | |
1956 switch (recognized_kind) { | |
1957 case MethodRecognizer::kUint32x4Select: { | |
1958 Definition* mask = call->ArgumentAt(0); | |
1959 Definition* trueValue = call->ArgumentAt(1); | |
1960 Definition* falseValue = call->ArgumentAt(2); | |
1961 // Type check left. | |
1962 AddCheckClass(mask, | |
1963 ICData::ZoneHandle( | |
1964 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
1965 call->deopt_id(), | |
1966 call->env(), | |
1967 call); | |
1968 Uint32x4SelectInstr* select = new Uint32x4SelectInstr( | |
1969 new Value(mask), | |
1970 new Value(trueValue), | |
1971 new Value(falseValue), | |
1972 call); | |
1973 ReplaceCall(call, select); | |
1974 return true; | |
1975 } | |
1976 case MethodRecognizer::kUint32x4ToUint32x4: { | |
1977 Definition* left = call->ArgumentAt(0); | |
1978 // Type check left. | |
1979 AddCheckClass(left, | |
1980 ICData::ZoneHandle( | |
1981 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
1982 call->deopt_id(), | |
1983 call->env(), | |
1984 call); | |
1985 Uint32x4ToFloat32x4Instr* cast = | |
1986 new Uint32x4ToFloat32x4Instr(new Value(left), call); | |
1987 ReplaceCall(call, cast); | |
1988 return true; | |
1989 } | |
1990 case MethodRecognizer::kUint32x4WithFlagX: | |
1991 case MethodRecognizer::kUint32x4WithFlagY: | |
1992 case MethodRecognizer::kUint32x4WithFlagZ: | |
1993 case MethodRecognizer::kUint32x4WithFlagW: { | |
1994 Definition* left = call->ArgumentAt(0); | |
1995 Definition* flag = call->ArgumentAt(1); | |
1996 // Type check left. | |
1997 AddCheckClass(left, | |
1998 ICData::ZoneHandle( | |
1999 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
2000 call->deopt_id(), | |
2001 call->env(), | |
2002 call); | |
2003 Uint32x4SetFlagInstr* setFlag = new Uint32x4SetFlagInstr(recognized_kind, | |
2004 new Value(left), | |
2005 new Value(flag), | |
2006 call); | |
2007 ReplaceCall(call, setFlag); | |
2008 return true; | |
2009 } | |
2010 default: | |
2011 return false; | |
2012 } | |
2013 } | |
2014 | |
2015 | |
1912 bool FlowGraphOptimizer::BuildByteArrayViewLoad( | 2016 bool FlowGraphOptimizer::BuildByteArrayViewLoad( |
1913 InstanceCallInstr* call, | 2017 InstanceCallInstr* call, |
1914 intptr_t receiver_cid, | 2018 intptr_t receiver_cid, |
1915 intptr_t view_cid) { | 2019 intptr_t view_cid) { |
1916 Definition* array = call->ArgumentAt(0); | 2020 Definition* array = call->ArgumentAt(0); |
1917 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); | 2021 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); |
1918 | 2022 |
1919 // Optimistically build a smi-checked load for Int32 and Uint32 | 2023 // Optimistically build a smi-checked load for Int32 and Uint32 |
1920 // loads on ia32 like we do for normal array loads, and only revert to | 2024 // loads on ia32 like we do for normal array loads, and only revert to |
1921 // mint case after deoptimizing here. | 2025 // mint case after deoptimizing here. |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2295 new Float32x4SplatInstr(new Value(call->ArgumentAt(1)), call); | 2399 new Float32x4SplatInstr(new Value(call->ArgumentAt(1)), call); |
2296 ReplaceCall(call, splat); | 2400 ReplaceCall(call, splat); |
2297 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { | 2401 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { |
2298 Float32x4ConstructorInstr* con = | 2402 Float32x4ConstructorInstr* con = |
2299 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)), | 2403 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)), |
2300 new Value(call->ArgumentAt(2)), | 2404 new Value(call->ArgumentAt(2)), |
2301 new Value(call->ArgumentAt(3)), | 2405 new Value(call->ArgumentAt(3)), |
2302 new Value(call->ArgumentAt(4)), | 2406 new Value(call->ArgumentAt(4)), |
2303 call); | 2407 call); |
2304 ReplaceCall(call, con); | 2408 ReplaceCall(call, con); |
2409 } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) { | |
2410 Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr( | |
2411 new Value(call->ArgumentAt(1)), | |
2412 new Value(call->ArgumentAt(2)), | |
2413 new Value(call->ArgumentAt(3)), | |
2414 new Value(call->ArgumentAt(4)), | |
2415 call); | |
srdjan
2013/05/10 18:36:58
Indent 4 spaces
| |
2416 ReplaceCall(call, con); | |
2305 } | 2417 } |
2306 } | 2418 } |
2307 | 2419 |
2308 | 2420 |
2309 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, | 2421 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, |
2310 const ICData& unary_ic_data) { | 2422 const ICData& unary_ic_data) { |
2311 ASSERT((unary_ic_data.NumberOfChecks() > 0) && | 2423 ASSERT((unary_ic_data.NumberOfChecks() > 0) && |
2312 (unary_ic_data.num_args_tested() == 1)); | 2424 (unary_ic_data.num_args_tested() == 1)); |
2313 if (FLAG_enable_type_checks) { | 2425 if (FLAG_enable_type_checks) { |
2314 // TODO(srdjan): Add assignable check node if --enable_type_checks. | 2426 // TODO(srdjan): Add assignable check node if --enable_type_checks. |
(...skipping 2937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5252 SetValue(instr, non_constant_); | 5364 SetValue(instr, non_constant_); |
5253 } | 5365 } |
5254 | 5366 |
5255 | 5367 |
5256 void ConstantPropagator::VisitFloat32x4ToUint32x4( | 5368 void ConstantPropagator::VisitFloat32x4ToUint32x4( |
5257 Float32x4ToUint32x4Instr* instr) { | 5369 Float32x4ToUint32x4Instr* instr) { |
5258 SetValue(instr, non_constant_); | 5370 SetValue(instr, non_constant_); |
5259 } | 5371 } |
5260 | 5372 |
5261 | 5373 |
5374 void ConstantPropagator::VisitUint32x4BoolConstructor( | |
5375 Uint32x4BoolConstructorInstr* instr) { | |
5376 SetValue(instr, non_constant_); | |
5377 } | |
5378 | |
5379 | |
5380 void ConstantPropagator::VisitUint32x4GetFlag(Uint32x4GetFlagInstr* instr) { | |
5381 SetValue(instr, non_constant_); | |
5382 } | |
5383 | |
5384 | |
5385 void ConstantPropagator::VisitUint32x4SetFlag(Uint32x4SetFlagInstr* instr) { | |
5386 SetValue(instr, non_constant_); | |
5387 } | |
5388 | |
5389 | |
5390 void ConstantPropagator::VisitUint32x4Select(Uint32x4SelectInstr* instr) { | |
5391 SetValue(instr, non_constant_); | |
5392 } | |
5393 | |
5394 | |
5395 void ConstantPropagator::VisitUint32x4ToFloat32x4( | |
5396 Uint32x4ToFloat32x4Instr* instr) { | |
5397 SetValue(instr, non_constant_); | |
5398 } | |
5399 | |
5400 | |
5401 void ConstantPropagator::VisitBinaryUint32x4Op(BinaryUint32x4OpInstr* instr) { | |
5402 SetValue(instr, non_constant_); | |
5403 } | |
5404 | |
5405 | |
5262 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) { | 5406 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) { |
5263 const Object& value = instr->value()->definition()->constant_value(); | 5407 const Object& value = instr->value()->definition()->constant_value(); |
5264 if (IsNonConstant(value)) { | 5408 if (IsNonConstant(value)) { |
5265 SetValue(instr, non_constant_); | 5409 SetValue(instr, non_constant_); |
5266 } else if (IsConstant(value)) { | 5410 } else if (IsConstant(value)) { |
5267 // TODO(kmillikin): Handle sqrt. | 5411 // TODO(kmillikin): Handle sqrt. |
5268 SetValue(instr, non_constant_); | 5412 SetValue(instr, non_constant_); |
5269 } | 5413 } |
5270 } | 5414 } |
5271 | 5415 |
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6145 | 6289 |
6146 // Insert materializations at environment uses. | 6290 // Insert materializations at environment uses. |
6147 const Class& cls = Class::Handle(alloc->constructor().Owner()); | 6291 const Class& cls = Class::Handle(alloc->constructor().Owner()); |
6148 for (intptr_t i = 0; i < exits.length(); i++) { | 6292 for (intptr_t i = 0; i < exits.length(); i++) { |
6149 CreateMaterializationAt(exits[i], alloc, cls, *fields); | 6293 CreateMaterializationAt(exits[i], alloc, cls, *fields); |
6150 } | 6294 } |
6151 } | 6295 } |
6152 | 6296 |
6153 | 6297 |
6154 } // namespace dart | 6298 } // namespace dart |
OLD | NEW |