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

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, enable_simd_inline, true,
40 "Enable 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_enable_simd_inline;
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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right), 1145 new ShiftMintOpInstr(op_kind, new Value(left), new Value(right),
1125 call->deopt_id()); 1146 call->deopt_id());
1126 ReplaceCall(call, shift_op); 1147 ReplaceCall(call, shift_op);
1127 } else { 1148 } else {
1128 BinaryMintOpInstr* bin_op = 1149 BinaryMintOpInstr* bin_op =
1129 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), 1150 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right),
1130 call->deopt_id()); 1151 call->deopt_id());
1131 ReplaceCall(call, bin_op); 1152 ReplaceCall(call, bin_op);
1132 } 1153 }
1133 } else if (operands_type == kFloat32x4Cid) { 1154 } else if (operands_type == kFloat32x4Cid) {
1134 // Type check left. 1155 return InlineFloat32x4BinaryOp(call, op_kind);
1135 AddCheckClass(left,
1136 ICData::ZoneHandle(
1137 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1138 call->deopt_id(),
1139 call->env(),
1140 call);
1141 // Type check right.
1142 AddCheckClass(right,
1143 ICData::ZoneHandle(
1144 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1145 call->deopt_id(),
1146 call->env(),
1147 call);
1148 // Replace call.
1149 BinaryFloat32x4OpInstr* float32x4_bin_op =
1150 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right),
1151 call->deopt_id());
1152 ReplaceCall(call, float32x4_bin_op);
1153 } else if (operands_type == kUint32x4Cid) { 1156 } else if (operands_type == kUint32x4Cid) {
1154 // Type check left. 1157 return InlineUint32x4BinaryOp(call, op_kind);
1155 AddCheckClass(left,
1156 ICData::ZoneHandle(
1157 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1158 call->deopt_id(),
1159 call->env(),
1160 call);
1161 // Type check right.
1162 AddCheckClass(right,
1163 ICData::ZoneHandle(
1164 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1165 call->deopt_id(),
1166 call->env(),
1167 call);
1168 // Replace call.
1169 BinaryUint32x4OpInstr* uint32x4_bin_op =
1170 new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right),
1171 call->deopt_id());
1172 ReplaceCall(call, uint32x4_bin_op);
1173 } else if (op_kind == Token::kMOD) { 1158 } else if (op_kind == Token::kMOD) {
1174 // TODO(vegorov): implement fast path code for modulo. 1159 // TODO(vegorov): implement fast path code for modulo.
1175 ASSERT(operands_type == kSmiCid); 1160 ASSERT(operands_type == kSmiCid);
1176 if (!right->IsConstant()) return false; 1161 if (!right->IsConstant()) return false;
1177 const Object& obj = right->AsConstant()->value(); 1162 const Object& obj = right->AsConstant()->value();
1178 if (!obj.IsSmi()) return false; 1163 if (!obj.IsSmi()) return false;
1179 const intptr_t value = Smi::Cast(obj).Value(); 1164 const intptr_t value = Smi::Cast(obj).Value();
1180 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; 1165 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false;
1181 1166
1182 // Insert smi check and attach a copy of the original environment 1167 // Insert smi check and attach a copy of the original environment
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 return GrowableObjectArray::length_offset(); 1443 return GrowableObjectArray::length_offset();
1459 default: 1444 default:
1460 UNREACHABLE(); 1445 UNREACHABLE();
1461 return 0; 1446 return 0;
1462 } 1447 }
1463 } 1448 }
1464 1449
1465 1450
1466 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, 1451 bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
1467 MethodRecognizer::Kind getter) { 1452 MethodRecognizer::Kind getter) {
1453 if (!ShouldInlineSimd()) {
1454 return false;
1455 }
1468 AddCheckClass(call->ArgumentAt(0), 1456 AddCheckClass(call->ArgumentAt(0),
1469 ICData::ZoneHandle( 1457 ICData::ZoneHandle(
1470 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1458 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1471 call->deopt_id(), 1459 call->deopt_id(),
1472 call->env(), 1460 call->env(),
1473 call); 1461 call);
1474 intptr_t mask = 0; 1462 intptr_t mask = 0;
1475 if (getter == MethodRecognizer::kFloat32x4Shuffle) { 1463 if (getter == MethodRecognizer::kFloat32x4Shuffle) {
1476 ASSERT(call->ArgumentCount() == 2); 1464 ASSERT(call->ArgumentCount() == 2);
1477 // Extract shuffle mask. 1465 // Extract shuffle mask.
(...skipping 11 matching lines...) Expand all
1489 new Value(call->ArgumentAt(0)), 1477 new Value(call->ArgumentAt(0)),
1490 mask, 1478 mask,
1491 call->deopt_id()); 1479 call->deopt_id());
1492 ReplaceCall(call, instr); 1480 ReplaceCall(call, instr);
1493 return true; 1481 return true;
1494 } 1482 }
1495 1483
1496 1484
1497 bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call, 1485 bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call,
1498 MethodRecognizer::Kind getter) { 1486 MethodRecognizer::Kind getter) {
1487 if (!ShouldInlineSimd()) {
1488 return false;
1489 }
1499 AddCheckClass(call->ArgumentAt(0), 1490 AddCheckClass(call->ArgumentAt(0),
1500 ICData::ZoneHandle( 1491 ICData::ZoneHandle(
1501 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 1492 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1502 call->deopt_id(), 1493 call->deopt_id(),
1503 call->env(), 1494 call->env(),
1504 call); 1495 call);
1505 Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr( 1496 Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr(
1506 getter, 1497 getter,
1507 new Value(call->ArgumentAt(0)), 1498 new Value(call->ArgumentAt(0)),
1508 call->deopt_id()); 1499 call->deopt_id());
1509 ReplaceCall(call, instr); 1500 ReplaceCall(call, instr);
1510 return true; 1501 return true;
1511 } 1502 }
1512 1503
1513 1504
1505 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
1506 Token::Kind op_kind) {
1507 if (!ShouldInlineSimd()) {
1508 return false;
1509 }
1510 ASSERT(call->ArgumentCount() == 2);
1511 Definition* left = call->ArgumentAt(0);
1512 Definition* right = call->ArgumentAt(1);
1513 // Type check left.
1514 AddCheckClass(left,
1515 ICData::ZoneHandle(
1516 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1517 call->deopt_id(),
1518 call->env(),
1519 call);
1520 // Type check right.
1521 AddCheckClass(right,
1522 ICData::ZoneHandle(
1523 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1524 call->deopt_id(),
1525 call->env(),
1526 call);
1527 // Replace call.
1528 BinaryFloat32x4OpInstr* float32x4_bin_op =
1529 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right),
1530 call->deopt_id());
1531 ReplaceCall(call, float32x4_bin_op);
1532
1533 return true;
1534 }
1535
1536
1537 bool FlowGraphOptimizer::InlineUint32x4BinaryOp(InstanceCallInstr* call,
1538 Token::Kind op_kind) {
1539 if (!ShouldInlineSimd()) {
1540 return false;
1541 }
1542 ASSERT(call->ArgumentCount() == 2);
1543 Definition* left = call->ArgumentAt(0);
1544 Definition* right = call->ArgumentAt(1);
1545 // Type check left.
1546 AddCheckClass(left,
1547 ICData::ZoneHandle(
1548 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1549 call->deopt_id(),
1550 call->env(),
1551 call);
1552 // Type check right.
1553 AddCheckClass(right,
1554 ICData::ZoneHandle(
1555 call->ic_data()->AsUnaryClassChecksForArgNr(1)),
1556 call->deopt_id(),
1557 call->env(),
1558 call);
1559 // Replace call.
1560 BinaryUint32x4OpInstr* uint32x4_bin_op =
1561 new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right),
1562 call->deopt_id());
1563 ReplaceCall(call, uint32x4_bin_op);
1564 return true;
1565 }
1566
1567
1514 // Only unique implicit instance getters can be currently handled. 1568 // Only unique implicit instance getters can be currently handled.
1515 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { 1569 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) {
1516 ASSERT(call->HasICData()); 1570 ASSERT(call->HasICData());
1517 const ICData& ic_data = *call->ic_data(); 1571 const ICData& ic_data = *call->ic_data();
1518 if (ic_data.NumberOfChecks() == 0) { 1572 if (ic_data.NumberOfChecks() == 0) {
1519 // No type feedback collected. 1573 // No type feedback collected.
1520 return false; 1574 return false;
1521 } 1575 }
1522 Function& target = Function::Handle(ic_data.GetTargetAt(0)); 1576 Function& target = Function::Handle(ic_data.GetTargetAt(0));
1523 if (target.kind() == RawFunction::kImplicitGetter) { 1577 if (target.kind() == RawFunction::kImplicitGetter) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
1894 return TryInlineFloat32x4Method(call, recognized_kind); 1948 return TryInlineFloat32x4Method(call, recognized_kind);
1895 } 1949 }
1896 1950
1897 if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) { 1951 if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) {
1898 return TryInlineUint32x4Method(call, recognized_kind); 1952 return TryInlineUint32x4Method(call, recognized_kind);
1899 } 1953 }
1900 return false; 1954 return false;
1901 } 1955 }
1902 1956
1903 1957
1958 bool FlowGraphOptimizer::TryInlineFloat32x4Constructor(
1959 StaticCallInstr* call,
1960 MethodRecognizer::Kind recognized_kind) {
1961 if (!ShouldInlineSimd()) {
1962 return false;
1963 }
1964 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) {
1965 Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call->deopt_id());
1966 ReplaceCall(call, zero);
1967 return true;
1968 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) {
1969 Float32x4SplatInstr* splat =
1970 new Float32x4SplatInstr(new Value(call->ArgumentAt(1)),
1971 call->deopt_id());
1972 ReplaceCall(call, splat);
1973 return true;
1974 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) {
1975 Float32x4ConstructorInstr* con =
1976 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)),
1977 new Value(call->ArgumentAt(2)),
1978 new Value(call->ArgumentAt(3)),
1979 new Value(call->ArgumentAt(4)),
1980 call->deopt_id());
1981 ReplaceCall(call, con);
1982 return true;
1983 }
1984 return false;
1985 }
1986
1987
1988 bool FlowGraphOptimizer::TryInlineUint32x4Constructor(
1989 StaticCallInstr* call,
1990 MethodRecognizer::Kind recognized_kind) {
1991 if (!ShouldInlineSimd()) {
1992 return false;
1993 }
1994 if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) {
1995 Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr(
1996 new Value(call->ArgumentAt(1)),
1997 new Value(call->ArgumentAt(2)),
1998 new Value(call->ArgumentAt(3)),
1999 new Value(call->ArgumentAt(4)),
2000 call->deopt_id());
2001 ReplaceCall(call, con);
2002 return true;
2003 }
2004 return false;
2005 }
2006
2007
1904 bool FlowGraphOptimizer::TryInlineFloat32x4Method( 2008 bool FlowGraphOptimizer::TryInlineFloat32x4Method(
1905 InstanceCallInstr* call, 2009 InstanceCallInstr* call,
1906 MethodRecognizer::Kind recognized_kind) { 2010 MethodRecognizer::Kind recognized_kind) {
2011 if (!ShouldInlineSimd()) {
2012 return false;
2013 }
1907 ASSERT(call->HasICData()); 2014 ASSERT(call->HasICData());
1908 switch (recognized_kind) { 2015 switch (recognized_kind) {
1909 case MethodRecognizer::kFloat32x4Equal: 2016 case MethodRecognizer::kFloat32x4Equal:
1910 case MethodRecognizer::kFloat32x4GreaterThan: 2017 case MethodRecognizer::kFloat32x4GreaterThan:
1911 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: 2018 case MethodRecognizer::kFloat32x4GreaterThanOrEqual:
1912 case MethodRecognizer::kFloat32x4LessThan: 2019 case MethodRecognizer::kFloat32x4LessThan:
1913 case MethodRecognizer::kFloat32x4LessThanOrEqual: 2020 case MethodRecognizer::kFloat32x4LessThanOrEqual:
1914 case MethodRecognizer::kFloat32x4NotEqual: { 2021 case MethodRecognizer::kFloat32x4NotEqual: {
1915 Definition* left = call->ArgumentAt(0); 2022 Definition* left = call->ArgumentAt(0);
1916 Definition* right = call->ArgumentAt(1); 2023 Definition* right = call->ArgumentAt(1);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 } 2160 }
2054 default: 2161 default:
2055 return false; 2162 return false;
2056 } 2163 }
2057 } 2164 }
2058 2165
2059 2166
2060 bool FlowGraphOptimizer::TryInlineUint32x4Method( 2167 bool FlowGraphOptimizer::TryInlineUint32x4Method(
2061 InstanceCallInstr* call, 2168 InstanceCallInstr* call,
2062 MethodRecognizer::Kind recognized_kind) { 2169 MethodRecognizer::Kind recognized_kind) {
2170 if (!ShouldInlineSimd()) {
2171 return false;
2172 }
2063 ASSERT(call->HasICData()); 2173 ASSERT(call->HasICData());
2064 switch (recognized_kind) { 2174 switch (recognized_kind) {
2065 case MethodRecognizer::kUint32x4Select: { 2175 case MethodRecognizer::kUint32x4Select: {
2066 Definition* mask = call->ArgumentAt(0); 2176 Definition* mask = call->ArgumentAt(0);
2067 Definition* trueValue = call->ArgumentAt(1); 2177 Definition* trueValue = call->ArgumentAt(1);
2068 Definition* falseValue = call->ArgumentAt(2); 2178 Definition* falseValue = call->ArgumentAt(2);
2069 // Type check left. 2179 // Type check left.
2070 AddCheckClass(mask, 2180 AddCheckClass(mask,
2071 ICData::ZoneHandle( 2181 ICData::ZoneHandle(
2072 call->ic_data()->AsUnaryClassChecksForArgNr(0)), 2182 call->ic_data()->AsUnaryClassChecksForArgNr(0)),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2119 default: 2229 default:
2120 return false; 2230 return false;
2121 } 2231 }
2122 } 2232 }
2123 2233
2124 2234
2125 bool FlowGraphOptimizer::BuildByteArrayViewLoad( 2235 bool FlowGraphOptimizer::BuildByteArrayViewLoad(
2126 InstanceCallInstr* call, 2236 InstanceCallInstr* call,
2127 intptr_t receiver_cid, 2237 intptr_t receiver_cid,
2128 intptr_t view_cid) { 2238 intptr_t view_cid) {
2239 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2240 return false;
2241 }
2242
2129 Definition* array = call->ArgumentAt(0); 2243 Definition* array = call->ArgumentAt(0);
2130 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); 2244 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
2131 2245
2132 // Optimistically build a smi-checked load for Int32 and Uint32 2246 // Optimistically build a smi-checked load for Int32 and Uint32
2133 // loads on ia32 like we do for normal array loads, and only revert to 2247 // loads on ia32 like we do for normal array loads, and only revert to
2134 // mint case after deoptimizing here. 2248 // mint case after deoptimizing here.
2135 intptr_t deopt_id = Isolate::kNoDeoptId; 2249 intptr_t deopt_id = Isolate::kNoDeoptId;
2136 if ((view_cid == kTypedDataInt32ArrayCid || 2250 if ((view_cid == kTypedDataInt32ArrayCid ||
2137 view_cid == kTypedDataUint32ArrayCid) && 2251 view_cid == kTypedDataUint32ArrayCid) &&
2138 call->ic_data()->deopt_reason() == kDeoptUnknown) { 2252 call->ic_data()->deopt_reason() == kDeoptUnknown) {
2139 deopt_id = call->deopt_id(); 2253 deopt_id = call->deopt_id();
2140 } 2254 }
2141 Definition* byte_index = call->ArgumentAt(1); 2255 Definition* byte_index = call->ArgumentAt(1);
2142 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array), 2256 LoadIndexedInstr* array_op = new LoadIndexedInstr(new Value(array),
2143 new Value(byte_index), 2257 new Value(byte_index),
2144 1, // Index scale. 2258 1, // Index scale.
2145 view_cid, 2259 view_cid,
2146 deopt_id); 2260 deopt_id);
2147 ReplaceCall(call, array_op); 2261 ReplaceCall(call, array_op);
2148 return true; 2262 return true;
2149 } 2263 }
2150 2264
2151 2265
2152 bool FlowGraphOptimizer::BuildByteArrayViewStore( 2266 bool FlowGraphOptimizer::BuildByteArrayViewStore(
2153 InstanceCallInstr* call, 2267 InstanceCallInstr* call,
2154 intptr_t receiver_cid, 2268 intptr_t receiver_cid,
2155 intptr_t view_cid) { 2269 intptr_t view_cid) {
2270 if ((view_cid == kTypedDataFloat32x4ArrayCid) && !ShouldInlineSimd()) {
2271 return false;
2272 }
2156 Definition* array = call->ArgumentAt(0); 2273 Definition* array = call->ArgumentAt(0);
2157 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array); 2274 PrepareByteArrayViewOp(call, receiver_cid, view_cid, &array);
2158 ICData& value_check = ICData::ZoneHandle(); 2275 ICData& value_check = ICData::ZoneHandle();
2159 switch (view_cid) { 2276 switch (view_cid) {
2160 case kTypedDataInt8ArrayCid: 2277 case kTypedDataInt8ArrayCid:
2161 case kTypedDataUint8ArrayCid: 2278 case kTypedDataUint8ArrayCid:
2162 case kTypedDataUint8ClampedArrayCid: 2279 case kTypedDataUint8ClampedArrayCid:
2163 case kExternalTypedDataUint8ArrayCid: 2280 case kExternalTypedDataUint8ArrayCid:
2164 case kExternalTypedDataUint8ClampedArrayCid: 2281 case kExternalTypedDataUint8ClampedArrayCid:
2165 case kTypedDataInt16ArrayCid: 2282 case kTypedDataInt16ArrayCid:
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2496 } 2613 }
2497 2614
2498 2615
2499 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) { 2616 void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
2500 MethodRecognizer::Kind recognized_kind = 2617 MethodRecognizer::Kind recognized_kind =
2501 MethodRecognizer::RecognizeKind(call->function()); 2618 MethodRecognizer::RecognizeKind(call->function());
2502 if (recognized_kind == MethodRecognizer::kMathSqrt) { 2619 if (recognized_kind == MethodRecognizer::kMathSqrt) {
2503 MathSqrtInstr* sqrt = 2620 MathSqrtInstr* sqrt =
2504 new MathSqrtInstr(new Value(call->ArgumentAt(0)), call->deopt_id()); 2621 new MathSqrtInstr(new Value(call->ArgumentAt(0)), call->deopt_id());
2505 ReplaceCall(call, sqrt); 2622 ReplaceCall(call, sqrt);
2506 } else if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { 2623 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) ||
2507 Float32x4ZeroInstr* zero = new Float32x4ZeroInstr(call->deopt_id()); 2624 (recognized_kind == MethodRecognizer::kFloat32x4Splat) ||
2508 ReplaceCall(call, zero); 2625 (recognized_kind == MethodRecognizer::kFloat32x4Constructor)) {
2509 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { 2626 TryInlineFloat32x4Constructor(call, recognized_kind);
2510 Float32x4SplatInstr* splat =
2511 new Float32x4SplatInstr(new Value(call->ArgumentAt(1)),
2512 call->deopt_id());
2513 ReplaceCall(call, splat);
2514 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) {
2515 Float32x4ConstructorInstr* con =
2516 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)),
2517 new Value(call->ArgumentAt(2)),
2518 new Value(call->ArgumentAt(3)),
2519 new Value(call->ArgumentAt(4)),
2520 call->deopt_id());
2521 ReplaceCall(call, con);
2522 } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) { 2627 } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) {
2523 Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr( 2628 TryInlineUint32x4Constructor(call, recognized_kind);
2524 new Value(call->ArgumentAt(1)),
2525 new Value(call->ArgumentAt(2)),
2526 new Value(call->ArgumentAt(3)),
2527 new Value(call->ArgumentAt(4)),
2528 call->deopt_id());
2529 ReplaceCall(call, con);
2530 } else if (recognized_kind == MethodRecognizer::kObjectConstructor) { 2629 } else if (recognized_kind == MethodRecognizer::kObjectConstructor) {
2531 // Remove the original push arguments. 2630 // Remove the original push arguments.
2532 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 2631 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2533 PushArgumentInstr* push = call->PushArgumentAt(i); 2632 PushArgumentInstr* push = call->PushArgumentAt(i);
2534 push->ReplaceUsesWith(push->value()->definition()); 2633 push->ReplaceUsesWith(push->value()->definition());
2535 push->RemoveFromGraph(); 2634 push->RemoveFromGraph();
2536 } 2635 }
2537 // Manually replace call with global null constant. ReplaceCall can't 2636 // Manually replace call with global null constant. ReplaceCall can't
2538 // be used for definitions that are already in the graph. 2637 // be used for definitions that are already in the graph.
2539 call->ReplaceUsesWith(flow_graph_->constant_null()); 2638 call->ReplaceUsesWith(flow_graph_->constant_null());
(...skipping 4704 matching lines...) Expand 10 before | Expand all | Expand 10 after
7244 7343
7245 // Insert materializations at environment uses. 7344 // Insert materializations at environment uses.
7246 const Class& cls = Class::Handle(alloc->constructor().Owner()); 7345 const Class& cls = Class::Handle(alloc->constructor().Owner());
7247 for (intptr_t i = 0; i < exits.length(); i++) { 7346 for (intptr_t i = 0; i < exits.length(); i++) {
7248 CreateMaterializationAt(exits[i], alloc, cls, *fields); 7347 CreateMaterializationAt(exits[i], alloc, cls, *fields);
7249 } 7348 }
7250 } 7349 }
7251 7350
7252 7351
7253 } // namespace dart 7352 } // 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