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

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

Issue 20125005: Allow SIMD types to be used on mips (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 5 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_optimizer.h ('k') | tests/lib/lib.status » ('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) 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/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 18 matching lines...) Expand all
29 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); 29 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis.");
30 DEFINE_FLAG(bool, trace_constant_propagation, false, 30 DEFINE_FLAG(bool, trace_constant_propagation, false,
31 "Print constant propagation and useless code elimination."); 31 "Print constant propagation and useless code elimination.");
32 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); 32 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
33 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); 33 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress");
34 DEFINE_FLAG(bool, truncating_left_shift, true, 34 DEFINE_FLAG(bool, truncating_left_shift, true,
35 "Optimize left shift to truncate if possible"); 35 "Optimize left shift to truncate if possible");
36 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); 36 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
37 DEFINE_FLAG(bool, trace_load_optimization, false, 37 DEFINE_FLAG(bool, trace_load_optimization, false,
38 "Print live sets for load optimization pass."); 38 "Print live sets for load optimization pass.");
39 DEFINE_FLAG(bool, disable_simd_inline, false,
srdjan 2013/07/25 17:02:14 Think positive, rename flag enable_simd_inline, de
40 "Disable inlining of SIMD related method calls.");
39 DECLARE_FLAG(bool, eliminate_type_checks); 41 DECLARE_FLAG(bool, eliminate_type_checks);
40 DECLARE_FLAG(bool, enable_type_checks); 42 DECLARE_FLAG(bool, enable_type_checks);
41 DECLARE_FLAG(bool, trace_type_check_elimination); 43 DECLARE_FLAG(bool, trace_type_check_elimination);
42 44
43 45
46 static bool ShouldInlineSimd() {
47 #if defined(TARGET_ARCH_MIPS)
48 return false;
49 #endif
50 return !FLAG_disable_simd_inline;
srdjan 2013/07/25 17:02:14 Why don't you use the ifdef on flag definition?
Cutch 2013/07/25 17:08:13 Because enabling it on MIPS will cause a crash.
51 }
52
53
44 // Optimize instance calls using ICData. 54 // Optimize instance calls using ICData.
45 void FlowGraphOptimizer::ApplyICData() { 55 void FlowGraphOptimizer::ApplyICData() {
46 VisitBlocks(); 56 VisitBlocks();
47 } 57 }
48 58
49 59
50 // Optimize instance calls using cid. 60 // Optimize instance calls using cid.
51 // Attempts to convert an instance call (IC call) using propagated class-ids, 61 // Attempts to convert an instance call (IC call) using propagated class-ids,
52 // e.g., receiver class id, guarded-cid. 62 // e.g., receiver class id, guarded-cid.
53 void FlowGraphOptimizer::ApplyClassIds() { 63 void FlowGraphOptimizer::ApplyClassIds() {
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 // Returns true if phi's representation was changed. 443 // Returns true if phi's representation was changed.
434 static bool UnboxPhi(PhiInstr* phi) { 444 static bool UnboxPhi(PhiInstr* phi) {
435 Representation current = phi->representation(); 445 Representation current = phi->representation();
436 Representation unboxed = current; 446 Representation unboxed = current;
437 447
438 switch (phi->Type()->ToCid()) { 448 switch (phi->Type()->ToCid()) {
439 case kDoubleCid: 449 case kDoubleCid:
440 unboxed = kUnboxedDouble; 450 unboxed = kUnboxedDouble;
441 break; 451 break;
442 case kFloat32x4Cid: 452 case kFloat32x4Cid:
443 unboxed = kUnboxedFloat32x4; 453 if (ShouldInlineSimd()) {
454 unboxed = kUnboxedFloat32x4;
455 }
444 break; 456 break;
445 case kUint32x4Cid: 457 case kUint32x4Cid:
446 unboxed = kUnboxedUint32x4; 458 if (ShouldInlineSimd()) {
459 unboxed = kUnboxedUint32x4;
460 }
447 break; 461 break;
448 } 462 }
449 463
450 if (unboxed != current) { 464 if (unboxed != current) {
451 phi->set_representation(unboxed); 465 phi->set_representation(unboxed);
452 return true; 466 return true;
453 } 467 }
454 468
455 return false; 469 return false;
456 } 470 }
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 case kTypedDataFloat64ArrayCid: { 827 case kTypedDataFloat64ArrayCid: {
814 // Check that value is always double. 828 // Check that value is always double.
815 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 829 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
816 if ((value_check.NumberOfChecks() != 1) || 830 if ((value_check.NumberOfChecks() != 1) ||
817 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) { 831 (value_check.GetReceiverClassIdAt(0) != kDoubleCid)) {
818 return false; 832 return false;
819 } 833 }
820 break; 834 break;
821 } 835 }
822 case kTypedDataFloat32x4ArrayCid: { 836 case kTypedDataFloat32x4ArrayCid: {
837 if (!ShouldInlineSimd()) {
838 return false;
839 }
823 // Check that value is always a Float32x4. 840 // Check that value is always a Float32x4.
824 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2); 841 value_check = call->ic_data()->AsUnaryClassChecksForArgNr(2);
825 if ((value_check.NumberOfChecks() != 1) || 842 if ((value_check.NumberOfChecks() != 1) ||
826 (value_check.GetReceiverClassIdAt(0) != kFloat32x4Cid)) { 843 (value_check.GetReceiverClassIdAt(0) != kFloat32x4Cid)) {
827 return false; 844 return false;
828 } 845 }
829 } 846 }
830 break; 847 break;
831 default: 848 default:
832 // TODO(fschneider): Add support for other array types. 849 // TODO(fschneider): Add support for other array types.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { 962 bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) {
946 const intptr_t class_id = ReceiverClassId(call); 963 const intptr_t class_id = ReceiverClassId(call);
947 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt. 964 // Set deopt_id to a valid id if the LoadIndexedInstr can cause deopt.
948 intptr_t deopt_id = Isolate::kNoDeoptId; 965 intptr_t deopt_id = Isolate::kNoDeoptId;
949 switch (class_id) { 966 switch (class_id) {
950 case kArrayCid: 967 case kArrayCid:
951 case kImmutableArrayCid: 968 case kImmutableArrayCid:
952 case kGrowableObjectArrayCid: 969 case kGrowableObjectArrayCid:
953 case kTypedDataFloat32ArrayCid: 970 case kTypedDataFloat32ArrayCid:
954 case kTypedDataFloat64ArrayCid: 971 case kTypedDataFloat64ArrayCid:
955 case kTypedDataFloat32x4ArrayCid:
956 case kTypedDataInt8ArrayCid: 972 case kTypedDataInt8ArrayCid:
957 case kTypedDataUint8ArrayCid: 973 case kTypedDataUint8ArrayCid:
958 case kTypedDataUint8ClampedArrayCid: 974 case kTypedDataUint8ClampedArrayCid:
959 case kExternalTypedDataUint8ArrayCid: 975 case kExternalTypedDataUint8ArrayCid:
960 case kExternalTypedDataUint8ClampedArrayCid: 976 case kExternalTypedDataUint8ClampedArrayCid:
961 case kTypedDataInt16ArrayCid: 977 case kTypedDataInt16ArrayCid:
962 case kTypedDataUint16ArrayCid: 978 case kTypedDataUint16ArrayCid:
963 break; 979 break;
980 case kTypedDataFloat32x4ArrayCid:
981 if (!ShouldInlineSimd()) {
982 return false;
983 }
984 break;
964 case kTypedDataInt32ArrayCid: 985 case kTypedDataInt32ArrayCid:
965 case kTypedDataUint32ArrayCid: { 986 case kTypedDataUint32ArrayCid: {
966 if (!CanUnboxInt32()) return false; 987 if (!CanUnboxInt32()) return false;
967 988
968 // Set deopt_id if we can optimistically assume that the result is Smi. 989 // Set deopt_id if we can optimistically assume that the result is Smi.
969 // Assume mixed Mint/Smi if this instruction caused deoptimization once. 990 // Assume mixed Mint/Smi if this instruction caused deoptimization once.
970 ASSERT(call->HasICData()); 991 ASSERT(call->HasICData());
971 const ICData& ic_data = *call->ic_data(); 992 const ICData& ic_data = *call->ic_data();
972 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ? 993 deopt_id = (ic_data.deopt_reason() == kDeoptUnknown) ?
973 call->deopt_id() : Isolate::kNoDeoptId; 994 call->deopt_id() : Isolate::kNoDeoptId;
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1121 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), 1142 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right),
1122 call->deopt_id()); 1143 call->deopt_id());
1123 ReplaceCall(call, shift_op); 1144 ReplaceCall(call, shift_op);
1124 } else { 1145 } else {
1125 BinaryMintOpInstr* bin_op = 1146 BinaryMintOpInstr* bin_op =
1126 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), 1147 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right),
1127 call->deopt_id()); 1148 call->deopt_id());
1128 ReplaceCall(call, bin_op); 1149 ReplaceCall(call, bin_op);
1129 } 1150 }
1130 } else if (operands_type == kFloat32x4Cid) { 1151 } else if (operands_type == kFloat32x4Cid) {
1131 // Type check left. 1152 return InlineFloat32x4BinaryOp(call, op_kind);
1132 AddCheckClass(left,
1133 ICData::ZoneHandle(
1134 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1135 call->deopt_id(),
1136 call->env(),
1137 call);
1138 // Type check right.
1139 AddCheckClass(right,
1140 ICData::ZoneHandle(
1141 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1142 call->deopt_id(),
1143 call->env(),
1144 call);
1145 // Replace call.
1146 BinaryFloat32x4OpInstr* float32x4_bin_op =
1147 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right),
1148 call->deopt_id());
1149 ReplaceCall(call, float32x4_bin_op);
1150 } else if (operands_type == kUint32x4Cid) { 1153 } else if (operands_type == kUint32x4Cid) {
1151 // Type check left. 1154 return InlineUint32x4BinaryOp(call, op_kind);
1152 AddCheckClass(left,
1153 ICData::ZoneHandle(
1154 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1155 call->deopt_id(),
1156 call->env(),
1157 call);
1158 // Type check right.
1159 AddCheckClass(right,
1160 ICData::ZoneHandle(
1161 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1162 call->deopt_id(),
1163 call->env(),
1164 call);
1165 // Replace call.
1166 BinaryUint32x4OpInstr* uint32x4_bin_op =
1167 new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right),
1168 call->deopt_id());
1169 ReplaceCall(call, uint32x4_bin_op);
1170 } else if (op_kind == Token::kMOD) { 1155 } else if (op_kind == Token::kMOD) {
1171 // TODO(vegorov): implement fast path code for modulo. 1156 // TODO(vegorov): implement fast path code for modulo.
1172 ASSERT(operands_type == kSmiCid); 1157 ASSERT(operands_type == kSmiCid);
1173 if (!right->IsConstant()) return false; 1158 if (!right->IsConstant()) return false;
1174 const Object& obj = right->AsConstant()->value(); 1159 const Object& obj = right->AsConstant()->value();
1175 if (!obj.IsSmi()) return false; 1160 if (!obj.IsSmi()) return false;
1176 const intptr_t value = Smi::Cast(obj).Value(); 1161 const intptr_t value = Smi::Cast(obj).Value();
1177 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; 1162 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false;
1178 1163
1179 // Insert smi check and attach a copy of the original environment 1164 // Insert smi check and attach a copy of the original environment
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 return GrowableObjectArray::length_offset(); 1440 return GrowableObjectArray::length_offset();
1456 default: 1441 default:
1457 UNREACHABLE(); 1442 UNREACHABLE();
1458 return 0; 1443 return 0;
1459 } 1444 }
1460 } 1445 }
1461 1446
1462 1447
1463 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, 1448 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
1464 MethodRecognizer::Kind getter) { 1449 MethodRecognizer::Kind getter) {
1450 if (!ShouldInlineSimd()) {
1451 return false;
1452 }
1465 AddCheckClass(call->ArgumentAt(0), 1453 AddCheckClass(call->ArgumentAt(0),
1466 ICData::ZoneHandle( 1454 ICData::ZoneHandle(
1467 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1455 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1468 call->deopt_id(), 1456 call->deopt_id(),
1469 call->env(), 1457 call->env(),
1470 call); 1458 call);
1471 intptr_t mask = 0; 1459 intptr_t mask = 0;
1472 if (getter == MethodRecognizer::kFloat32x4Shuffle) { 1460 if (getter == MethodRecognizer::kFloat32x4Shuffle) {
1473 ASSERT(call->ArgumentCount() == 2); 1461 ASSERT(call->ArgumentCount() == 2);
1474 // Extract shuffle mask. 1462 // Extract shuffle mask.
(...skipping 11 matching lines...) Expand all
1486 new Value(call->ArgumentAt(0)), 1474 new Value(call->ArgumentAt(0)),
1487 mask, 1475 mask,
1488 call->deopt_id()); 1476 call->deopt_id());
1489 ReplaceCall(call, instr); 1477 ReplaceCall(call, instr);
1490 return true; 1478 return true;
1491 } 1479 }
1492 1480
1493 1481
1494 bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call, 1482 bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call,
1495 MethodRecognizer::Kind getter) { 1483 MethodRecognizer::Kind getter) {
1484 if (!ShouldInlineSimd()) {
1485 return false;
1486 }
1496 AddCheckClass(call->ArgumentAt(0), 1487 AddCheckClass(call->ArgumentAt(0),
1497 ICData::ZoneHandle( 1488 ICData::ZoneHandle(
1498 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1489 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1499 call->deopt_id(), 1490 call->deopt_id(),
1500 call->env(), 1491 call->env(),
1501 call); 1492 call);
1502 Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr( 1493 Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr(
1503 getter, 1494 getter,
1504 new Value(call->ArgumentAt(0)), 1495 new Value(call->ArgumentAt(0)),
1505 call->deopt_id()); 1496 call->deopt_id());
1506 ReplaceCall(call, instr); 1497 ReplaceCall(call, instr);
1507 return true; 1498 return true;
1508 } 1499 }
1509 1500
1510 1501
1502 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
1503 Token::Kind op_kind) {
1504 if (!ShouldInlineSimd()) {
1505 return false;
1506 }
1507 ASSERT(call->ArgumentCount() == 2);
1508 Definition* left = call->ArgumentAt(0);
1509 Definition* right = call->ArgumentAt(1);
1510 // Type check left.
1511 AddCheckClass(left,
1512 ICData::ZoneHandle(
1513 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1514 call->deopt_id(),
1515 call->env(),
1516 call);
1517 // Type check right.
1518 AddCheckClass(right,
1519 ICData::ZoneHandle(
1520 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1521 call->deopt_id(),
1522 call->env(),
1523 call);
1524 // Replace call.
1525 BinaryFloat32x4OpInstr* float32x4_bin_op =
1526 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right),
1527 call->deopt_id());
1528 ReplaceCall(call, float32x4_bin_op);
1529
1530 return true;
1531 }
1532
1533
1534 bool FlowGraphOptimizer::InlineUint32x4BinaryOp(InstanceCallInstr* call,
1535 Token::Kind op_kind) {
1536 if (!ShouldInlineSimd()) {
1537 return false;
1538 }
1539 ASSERT(call->ArgumentCount() == 2);
1540 Definition* left = call->ArgumentAt(0);
1541 Definition* right = call->ArgumentAt(1);
1542 // Type check left.
1543 AddCheckClass(left,
1544 ICData::ZoneHandle(
1545 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1546 call->deopt_id(),
1547 call->env(),
1548 call);
1549 // Type check right.
1550 AddCheckClass(right,
1551 ICData::ZoneHandle(
1552 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1553 call->deopt_id(),
1554 call->env(),
1555 call);
1556 // Replace call.
1557 BinaryUint32x4OpInstr* uint32x4_bin_op =
1558 new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right),
1559 call->deopt_id());
1560 ReplaceCall(call, uint32x4_bin_op);
1561 return true;
1562 }
1563
1564
1511 // Only unique implicit instance getters can be currently handled. 1565 // Only unique implicit instance getters can be currently handled.
1512 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { 1566 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
1513 ASSERT(call->HasICData()); 1567 ASSERT(call->HasICData());
1514 const ICData& ic_data = *call->ic_data(); 1568 const ICData& ic_data = *call->ic_data();
1515 if (ic_data.NumberOfChecks() == 0) { 1569 if (ic_data.NumberOfChecks() == 0) {
1516 // No type feedback collected. 1570 // No type feedback collected.
1517 return false; 1571 return false;
1518 } 1572 }
1519 Function& target = Function::Handle(ic_data.GetTargetAt(0)); 1573 Function& target = Function::Handle(ic_data.GetTargetAt(0));
1520 if (target.kind() == RawFunction::kImplicitGetter) { 1574 if (target.kind() == RawFunction::kImplicitGetter) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
1891 return TryInlineFloat32x4Method(call, recognized_kind); 1945 return TryInlineFloat32x4Method(call, recognized_kind);
1892 } 1946 }
1893 1947
1894 if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) { 1948 if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
1895 return TryInlineUint32x4Method(call, recognized_kind); 1949 return TryInlineUint32x4Method(call, recognized_kind);
1896 } 1950 }
1897 return false; 1951 return false;
1898 } 1952 }
1899 1953
1900 1954
1955 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
1956 StaticCallInstr* call,
1957 MethodRecognizer::Kind recognized_kind) {
1958 if (!ShouldInlineSimd()) {
1959 return false;
1960 }
1961 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) {
1962 Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call->deopt_id());
1963 ReplaceCall(call, zero);
1964 return true;
1965 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) {
1966 Float32x4SplatInstr* splat =
1967 new Float32x4SplatInstr(new Value(call->ArgumentAt(1)),
1968 call->deopt_id());
1969 ReplaceCall(call, splat);
1970 return true;
1971 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) {
1972 Float32x4ConstructorInstr* con =
1973 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)),
1974 new Value(call->ArgumentAt(2)),
1975 new Value(call->ArgumentAt(3)),
1976 new Value(call->ArgumentAt(4)),
1977 call->deopt_id());
1978 ReplaceCall(call, con);
1979 return true;
1980 }
1981 return false;
1982 }
1983
1984
1985 bool FlowGraphOptimizer::TryInlineUint32x4Constructor(
1986 StaticCallInstr* call,
1987 MethodRecognizer::Kind recognized_kind) {
1988 if (!ShouldInlineSimd()) {
1989 return false;
1990 }
1991 if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) {
1992 Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr(
1993 new Value(call->ArgumentAt(1)),
1994 new Value(call->ArgumentAt(2)),
1995 new Value(call->ArgumentAt(3)),
1996 new Value(call->ArgumentAt(4)),
1997 call->deopt_id());
1998 ReplaceCall(call, con);
1999 return true;
2000 }
2001 return false;
2002 }
2003
2004
1901 bool FlowGraphOptimizer::TryInlineFloat32x4Method( 2005 bool FlowGraphOptimizer::TryInlineFloat32x4Method(
1902 InstanceCallInstr* call, 2006 InstanceCallInstr* call,
1903 MethodRecognizer::Kind recognized_kind) { 2007 MethodRecognizer::Kind recognized_kind) {
2008 if (!ShouldInlineSimd()) {
2009 return false;
2010 }
1904 ASSERT(call->HasICData()); 2011 ASSERT(call->HasICData());
1905 switch (recognized_kind) { 2012 switch (recognized_kind) {
1906 case MethodRecognizer::kFloat32x4Equal: 2013 case MethodRecognizer::kFloat32x4Equal:
1907 case MethodRecognizer::kFloat32x4GreaterThan: 2014 case MethodRecognizer::kFloat32x4GreaterThan:
1908 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: 2015 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
1909 case MethodRecognizer::kFloat32x4LessThan: 2016 case MethodRecognizer::kFloat32x4LessThan:
1910 case MethodRecognizer::kFloat32x4LessThanOrEqual: 2017 case MethodRecognizer::kFloat32x4LessThanOrEqual:
1911 case MethodRecognizer::kFloat32x4NotEqual: { 2018 case MethodRecognizer::kFloat32x4NotEqual: {
1912 Definition* left = call->ArgumentAt(0); 2019 Definition* left = call->ArgumentAt(0);
1913 Definition* right = call->ArgumentAt(1); 2020 Definition* right = call->ArgumentAt(1);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2050 } 2157 }
2051 default: 2158 default:
2052 return false; 2159 return false;
2053 } 2160 }
2054 } 2161 }
2055 2162
2056 2163
2057 bool FlowGraphOptimizer::TryInlineUint32x4Method( 2164 bool FlowGraphOptimizer::TryInlineUint32x4Method(
2058 InstanceCallInstr* call, 2165 InstanceCallInstr* call,
2059 MethodRecognizer::Kind recognized_kind) { 2166 MethodRecognizer::Kind recognized_kind) {
2167 if (!ShouldInlineSimd()) {
2168 return false;
2169 }
2060 ASSERT(call->HasICData()); 2170 ASSERT(call->HasICData());
2061 switch (recognized_kind) { 2171 switch (recognized_kind) {
2062 case MethodRecognizer::kUint32x4Select: { 2172 case MethodRecognizer::kUint32x4Select: {
2063 Definition* mask = call->ArgumentAt(0); 2173 Definition* mask = call->ArgumentAt(0);
2064 Definition* trueValue = call->ArgumentAt(1); 2174 Definition* trueValue = call->ArgumentAt(1);
2065 Definition* falseValue = call->ArgumentAt(2); 2175 Definition* falseValue = call->ArgumentAt(2);
2066 // Type check left. 2176 // Type check left.
2067 AddCheckClass(mask, 2177 AddCheckClass(mask,
2068 ICData::ZoneHandle( 2178 ICData::ZoneHandle(
2069 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2179 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2116 default: 2226 default:
2117 return false; 2227 return false;
2118 } 2228 }
2119 } 2229 }
2120 2230
2121 2231
2122 bool FlowGraphOptimizer::BuildByteArrayViewLoad( 2232 bool FlowGraphOptimizer::BuildByteArrayViewLoad(
2123 InstanceCallInstr* call, 2233 InstanceCallInstr* call,
2124 intptr_t receiver_cid, 2234 intptr_t receiver_cid,
2125 intptr_t view_cid) { 2235 intptr_t view_cid) {
2236 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2237 return false;
2238 }
2239
2126 Definition* array = call->ArgumentAt(0); 2240 Definition* array = call->ArgumentAt(0);
2127 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); 2241 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
2128 2242
2129 // Optimistically build a smi-checked load for Int32 and Uint32 2243 // Optimistically build a smi-checked load for Int32 and Uint32
2130 // loads on ia32 like we do for normal array loads, and only revert to 2244 // loads on ia32 like we do for normal array loads, and only revert to
2131 // mint case after deoptimizing here. 2245 // mint case after deoptimizing here.
2132 intptr_t deopt_id = Isolate::kNoDeoptId; 2246 intptr_t deopt_id = Isolate::kNoDeoptId;
2133 if ((view_cid == kTypedDataInt32ArrayCid || 2247 if ((view_cid == kTypedDataInt32ArrayCid ||
2134 view_cid == kTypedDataUint32ArrayCid) && 2248 view_cid == kTypedDataUint32ArrayCid) &&
2135 call->ic_data()->deopt_reason() == kDeoptUnknown) { 2249 call->ic_data()->deopt_reason() == kDeoptUnknown) {
2136 deopt_id = call->deopt_id(); 2250 deopt_id = call->deopt_id();
2137 } 2251 }
2138 Definition* byte_index = call->ArgumentAt(1); 2252 Definition* byte_index = call->ArgumentAt(1);
2139 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), 2253 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array),
2140 new Value(byte_index), 2254 new Value(byte_index),
2141 1, // Index scale. 2255 1, // Index scale.
2142 view_cid, 2256 view_cid,
2143 deopt_id); 2257 deopt_id);
2144 ReplaceCall(call, array_op); 2258 ReplaceCall(call, array_op);
2145 return true; 2259 return true;
2146 } 2260 }
2147 2261
2148 2262
2149 bool FlowGraphOptimizer::BuildByteArrayViewStore( 2263 bool FlowGraphOptimizer::BuildByteArrayViewStore(
2150 InstanceCallInstr* call, 2264 InstanceCallInstr* call,
2151 intptr_t receiver_cid, 2265 intptr_t receiver_cid,
2152 intptr_t view_cid) { 2266 intptr_t view_cid) {
2267 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2268 return false;
srdjan 2013/07/25 17:02:14 Bad indentation.
Cutch 2013/07/25 17:08:13 Done.
2269 }
2153 Definition* array = call->ArgumentAt(0); 2270 Definition* array = call->ArgumentAt(0);
2154 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); 2271 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
2155 ICData& value_check = ICData::ZoneHandle(); 2272 ICData& value_check = ICData::ZoneHandle();
2156 switch (view_cid) { 2273 switch (view_cid) {
2157 case kTypedDataInt8ArrayCid: 2274 case kTypedDataInt8ArrayCid:
2158 case kTypedDataUint8ArrayCid: 2275 case kTypedDataUint8ArrayCid:
2159 case kTypedDataUint8ClampedArrayCid: 2276 case kTypedDataUint8ClampedArrayCid:
2160 case kExternalTypedDataUint8ArrayCid: 2277 case kExternalTypedDataUint8ArrayCid:
2161 case kExternalTypedDataUint8ClampedArrayCid: 2278 case kExternalTypedDataUint8ClampedArrayCid:
2162 case kTypedDataInt16ArrayCid: 2279 case kTypedDataInt16ArrayCid:
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2493 } 2610 }
2494 2611
2495 2612
2496 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { 2613 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
2497 MethodRecognizer::Kind recognized_kind = 2614 MethodRecognizer::Kind recognized_kind =
2498 MethodRecognizer::RecognizeKind(call->function()); 2615 MethodRecognizer::RecognizeKind(call->function());
2499 if (recognized_kind == MethodRecognizer::kMathSqrt) { 2616 if (recognized_kind == MethodRecognizer::kMathSqrt) {
2500 MathSqrtInstr* sqrt = 2617 MathSqrtInstr* sqrt =
2501 new MathSqrtInstr(new Value(call->ArgumentAt(0)), call->deopt_id()); 2618 new MathSqrtInstr(new Value(call->ArgumentAt(0)), call->deopt_id());
2502 ReplaceCall(call, sqrt); 2619 ReplaceCall(call, sqrt);
2503 } else if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { 2620 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) ||
2504 Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call->deopt_id()); 2621 (recognized_kind == MethodRecognizer::kFloat32x4Splat) ||
2505 ReplaceCall(call, zero); 2622 (recognized_kind == MethodRecognizer::kFloat32x4Constructor)) {
2506 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { 2623 TryInlineFloat32x4Constructor(call, recognized_kind);
2507 Float32x4SplatInstr* splat =
2508 new Float32x4SplatInstr(new Value(call->ArgumentAt(1)),
2509 call->deopt_id());
2510 ReplaceCall(call, splat);
2511 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) {
2512 Float32x4ConstructorInstr* con =
2513 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)),
2514 new Value(call->ArgumentAt(2)),
2515 new Value(call->ArgumentAt(3)),
2516 new Value(call->ArgumentAt(4)),
2517 call->deopt_id());
2518 ReplaceCall(call, con);
2519 } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) { 2624 } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) {
2520 Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr( 2625 TryInlineUint32x4Constructor(call, recognized_kind);
2521 new Value(call->ArgumentAt(1)),
2522 new Value(call->ArgumentAt(2)),
2523 new Value(call->ArgumentAt(3)),
2524 new Value(call->ArgumentAt(4)),
2525 call->deopt_id());
2526 ReplaceCall(call, con);
2527 } else if (recognized_kind == MethodRecognizer::kObjectConstructor) { 2626 } else if (recognized_kind == MethodRecognizer::kObjectConstructor) {
2528 // Remove the original push arguments. 2627 // Remove the original push arguments.
2529 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 2628 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2530 PushArgumentInstr* push = call->PushArgumentAt(i); 2629 PushArgumentInstr* push = call->PushArgumentAt(i);
2531 push->ReplaceUsesWith(push->value()->definition()); 2630 push->ReplaceUsesWith(push->value()->definition());
2532 push->RemoveFromGraph(); 2631 push->RemoveFromGraph();
2533 } 2632 }
2534 // Manually replace call with global null constant. ReplaceCall can't 2633 // Manually replace call with global null constant. ReplaceCall can't
2535 // be used for definitions that are already in the graph. 2634 // be used for definitions that are already in the graph.
2536 call->ReplaceUsesWith(flow_graph_->constant_null()); 2635 call->ReplaceUsesWith(flow_graph_->constant_null());
(...skipping 4704 matching lines...) Expand 10 before | Expand all | Expand 10 after
7241 7340
7242 // Insert materializations at environment uses. 7341 // Insert materializations at environment uses.
7243 const Class& cls = Class::Handle(alloc->constructor().Owner()); 7342 const Class& cls = Class::Handle(alloc->constructor().Owner());
7244 for (intptr_t i = 0; i < exits.length(); i++) { 7343 for (intptr_t i = 0; i < exits.length(); i++) {
7245 CreateMaterializationAt(exits[i], alloc, cls, *fields); 7344 CreateMaterializationAt(exits[i], alloc, cls, *fields);
7246 } 7345 }
7247 } 7346 }
7248 7347
7249 7348
7250 } // namespace dart 7349 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | tests/lib/lib.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698