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

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

Issue 15085006: Inline Uint32x4 operations (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 7 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) 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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698