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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id); | 386 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id); |
387 } | 387 } |
388 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) { | 388 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) { |
389 ASSERT((deopt_target != NULL) || | 389 ASSERT((deopt_target != NULL) || |
390 (use->Type()->ToCid() == kFloat32x4Cid)); | 390 (use->Type()->ToCid() == kFloat32x4Cid)); |
391 const intptr_t deopt_id = (deopt_target != NULL) ? | 391 const intptr_t deopt_id = (deopt_target != NULL) ? |
392 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 392 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
393 converted = new UnboxFloat32x4Instr(use->CopyWithType(), deopt_id); | 393 converted = new UnboxFloat32x4Instr(use->CopyWithType(), deopt_id); |
394 } else if ((from == kUnboxedFloat32x4) && (to == kTagged)) { | 394 } else if ((from == kUnboxedFloat32x4) && (to == kTagged)) { |
395 converted = new BoxFloat32x4Instr(use->CopyWithType()); | 395 converted = new BoxFloat32x4Instr(use->CopyWithType()); |
396 } else if ((from == kTagged) && (to == kUnboxedUint32x4)) { | 396 } else if ((from == kTagged) && (to == kUnboxedInt32x4)) { |
397 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kUint32x4Cid)); | 397 ASSERT((deopt_target != NULL) || (use->Type()->ToCid() == kInt32x4Cid)); |
398 const intptr_t deopt_id = (deopt_target != NULL) ? | 398 const intptr_t deopt_id = (deopt_target != NULL) ? |
399 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 399 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
400 converted = new UnboxUint32x4Instr(use->CopyWithType(), deopt_id); | 400 converted = new UnboxInt32x4Instr(use->CopyWithType(), deopt_id); |
401 } else if ((from == kUnboxedUint32x4) && (to == kTagged)) { | 401 } else if ((from == kUnboxedInt32x4) && (to == kTagged)) { |
402 converted = new BoxUint32x4Instr(use->CopyWithType()); | 402 converted = new BoxInt32x4Instr(use->CopyWithType()); |
403 } else { | 403 } else { |
404 // We have failed to find a suitable conversion instruction. | 404 // We have failed to find a suitable conversion instruction. |
405 // Insert two "dummy" conversion instructions with the correct | 405 // Insert two "dummy" conversion instructions with the correct |
406 // "from" and "to" representation. The inserted instructions will | 406 // "from" and "to" representation. The inserted instructions will |
407 // trigger a deoptimization if executed. See #12417 for a discussion. | 407 // trigger a deoptimization if executed. See #12417 for a discussion. |
408 const intptr_t deopt_id = (deopt_target != NULL) ? | 408 const intptr_t deopt_id = (deopt_target != NULL) ? |
409 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 409 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
410 ASSERT(from != kTagged); | 410 ASSERT(from != kTagged); |
411 ASSERT(to != kTagged); | 411 ASSERT(to != kTagged); |
412 Definition* boxed = NULL; | 412 Definition* boxed = NULL; |
413 if (from == kUnboxedDouble) { | 413 if (from == kUnboxedDouble) { |
414 boxed = new BoxDoubleInstr(use->CopyWithType()); | 414 boxed = new BoxDoubleInstr(use->CopyWithType()); |
415 } else if (from == kUnboxedUint32x4) { | 415 } else if (from == kUnboxedInt32x4) { |
416 boxed = new BoxUint32x4Instr(use->CopyWithType()); | 416 boxed = new BoxInt32x4Instr(use->CopyWithType()); |
417 } else if (from == kUnboxedFloat32x4) { | 417 } else if (from == kUnboxedFloat32x4) { |
418 boxed = new BoxFloat32x4Instr(use->CopyWithType()); | 418 boxed = new BoxFloat32x4Instr(use->CopyWithType()); |
419 } else if (from == kUnboxedMint) { | 419 } else if (from == kUnboxedMint) { |
420 boxed = new BoxIntegerInstr(use->CopyWithType()); | 420 boxed = new BoxIntegerInstr(use->CopyWithType()); |
421 } else { | 421 } else { |
422 UNIMPLEMENTED(); | 422 UNIMPLEMENTED(); |
423 } | 423 } |
424 use->BindTo(boxed); | 424 use->BindTo(boxed); |
425 InsertBefore(insert_before, boxed, NULL, Definition::kValue); | 425 InsertBefore(insert_before, boxed, NULL, Definition::kValue); |
426 Value* to_value = new Value(boxed); | 426 Value* to_value = new Value(boxed); |
427 if (to == kUnboxedDouble) { | 427 if (to == kUnboxedDouble) { |
428 converted = new UnboxDoubleInstr(to_value, deopt_id); | 428 converted = new UnboxDoubleInstr(to_value, deopt_id); |
429 } else if (to == kUnboxedUint32x4) { | 429 } else if (to == kUnboxedInt32x4) { |
430 converted = new UnboxUint32x4Instr(to_value, deopt_id); | 430 converted = new UnboxInt32x4Instr(to_value, deopt_id); |
431 } else if (to == kUnboxedFloat32x4) { | 431 } else if (to == kUnboxedFloat32x4) { |
432 converted = new UnboxFloat32x4Instr(to_value, deopt_id); | 432 converted = new UnboxFloat32x4Instr(to_value, deopt_id); |
433 } else if (to == kUnboxedMint) { | 433 } else if (to == kUnboxedMint) { |
434 converted = new UnboxIntegerInstr(to_value, deopt_id); | 434 converted = new UnboxIntegerInstr(to_value, deopt_id); |
435 } else { | 435 } else { |
436 UNIMPLEMENTED(); | 436 UNIMPLEMENTED(); |
437 } | 437 } |
438 } | 438 } |
439 ASSERT(converted != NULL); | 439 ASSERT(converted != NULL); |
440 use->BindTo(converted); | 440 use->BindTo(converted); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 | 485 |
486 switch (phi->Type()->ToCid()) { | 486 switch (phi->Type()->ToCid()) { |
487 case kDoubleCid: | 487 case kDoubleCid: |
488 unboxed = kUnboxedDouble; | 488 unboxed = kUnboxedDouble; |
489 break; | 489 break; |
490 case kFloat32x4Cid: | 490 case kFloat32x4Cid: |
491 if (ShouldInlineSimd()) { | 491 if (ShouldInlineSimd()) { |
492 unboxed = kUnboxedFloat32x4; | 492 unboxed = kUnboxedFloat32x4; |
493 } | 493 } |
494 break; | 494 break; |
495 case kUint32x4Cid: | 495 case kInt32x4Cid: |
496 if (ShouldInlineSimd()) { | 496 if (ShouldInlineSimd()) { |
497 unboxed = kUnboxedUint32x4; | 497 unboxed = kUnboxedInt32x4; |
498 } | 498 } |
499 break; | 499 break; |
500 } | 500 } |
501 | 501 |
502 if (unboxed != current) { | 502 if (unboxed != current) { |
503 phi->set_representation(unboxed); | 503 phi->set_representation(unboxed); |
504 return true; | 504 return true; |
505 } | 505 } |
506 | 506 |
507 return false; | 507 return false; |
508 } | 508 } |
509 | 509 |
510 | 510 |
511 void FlowGraphOptimizer::SelectRepresentations() { | 511 void FlowGraphOptimizer::SelectRepresentations() { |
512 // Convervatively unbox all phis that were proven to be of Double, | 512 // Convervatively unbox all phis that were proven to be of Double, |
513 // Float32x4, or Uint32x4 type. | 513 // Float32x4, or Int32x4 type. |
514 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 514 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
515 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); | 515 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); |
516 if (join_entry != NULL) { | 516 if (join_entry != NULL) { |
517 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { | 517 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) { |
518 PhiInstr* phi = it.Current(); | 518 PhiInstr* phi = it.Current(); |
519 UnboxPhi(phi); | 519 UnboxPhi(phi); |
520 } | 520 } |
521 } | 521 } |
522 } | 522 } |
523 | 523 |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 return kTypedDataInt32ArrayCid; | 805 return kTypedDataInt32ArrayCid; |
806 | 806 |
807 case MethodRecognizer::kUint32ArrayGetIndexed: | 807 case MethodRecognizer::kUint32ArrayGetIndexed: |
808 case MethodRecognizer::kUint32ArraySetIndexed: | 808 case MethodRecognizer::kUint32ArraySetIndexed: |
809 return kTypedDataUint32ArrayCid; | 809 return kTypedDataUint32ArrayCid; |
810 | 810 |
811 case MethodRecognizer::kFloat32x4ArrayGetIndexed: | 811 case MethodRecognizer::kFloat32x4ArrayGetIndexed: |
812 case MethodRecognizer::kFloat32x4ArraySetIndexed: | 812 case MethodRecognizer::kFloat32x4ArraySetIndexed: |
813 return kTypedDataFloat32x4ArrayCid; | 813 return kTypedDataFloat32x4ArrayCid; |
814 | 814 |
815 case MethodRecognizer::kUint32x4ArrayGetIndexed: | 815 case MethodRecognizer::kInt32x4ArrayGetIndexed: |
816 case MethodRecognizer::kUint32x4ArraySetIndexed: | 816 case MethodRecognizer::kInt32x4ArraySetIndexed: |
817 return kTypedDataUint32x4ArrayCid; | 817 return kTypedDataInt32x4ArrayCid; |
818 | 818 |
819 default: | 819 default: |
820 break; | 820 break; |
821 } | 821 } |
822 return kIllegalCid; | 822 return kIllegalCid; |
823 } | 823 } |
824 | 824 |
825 | 825 |
826 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { | 826 bool FlowGraphOptimizer::TryReplaceWithStoreIndexed(InstanceCallInstr* call) { |
827 // Check for monomorphic IC data. | 827 // Check for monomorphic IC data. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
969 &cursor); | 969 &cursor); |
970 | 970 |
971 // Check if store barrier is needed. Byte arrays don't need a store barrier. | 971 // Check if store barrier is needed. Byte arrays don't need a store barrier. |
972 StoreBarrierType needs_store_barrier = | 972 StoreBarrierType needs_store_barrier = |
973 (RawObject::IsTypedDataClassId(array_cid) || | 973 (RawObject::IsTypedDataClassId(array_cid) || |
974 RawObject::IsTypedDataViewClassId(array_cid) || | 974 RawObject::IsTypedDataViewClassId(array_cid) || |
975 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier | 975 RawObject::IsExternalTypedDataClassId(array_cid)) ? kNoStoreBarrier |
976 : kEmitStoreBarrier; | 976 : kEmitStoreBarrier; |
977 if (!value_check.IsNull()) { | 977 if (!value_check.IsNull()) { |
978 // No store barrier needed because checked value is a smi, an unboxed mint, | 978 // No store barrier needed because checked value is a smi, an unboxed mint, |
979 // an unboxed double, an unboxed Float32x4, or unboxed Uint32x4. | 979 // an unboxed double, an unboxed Float32x4, or unboxed Int32x4. |
980 needs_store_barrier = kNoStoreBarrier; | 980 needs_store_barrier = kNoStoreBarrier; |
981 Instruction* check = | 981 Instruction* check = |
982 GetCheckClass(stored_value, value_check, call->deopt_id()); | 982 GetCheckClass(stored_value, value_check, call->deopt_id()); |
983 cursor = flow_graph()->AppendTo(cursor, | 983 cursor = flow_graph()->AppendTo(cursor, |
984 check, | 984 check, |
985 call->env(), | 985 call->env(), |
986 Definition::kEffect); | 986 Definition::kEffect); |
987 } | 987 } |
988 | 988 |
989 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); | 989 intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(array_cid); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 ic_data, entry, last); | 1115 ic_data, entry, last); |
1116 case MethodRecognizer::kByteArrayBaseGetFloat64: | 1116 case MethodRecognizer::kByteArrayBaseGetFloat64: |
1117 return InlineByteArrayViewLoad(call, receiver, receiver_cid, | 1117 return InlineByteArrayViewLoad(call, receiver, receiver_cid, |
1118 kTypedDataFloat64ArrayCid, | 1118 kTypedDataFloat64ArrayCid, |
1119 ic_data, entry, last); | 1119 ic_data, entry, last); |
1120 case MethodRecognizer::kByteArrayBaseGetFloat32x4: | 1120 case MethodRecognizer::kByteArrayBaseGetFloat32x4: |
1121 if (!ShouldInlineSimd()) return false; | 1121 if (!ShouldInlineSimd()) return false; |
1122 return InlineByteArrayViewLoad(call, receiver, receiver_cid, | 1122 return InlineByteArrayViewLoad(call, receiver, receiver_cid, |
1123 kTypedDataFloat32x4ArrayCid, | 1123 kTypedDataFloat32x4ArrayCid, |
1124 ic_data, entry, last); | 1124 ic_data, entry, last); |
1125 case MethodRecognizer::kByteArrayBaseGetUint32x4: | 1125 case MethodRecognizer::kByteArrayBaseGetInt32x4: |
1126 if (!ShouldInlineSimd()) return false; | 1126 if (!ShouldInlineSimd()) return false; |
1127 return InlineByteArrayViewLoad(call, receiver, receiver_cid, | 1127 return InlineByteArrayViewLoad(call, receiver, receiver_cid, |
1128 kTypedDataUint32x4ArrayCid, | 1128 kTypedDataInt32x4ArrayCid, |
1129 ic_data, entry, last); | 1129 ic_data, entry, last); |
1130 default: | 1130 default: |
1131 return false; | 1131 return false; |
1132 } | 1132 } |
1133 } | 1133 } |
1134 | 1134 |
1135 | 1135 |
1136 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, | 1136 intptr_t FlowGraphOptimizer::PrepareInlineIndexedOp(Instruction* call, |
1137 intptr_t array_cid, | 1137 intptr_t array_cid, |
1138 Definition** array, | 1138 Definition** array, |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 } else if (HasTwoMintOrSmi(ic_data) && | 1363 } else if (HasTwoMintOrSmi(ic_data) && |
1364 FlowGraphCompiler::SupportsUnboxedMints()) { | 1364 FlowGraphCompiler::SupportsUnboxedMints()) { |
1365 // Don't generate mint code if the IC data is marked because of an | 1365 // Don't generate mint code if the IC data is marked because of an |
1366 // overflow. | 1366 // overflow. |
1367 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; | 1367 if (ic_data.deopt_reason() == kDeoptBinaryMintOp) return false; |
1368 operands_type = kMintCid; | 1368 operands_type = kMintCid; |
1369 } else if (ShouldSpecializeForDouble(ic_data)) { | 1369 } else if (ShouldSpecializeForDouble(ic_data)) { |
1370 operands_type = kDoubleCid; | 1370 operands_type = kDoubleCid; |
1371 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { | 1371 } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) { |
1372 operands_type = kFloat32x4Cid; | 1372 operands_type = kFloat32x4Cid; |
1373 } else if (HasOnlyTwoOf(ic_data, kUint32x4Cid)) { | 1373 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { |
1374 operands_type = kUint32x4Cid; | 1374 operands_type = kInt32x4Cid; |
1375 } else { | 1375 } else { |
1376 return false; | 1376 return false; |
1377 } | 1377 } |
1378 break; | 1378 break; |
1379 case Token::kMUL: | 1379 case Token::kMUL: |
1380 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1380 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
1381 // Don't generate smi code if the IC data is marked because of an | 1381 // Don't generate smi code if the IC data is marked because of an |
1382 // overflow. | 1382 // overflow. |
1383 // TODO(fschneider): Add unboxed mint multiplication. | 1383 // TODO(fschneider): Add unboxed mint multiplication. |
1384 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; | 1384 if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false; |
(...skipping 23 matching lines...) Expand all Loading... |
1408 return false; | 1408 return false; |
1409 } | 1409 } |
1410 break; | 1410 break; |
1411 case Token::kBIT_AND: | 1411 case Token::kBIT_AND: |
1412 case Token::kBIT_OR: | 1412 case Token::kBIT_OR: |
1413 case Token::kBIT_XOR: | 1413 case Token::kBIT_XOR: |
1414 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1414 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
1415 operands_type = kSmiCid; | 1415 operands_type = kSmiCid; |
1416 } else if (HasTwoMintOrSmi(ic_data)) { | 1416 } else if (HasTwoMintOrSmi(ic_data)) { |
1417 operands_type = kMintCid; | 1417 operands_type = kMintCid; |
1418 } else if (HasOnlyTwoOf(ic_data, kUint32x4Cid)) { | 1418 } else if (HasOnlyTwoOf(ic_data, kInt32x4Cid)) { |
1419 operands_type = kUint32x4Cid; | 1419 operands_type = kInt32x4Cid; |
1420 } else { | 1420 } else { |
1421 return false; | 1421 return false; |
1422 } | 1422 } |
1423 break; | 1423 break; |
1424 case Token::kSHR: | 1424 case Token::kSHR: |
1425 case Token::kSHL: | 1425 case Token::kSHL: |
1426 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 1426 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
1427 // Left shift may overflow from smi into mint or big ints. | 1427 // Left shift may overflow from smi into mint or big ints. |
1428 // Don't generate smi code if the IC data is marked because | 1428 // Don't generate smi code if the IC data is marked because |
1429 // of an overflow. | 1429 // of an overflow. |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1483 call->deopt_id()); | 1483 call->deopt_id()); |
1484 ReplaceCall(call, shift_op); | 1484 ReplaceCall(call, shift_op); |
1485 } else { | 1485 } else { |
1486 BinaryMintOpInstr* bin_op = | 1486 BinaryMintOpInstr* bin_op = |
1487 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), | 1487 new BinaryMintOpInstr(op_kind, new Value(left), new Value(right), |
1488 call->deopt_id()); | 1488 call->deopt_id()); |
1489 ReplaceCall(call, bin_op); | 1489 ReplaceCall(call, bin_op); |
1490 } | 1490 } |
1491 } else if (operands_type == kFloat32x4Cid) { | 1491 } else if (operands_type == kFloat32x4Cid) { |
1492 return InlineFloat32x4BinaryOp(call, op_kind); | 1492 return InlineFloat32x4BinaryOp(call, op_kind); |
1493 } else if (operands_type == kUint32x4Cid) { | 1493 } else if (operands_type == kInt32x4Cid) { |
1494 return InlineUint32x4BinaryOp(call, op_kind); | 1494 return InlineInt32x4BinaryOp(call, op_kind); |
1495 } else if (op_kind == Token::kMOD) { | 1495 } else if (op_kind == Token::kMOD) { |
1496 // TODO(vegorov): implement fast path code for modulo. | 1496 // TODO(vegorov): implement fast path code for modulo. |
1497 ASSERT(operands_type == kSmiCid); | 1497 ASSERT(operands_type == kSmiCid); |
1498 if (!right->IsConstant()) return false; | 1498 if (!right->IsConstant()) return false; |
1499 const Object& obj = right->AsConstant()->value(); | 1499 const Object& obj = right->AsConstant()->value(); |
1500 if (!obj.IsSmi()) return false; | 1500 if (!obj.IsSmi()) return false; |
1501 const intptr_t value = Smi::Cast(obj).Value(); | 1501 const intptr_t value = Smi::Cast(obj).Value(); |
1502 if (!Utils::IsPowerOfTwo(value)) return false; | 1502 if (!Utils::IsPowerOfTwo(value)) return false; |
1503 | 1503 |
1504 // Insert smi check and attach a copy of the original environment | 1504 // Insert smi check and attach a copy of the original environment |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1748 mask, | 1748 mask, |
1749 call->deopt_id()); | 1749 call->deopt_id()); |
1750 ReplaceCall(call, instr); | 1750 ReplaceCall(call, instr); |
1751 return true; | 1751 return true; |
1752 } | 1752 } |
1753 UNREACHABLE(); | 1753 UNREACHABLE(); |
1754 return false; | 1754 return false; |
1755 } | 1755 } |
1756 | 1756 |
1757 | 1757 |
1758 bool FlowGraphOptimizer::InlineUint32x4Getter(InstanceCallInstr* call, | 1758 bool FlowGraphOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, |
1759 MethodRecognizer::Kind getter) { | 1759 MethodRecognizer::Kind getter) { |
1760 if (!ShouldInlineSimd()) { | 1760 if (!ShouldInlineSimd()) { |
1761 return false; | 1761 return false; |
1762 } | 1762 } |
1763 AddCheckClass(call->ArgumentAt(0), | 1763 AddCheckClass(call->ArgumentAt(0), |
1764 ICData::ZoneHandle( | 1764 ICData::ZoneHandle( |
1765 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1765 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
1766 call->deopt_id(), | 1766 call->deopt_id(), |
1767 call->env(), | 1767 call->env(), |
1768 call); | 1768 call); |
1769 intptr_t mask = 0; | 1769 intptr_t mask = 0; |
1770 if ((getter == MethodRecognizer::kUint32x4Shuffle) || | 1770 if ((getter == MethodRecognizer::kInt32x4Shuffle) || |
1771 (getter == MethodRecognizer::kUint32x4ShuffleMix)) { | 1771 (getter == MethodRecognizer::kInt32x4ShuffleMix)) { |
1772 // Extract shuffle mask. | 1772 // Extract shuffle mask. |
1773 Definition* mask_definition = NULL; | 1773 Definition* mask_definition = NULL; |
1774 if (getter == MethodRecognizer::kUint32x4Shuffle) { | 1774 if (getter == MethodRecognizer::kInt32x4Shuffle) { |
1775 ASSERT(call->ArgumentCount() == 2); | 1775 ASSERT(call->ArgumentCount() == 2); |
1776 mask_definition = call->ArgumentAt(1); | 1776 mask_definition = call->ArgumentAt(1); |
1777 } else { | 1777 } else { |
1778 ASSERT(getter == MethodRecognizer::kUint32x4ShuffleMix); | 1778 ASSERT(getter == MethodRecognizer::kInt32x4ShuffleMix); |
1779 ASSERT(call->ArgumentCount() == 3); | 1779 ASSERT(call->ArgumentCount() == 3); |
1780 mask_definition = call->ArgumentAt(2); | 1780 mask_definition = call->ArgumentAt(2); |
1781 } | 1781 } |
1782 if (!mask_definition->IsConstant()) { | 1782 if (!mask_definition->IsConstant()) { |
1783 return false; | 1783 return false; |
1784 } | 1784 } |
1785 ASSERT(mask_definition->IsConstant()); | 1785 ASSERT(mask_definition->IsConstant()); |
1786 ConstantInstr* constant_instruction = mask_definition->AsConstant(); | 1786 ConstantInstr* constant_instruction = mask_definition->AsConstant(); |
1787 const Object& constant_mask = constant_instruction->value(); | 1787 const Object& constant_mask = constant_instruction->value(); |
1788 if (!constant_mask.IsSmi()) { | 1788 if (!constant_mask.IsSmi()) { |
1789 return false; | 1789 return false; |
1790 } | 1790 } |
1791 ASSERT(constant_mask.IsSmi()); | 1791 ASSERT(constant_mask.IsSmi()); |
1792 mask = Smi::Cast(constant_mask).Value(); | 1792 mask = Smi::Cast(constant_mask).Value(); |
1793 if ((mask < 0) || (mask > 255)) { | 1793 if ((mask < 0) || (mask > 255)) { |
1794 // Not a valid mask. | 1794 // Not a valid mask. |
1795 return false; | 1795 return false; |
1796 } | 1796 } |
1797 } | 1797 } |
1798 if (getter == MethodRecognizer::kUint32x4GetSignMask) { | 1798 if (getter == MethodRecognizer::kInt32x4GetSignMask) { |
1799 Simd32x4GetSignMaskInstr* instr = new Simd32x4GetSignMaskInstr( | 1799 Simd32x4GetSignMaskInstr* instr = new Simd32x4GetSignMaskInstr( |
1800 getter, | 1800 getter, |
1801 new Value(call->ArgumentAt(0)), | 1801 new Value(call->ArgumentAt(0)), |
1802 call->deopt_id()); | 1802 call->deopt_id()); |
1803 ReplaceCall(call, instr); | 1803 ReplaceCall(call, instr); |
1804 return true; | 1804 return true; |
1805 } else if (getter == MethodRecognizer::kUint32x4ShuffleMix) { | 1805 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) { |
1806 Simd32x4ShuffleMixInstr* instr = new Simd32x4ShuffleMixInstr( | 1806 Simd32x4ShuffleMixInstr* instr = new Simd32x4ShuffleMixInstr( |
1807 getter, | 1807 getter, |
1808 new Value(call->ArgumentAt(0)), | 1808 new Value(call->ArgumentAt(0)), |
1809 new Value(call->ArgumentAt(1)), | 1809 new Value(call->ArgumentAt(1)), |
1810 mask, | 1810 mask, |
1811 call->deopt_id()); | 1811 call->deopt_id()); |
1812 ReplaceCall(call, instr); | 1812 ReplaceCall(call, instr); |
1813 return true; | 1813 return true; |
1814 } else if (getter == MethodRecognizer::kUint32x4Shuffle) { | 1814 } else if (getter == MethodRecognizer::kInt32x4Shuffle) { |
1815 Simd32x4ShuffleInstr* instr = new Simd32x4ShuffleInstr( | 1815 Simd32x4ShuffleInstr* instr = new Simd32x4ShuffleInstr( |
1816 getter, | 1816 getter, |
1817 new Value(call->ArgumentAt(0)), | 1817 new Value(call->ArgumentAt(0)), |
1818 mask, | 1818 mask, |
1819 call->deopt_id()); | 1819 call->deopt_id()); |
1820 ReplaceCall(call, instr); | 1820 ReplaceCall(call, instr); |
1821 return true; | 1821 return true; |
1822 } else { | 1822 } else { |
1823 Uint32x4GetFlagInstr* instr = new Uint32x4GetFlagInstr( | 1823 Int32x4GetFlagInstr* instr = new Int32x4GetFlagInstr( |
1824 getter, | 1824 getter, |
1825 new Value(call->ArgumentAt(0)), | 1825 new Value(call->ArgumentAt(0)), |
1826 call->deopt_id()); | 1826 call->deopt_id()); |
1827 ReplaceCall(call, instr); | 1827 ReplaceCall(call, instr); |
1828 return true; | 1828 return true; |
1829 } | 1829 } |
1830 } | 1830 } |
1831 | 1831 |
1832 | 1832 |
1833 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 1833 bool FlowGraphOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, |
(...skipping 21 matching lines...) Expand all Loading... |
1855 // Replace call. | 1855 // Replace call. |
1856 BinaryFloat32x4OpInstr* float32x4_bin_op = | 1856 BinaryFloat32x4OpInstr* float32x4_bin_op = |
1857 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), | 1857 new BinaryFloat32x4OpInstr(op_kind, new Value(left), new Value(right), |
1858 call->deopt_id()); | 1858 call->deopt_id()); |
1859 ReplaceCall(call, float32x4_bin_op); | 1859 ReplaceCall(call, float32x4_bin_op); |
1860 | 1860 |
1861 return true; | 1861 return true; |
1862 } | 1862 } |
1863 | 1863 |
1864 | 1864 |
1865 bool FlowGraphOptimizer::InlineUint32x4BinaryOp(InstanceCallInstr* call, | 1865 bool FlowGraphOptimizer::InlineInt32x4BinaryOp(InstanceCallInstr* call, |
1866 Token::Kind op_kind) { | 1866 Token::Kind op_kind) { |
1867 if (!ShouldInlineSimd()) { | 1867 if (!ShouldInlineSimd()) { |
1868 return false; | 1868 return false; |
1869 } | 1869 } |
1870 ASSERT(call->ArgumentCount() == 2); | 1870 ASSERT(call->ArgumentCount() == 2); |
1871 Definition* left = call->ArgumentAt(0); | 1871 Definition* left = call->ArgumentAt(0); |
1872 Definition* right = call->ArgumentAt(1); | 1872 Definition* right = call->ArgumentAt(1); |
1873 // Type check left. | 1873 // Type check left. |
1874 AddCheckClass(left, | 1874 AddCheckClass(left, |
1875 ICData::ZoneHandle( | 1875 ICData::ZoneHandle( |
1876 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1876 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
1877 call->deopt_id(), | 1877 call->deopt_id(), |
1878 call->env(), | 1878 call->env(), |
1879 call); | 1879 call); |
1880 // Type check right. | 1880 // Type check right. |
1881 AddCheckClass(right, | 1881 AddCheckClass(right, |
1882 ICData::ZoneHandle( | 1882 ICData::ZoneHandle( |
1883 call->ic_data()->AsUnaryClassChecksForArgNr(1)), | 1883 call->ic_data()->AsUnaryClassChecksForArgNr(1)), |
1884 call->deopt_id(), | 1884 call->deopt_id(), |
1885 call->env(), | 1885 call->env(), |
1886 call); | 1886 call); |
1887 // Replace call. | 1887 // Replace call. |
1888 BinaryUint32x4OpInstr* uint32x4_bin_op = | 1888 BinaryInt32x4OpInstr* int32x4_bin_op = |
1889 new BinaryUint32x4OpInstr(op_kind, new Value(left), new Value(right), | 1889 new BinaryInt32x4OpInstr(op_kind, new Value(left), new Value(right), |
1890 call->deopt_id()); | 1890 call->deopt_id()); |
1891 ReplaceCall(call, uint32x4_bin_op); | 1891 ReplaceCall(call, int32x4_bin_op); |
1892 return true; | 1892 return true; |
1893 } | 1893 } |
1894 | 1894 |
1895 | 1895 |
1896 // Only unique implicit instance getters can be currently handled. | 1896 // Only unique implicit instance getters can be currently handled. |
1897 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { | 1897 bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
1898 ASSERT(call->HasICData()); | 1898 ASSERT(call->HasICData()); |
1899 const ICData& ic_data = *call->ic_data(); | 1899 const ICData& ic_data = *call->ic_data(); |
1900 if (ic_data.NumberOfChecks() == 0) { | 1900 if (ic_data.NumberOfChecks() == 0) { |
1901 // No type feedback collected. | 1901 // No type feedback collected. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1980 case kExternalTypedDataUint8ArrayCid: | 1980 case kExternalTypedDataUint8ArrayCid: |
1981 case kTypedDataUint8ClampedArrayCid: | 1981 case kTypedDataUint8ClampedArrayCid: |
1982 case kExternalTypedDataUint8ClampedArrayCid: | 1982 case kExternalTypedDataUint8ClampedArrayCid: |
1983 case kTypedDataInt16ArrayCid: | 1983 case kTypedDataInt16ArrayCid: |
1984 case kTypedDataUint16ArrayCid: | 1984 case kTypedDataUint16ArrayCid: |
1985 case kTypedDataInt32ArrayCid: | 1985 case kTypedDataInt32ArrayCid: |
1986 case kTypedDataUint32ArrayCid: | 1986 case kTypedDataUint32ArrayCid: |
1987 case kTypedDataFloat32ArrayCid: | 1987 case kTypedDataFloat32ArrayCid: |
1988 case kTypedDataFloat64ArrayCid: | 1988 case kTypedDataFloat64ArrayCid: |
1989 case kTypedDataFloat32x4ArrayCid: | 1989 case kTypedDataFloat32x4ArrayCid: |
1990 case kTypedDataUint32x4ArrayCid: | 1990 case kTypedDataInt32x4ArrayCid: |
1991 return true; | 1991 return true; |
1992 default: | 1992 default: |
1993 return false; | 1993 return false; |
1994 } | 1994 } |
1995 } | 1995 } |
1996 | 1996 |
1997 | 1997 |
1998 // Inline only simple, frequently called core library methods. | 1998 // Inline only simple, frequently called core library methods. |
1999 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { | 1999 bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { |
2000 ASSERT(call->HasICData()); | 2000 ASSERT(call->HasICData()); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2154 case MethodRecognizer::kByteArrayBaseGetInt32: | 2154 case MethodRecognizer::kByteArrayBaseGetInt32: |
2155 return BuildByteArrayViewLoad(call, kTypedDataInt32ArrayCid); | 2155 return BuildByteArrayViewLoad(call, kTypedDataInt32ArrayCid); |
2156 case MethodRecognizer::kByteArrayBaseGetUint32: | 2156 case MethodRecognizer::kByteArrayBaseGetUint32: |
2157 return BuildByteArrayViewLoad(call, kTypedDataUint32ArrayCid); | 2157 return BuildByteArrayViewLoad(call, kTypedDataUint32ArrayCid); |
2158 case MethodRecognizer::kByteArrayBaseGetFloat32: | 2158 case MethodRecognizer::kByteArrayBaseGetFloat32: |
2159 return BuildByteArrayViewLoad(call, kTypedDataFloat32ArrayCid); | 2159 return BuildByteArrayViewLoad(call, kTypedDataFloat32ArrayCid); |
2160 case MethodRecognizer::kByteArrayBaseGetFloat64: | 2160 case MethodRecognizer::kByteArrayBaseGetFloat64: |
2161 return BuildByteArrayViewLoad(call, kTypedDataFloat64ArrayCid); | 2161 return BuildByteArrayViewLoad(call, kTypedDataFloat64ArrayCid); |
2162 case MethodRecognizer::kByteArrayBaseGetFloat32x4: | 2162 case MethodRecognizer::kByteArrayBaseGetFloat32x4: |
2163 return BuildByteArrayViewLoad(call, kTypedDataFloat32x4ArrayCid); | 2163 return BuildByteArrayViewLoad(call, kTypedDataFloat32x4ArrayCid); |
2164 case MethodRecognizer::kByteArrayBaseGetUint32x4: | 2164 case MethodRecognizer::kByteArrayBaseGetInt32x4: |
2165 return BuildByteArrayViewLoad(call, kTypedDataUint32x4ArrayCid); | 2165 return BuildByteArrayViewLoad(call, kTypedDataInt32x4ArrayCid); |
2166 | 2166 |
2167 // ByteArray setters. | 2167 // ByteArray setters. |
2168 case MethodRecognizer::kByteArrayBaseSetInt8: | 2168 case MethodRecognizer::kByteArrayBaseSetInt8: |
2169 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid); | 2169 return BuildByteArrayViewStore(call, kTypedDataInt8ArrayCid); |
2170 case MethodRecognizer::kByteArrayBaseSetUint8: | 2170 case MethodRecognizer::kByteArrayBaseSetUint8: |
2171 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid); | 2171 return BuildByteArrayViewStore(call, kTypedDataUint8ArrayCid); |
2172 case MethodRecognizer::kByteArrayBaseSetInt16: | 2172 case MethodRecognizer::kByteArrayBaseSetInt16: |
2173 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid); | 2173 return BuildByteArrayViewStore(call, kTypedDataInt16ArrayCid); |
2174 case MethodRecognizer::kByteArrayBaseSetUint16: | 2174 case MethodRecognizer::kByteArrayBaseSetUint16: |
2175 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid); | 2175 return BuildByteArrayViewStore(call, kTypedDataUint16ArrayCid); |
2176 case MethodRecognizer::kByteArrayBaseSetInt32: | 2176 case MethodRecognizer::kByteArrayBaseSetInt32: |
2177 return BuildByteArrayViewStore(call, kTypedDataInt32ArrayCid); | 2177 return BuildByteArrayViewStore(call, kTypedDataInt32ArrayCid); |
2178 case MethodRecognizer::kByteArrayBaseSetUint32: | 2178 case MethodRecognizer::kByteArrayBaseSetUint32: |
2179 return BuildByteArrayViewStore(call, kTypedDataUint32ArrayCid); | 2179 return BuildByteArrayViewStore(call, kTypedDataUint32ArrayCid); |
2180 case MethodRecognizer::kByteArrayBaseSetFloat32: | 2180 case MethodRecognizer::kByteArrayBaseSetFloat32: |
2181 return BuildByteArrayViewStore(call, kTypedDataFloat32ArrayCid); | 2181 return BuildByteArrayViewStore(call, kTypedDataFloat32ArrayCid); |
2182 case MethodRecognizer::kByteArrayBaseSetFloat64: | 2182 case MethodRecognizer::kByteArrayBaseSetFloat64: |
2183 return BuildByteArrayViewStore(call, kTypedDataFloat64ArrayCid); | 2183 return BuildByteArrayViewStore(call, kTypedDataFloat64ArrayCid); |
2184 case MethodRecognizer::kByteArrayBaseSetFloat32x4: | 2184 case MethodRecognizer::kByteArrayBaseSetFloat32x4: |
2185 return BuildByteArrayViewStore(call, kTypedDataFloat32x4ArrayCid); | 2185 return BuildByteArrayViewStore(call, kTypedDataFloat32x4ArrayCid); |
2186 case MethodRecognizer::kByteArrayBaseSetUint32x4: | 2186 case MethodRecognizer::kByteArrayBaseSetInt32x4: |
2187 return BuildByteArrayViewStore(call, kTypedDataUint32x4ArrayCid); | 2187 return BuildByteArrayViewStore(call, kTypedDataInt32x4ArrayCid); |
2188 default: | 2188 default: |
2189 // Unsupported method. | 2189 // Unsupported method. |
2190 return false; | 2190 return false; |
2191 } | 2191 } |
2192 } | 2192 } |
2193 | 2193 |
2194 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { | 2194 if ((class_ids[0] == kFloat32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
2195 return TryInlineFloat32x4Method(call, recognized_kind); | 2195 return TryInlineFloat32x4Method(call, recognized_kind); |
2196 } | 2196 } |
2197 | 2197 |
2198 if ((class_ids[0] == kUint32x4Cid) && (ic_data.NumberOfChecks() == 1)) { | 2198 if ((class_ids[0] == kInt32x4Cid) && (ic_data.NumberOfChecks() == 1)) { |
2199 return TryInlineUint32x4Method(call, recognized_kind); | 2199 return TryInlineInt32x4Method(call, recognized_kind); |
2200 } | 2200 } |
2201 | 2201 |
2202 if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) { | 2202 if (recognized_kind == MethodRecognizer::kIntegerLeftShiftWithMask32) { |
2203 ASSERT(call->ArgumentCount() == 3); | 2203 ASSERT(call->ArgumentCount() == 3); |
2204 ASSERT(ic_data.num_args_tested() == 2); | 2204 ASSERT(ic_data.num_args_tested() == 2); |
2205 Definition* value = call->ArgumentAt(0); | 2205 Definition* value = call->ArgumentAt(0); |
2206 Definition* count = call->ArgumentAt(1); | 2206 Definition* count = call->ArgumentAt(1); |
2207 Definition* int32_mask = call->ArgumentAt(2); | 2207 Definition* int32_mask = call->ArgumentAt(2); |
2208 if (HasOnlyTwoOf(ic_data, kSmiCid)) { | 2208 if (HasOnlyTwoOf(ic_data, kSmiCid)) { |
2209 if (ic_data.deopt_reason() == kDeoptShiftMintOp) { | 2209 if (ic_data.deopt_reason() == kDeoptShiftMintOp) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2281 return true; | 2281 return true; |
2282 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { | 2282 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { |
2283 Float32x4ConstructorInstr* con = | 2283 Float32x4ConstructorInstr* con = |
2284 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)), | 2284 new Float32x4ConstructorInstr(new Value(call->ArgumentAt(1)), |
2285 new Value(call->ArgumentAt(2)), | 2285 new Value(call->ArgumentAt(2)), |
2286 new Value(call->ArgumentAt(3)), | 2286 new Value(call->ArgumentAt(3)), |
2287 new Value(call->ArgumentAt(4)), | 2287 new Value(call->ArgumentAt(4)), |
2288 call->deopt_id()); | 2288 call->deopt_id()); |
2289 ReplaceCall(call, con); | 2289 ReplaceCall(call, con); |
2290 return true; | 2290 return true; |
2291 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromUint32x4Bits) { | 2291 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) { |
2292 Uint32x4ToFloat32x4Instr* cast = | 2292 Int32x4ToFloat32x4Instr* cast = |
2293 new Uint32x4ToFloat32x4Instr(new Value(call->ArgumentAt(1)), | 2293 new Int32x4ToFloat32x4Instr(new Value(call->ArgumentAt(1)), |
2294 call->deopt_id()); | 2294 call->deopt_id()); |
2295 ReplaceCall(call, cast); | 2295 ReplaceCall(call, cast); |
2296 return true; | 2296 return true; |
2297 } | 2297 } |
2298 return false; | 2298 return false; |
2299 } | 2299 } |
2300 | 2300 |
2301 | 2301 |
2302 bool FlowGraphOptimizer::TryInlineUint32x4Constructor( | 2302 bool FlowGraphOptimizer::TryInlineInt32x4Constructor( |
2303 StaticCallInstr* call, | 2303 StaticCallInstr* call, |
2304 MethodRecognizer::Kind recognized_kind) { | 2304 MethodRecognizer::Kind recognized_kind) { |
2305 if (!ShouldInlineSimd()) { | 2305 if (!ShouldInlineSimd()) { |
2306 return false; | 2306 return false; |
2307 } | 2307 } |
2308 if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) { | 2308 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { |
2309 Uint32x4BoolConstructorInstr* con = new Uint32x4BoolConstructorInstr( | 2309 Int32x4BoolConstructorInstr* con = new Int32x4BoolConstructorInstr( |
2310 new Value(call->ArgumentAt(1)), | 2310 new Value(call->ArgumentAt(1)), |
2311 new Value(call->ArgumentAt(2)), | 2311 new Value(call->ArgumentAt(2)), |
2312 new Value(call->ArgumentAt(3)), | 2312 new Value(call->ArgumentAt(3)), |
2313 new Value(call->ArgumentAt(4)), | 2313 new Value(call->ArgumentAt(4)), |
2314 call->deopt_id()); | 2314 call->deopt_id()); |
2315 ReplaceCall(call, con); | 2315 ReplaceCall(call, con); |
2316 return true; | 2316 return true; |
2317 } else if (recognized_kind == MethodRecognizer::kUint32x4FromFloat32x4Bits) { | 2317 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) { |
2318 Float32x4ToUint32x4Instr* cast = | 2318 Float32x4ToInt32x4Instr* cast = |
2319 new Float32x4ToUint32x4Instr(new Value(call->ArgumentAt(1)), | 2319 new Float32x4ToInt32x4Instr(new Value(call->ArgumentAt(1)), |
2320 call->deopt_id()); | 2320 call->deopt_id()); |
2321 ReplaceCall(call, cast); | 2321 ReplaceCall(call, cast); |
2322 return true; | 2322 return true; |
2323 } | 2323 } |
2324 return false; | 2324 return false; |
2325 } | 2325 } |
2326 | 2326 |
2327 | 2327 |
2328 bool FlowGraphOptimizer::TryInlineFloat32x4Method( | 2328 bool FlowGraphOptimizer::TryInlineFloat32x4Method( |
2329 InstanceCallInstr* call, | 2329 InstanceCallInstr* call, |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2473 case MethodRecognizer::kFloat32x4ShuffleMix: | 2473 case MethodRecognizer::kFloat32x4ShuffleMix: |
2474 case MethodRecognizer::kFloat32x4Shuffle: { | 2474 case MethodRecognizer::kFloat32x4Shuffle: { |
2475 return InlineFloat32x4Getter(call, recognized_kind); | 2475 return InlineFloat32x4Getter(call, recognized_kind); |
2476 } | 2476 } |
2477 default: | 2477 default: |
2478 return false; | 2478 return false; |
2479 } | 2479 } |
2480 } | 2480 } |
2481 | 2481 |
2482 | 2482 |
2483 bool FlowGraphOptimizer::TryInlineUint32x4Method( | 2483 bool FlowGraphOptimizer::TryInlineInt32x4Method( |
2484 InstanceCallInstr* call, | 2484 InstanceCallInstr* call, |
2485 MethodRecognizer::Kind recognized_kind) { | 2485 MethodRecognizer::Kind recognized_kind) { |
2486 if (!ShouldInlineSimd()) { | 2486 if (!ShouldInlineSimd()) { |
2487 return false; | 2487 return false; |
2488 } | 2488 } |
2489 ASSERT(call->HasICData()); | 2489 ASSERT(call->HasICData()); |
2490 switch (recognized_kind) { | 2490 switch (recognized_kind) { |
2491 case MethodRecognizer::kUint32x4ShuffleMix: | 2491 case MethodRecognizer::kInt32x4ShuffleMix: |
2492 case MethodRecognizer::kUint32x4Shuffle: | 2492 case MethodRecognizer::kInt32x4Shuffle: |
2493 case MethodRecognizer::kUint32x4GetFlagX: | 2493 case MethodRecognizer::kInt32x4GetFlagX: |
2494 case MethodRecognizer::kUint32x4GetFlagY: | 2494 case MethodRecognizer::kInt32x4GetFlagY: |
2495 case MethodRecognizer::kUint32x4GetFlagZ: | 2495 case MethodRecognizer::kInt32x4GetFlagZ: |
2496 case MethodRecognizer::kUint32x4GetFlagW: | 2496 case MethodRecognizer::kInt32x4GetFlagW: |
2497 case MethodRecognizer::kUint32x4GetSignMask: | 2497 case MethodRecognizer::kInt32x4GetSignMask: |
2498 ASSERT(call->ic_data()->HasReceiverClassId(kUint32x4Cid)); | 2498 ASSERT(call->ic_data()->HasReceiverClassId(kInt32x4Cid)); |
2499 ASSERT(call->ic_data()->HasOneTarget()); | 2499 ASSERT(call->ic_data()->HasOneTarget()); |
2500 return InlineUint32x4Getter(call, recognized_kind); | 2500 return InlineInt32x4Getter(call, recognized_kind); |
2501 | 2501 |
2502 case MethodRecognizer::kUint32x4Select: { | 2502 case MethodRecognizer::kInt32x4Select: { |
2503 Definition* mask = call->ArgumentAt(0); | 2503 Definition* mask = call->ArgumentAt(0); |
2504 Definition* trueValue = call->ArgumentAt(1); | 2504 Definition* trueValue = call->ArgumentAt(1); |
2505 Definition* falseValue = call->ArgumentAt(2); | 2505 Definition* falseValue = call->ArgumentAt(2); |
2506 // Type check left. | 2506 // Type check left. |
2507 AddCheckClass(mask, | 2507 AddCheckClass(mask, |
2508 ICData::ZoneHandle( | 2508 ICData::ZoneHandle( |
2509 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2509 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2510 call->deopt_id(), | 2510 call->deopt_id(), |
2511 call->env(), | 2511 call->env(), |
2512 call); | 2512 call); |
2513 Uint32x4SelectInstr* select = new Uint32x4SelectInstr( | 2513 Int32x4SelectInstr* select = new Int32x4SelectInstr( |
2514 new Value(mask), | 2514 new Value(mask), |
2515 new Value(trueValue), | 2515 new Value(trueValue), |
2516 new Value(falseValue), | 2516 new Value(falseValue), |
2517 call->deopt_id()); | 2517 call->deopt_id()); |
2518 ReplaceCall(call, select); | 2518 ReplaceCall(call, select); |
2519 return true; | 2519 return true; |
2520 } | 2520 } |
2521 case MethodRecognizer::kUint32x4WithFlagX: | 2521 case MethodRecognizer::kInt32x4WithFlagX: |
2522 case MethodRecognizer::kUint32x4WithFlagY: | 2522 case MethodRecognizer::kInt32x4WithFlagY: |
2523 case MethodRecognizer::kUint32x4WithFlagZ: | 2523 case MethodRecognizer::kInt32x4WithFlagZ: |
2524 case MethodRecognizer::kUint32x4WithFlagW: { | 2524 case MethodRecognizer::kInt32x4WithFlagW: { |
2525 Definition* left = call->ArgumentAt(0); | 2525 Definition* left = call->ArgumentAt(0); |
2526 Definition* flag = call->ArgumentAt(1); | 2526 Definition* flag = call->ArgumentAt(1); |
2527 // Type check left. | 2527 // Type check left. |
2528 AddCheckClass(left, | 2528 AddCheckClass(left, |
2529 ICData::ZoneHandle( | 2529 ICData::ZoneHandle( |
2530 call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 2530 call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
2531 call->deopt_id(), | 2531 call->deopt_id(), |
2532 call->env(), | 2532 call->env(), |
2533 call); | 2533 call); |
2534 Uint32x4SetFlagInstr* setFlag = new Uint32x4SetFlagInstr( | 2534 Int32x4SetFlagInstr* setFlag = new Int32x4SetFlagInstr( |
2535 recognized_kind, | 2535 recognized_kind, |
2536 new Value(left), | 2536 new Value(left), |
2537 new Value(flag), | 2537 new Value(flag), |
2538 call->deopt_id()); | 2538 call->deopt_id()); |
2539 ReplaceCall(call, setFlag); | 2539 ReplaceCall(call, setFlag); |
2540 return true; | 2540 return true; |
2541 } | 2541 } |
2542 default: | 2542 default: |
2543 return false; | 2543 return false; |
2544 } | 2544 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2668 Definition::kValue); | 2668 Definition::kValue); |
2669 *array = elements; | 2669 *array = elements; |
2670 } | 2670 } |
2671 return array_cid; | 2671 return array_cid; |
2672 } | 2672 } |
2673 | 2673 |
2674 | 2674 |
2675 bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call, | 2675 bool FlowGraphOptimizer::BuildByteArrayViewLoad(InstanceCallInstr* call, |
2676 intptr_t view_cid) { | 2676 intptr_t view_cid) { |
2677 bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) || | 2677 bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) || |
2678 (view_cid == kTypedDataUint32x4ArrayCid); | 2678 (view_cid == kTypedDataInt32x4ArrayCid); |
2679 if (simd_view && !ShouldInlineSimd()) { | 2679 if (simd_view && !ShouldInlineSimd()) { |
2680 return false; | 2680 return false; |
2681 } | 2681 } |
2682 | 2682 |
2683 ASSERT(call->HasICData()); | 2683 ASSERT(call->HasICData()); |
2684 Function& target = Function::Handle(); | 2684 Function& target = Function::Handle(); |
2685 GrowableArray<intptr_t> class_ids; | 2685 GrowableArray<intptr_t> class_ids; |
2686 call->ic_data()->GetCheckAt(0, &class_ids, &target); | 2686 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
2687 const intptr_t receiver_cid = class_ids[0]; | 2687 const intptr_t receiver_cid = class_ids[0]; |
2688 | 2688 |
(...skipping 29 matching lines...) Expand all Loading... |
2718 current_iterator()->RemoveCurrentFromGraph(); | 2718 current_iterator()->RemoveCurrentFromGraph(); |
2719 call->set_previous(NULL); | 2719 call->set_previous(NULL); |
2720 call->set_next(NULL); | 2720 call->set_next(NULL); |
2721 return true; | 2721 return true; |
2722 } | 2722 } |
2723 | 2723 |
2724 | 2724 |
2725 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call, | 2725 bool FlowGraphOptimizer::BuildByteArrayViewStore(InstanceCallInstr* call, |
2726 intptr_t view_cid) { | 2726 intptr_t view_cid) { |
2727 bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) || | 2727 bool simd_view = (view_cid == kTypedDataFloat32x4ArrayCid) || |
2728 (view_cid == kTypedDataUint32x4ArrayCid); | 2728 (view_cid == kTypedDataInt32x4ArrayCid); |
2729 if (simd_view && !ShouldInlineSimd()) { | 2729 if (simd_view && !ShouldInlineSimd()) { |
2730 return false; | 2730 return false; |
2731 } | 2731 } |
2732 ASSERT(call->HasICData()); | 2732 ASSERT(call->HasICData()); |
2733 Function& target = Function::Handle(); | 2733 Function& target = Function::Handle(); |
2734 GrowableArray<intptr_t> class_ids; | 2734 GrowableArray<intptr_t> class_ids; |
2735 call->ic_data()->GetCheckAt(0, &class_ids, &target); | 2735 call->ic_data()->GetCheckAt(0, &class_ids, &target); |
2736 const intptr_t receiver_cid = class_ids[0]; | 2736 const intptr_t receiver_cid = class_ids[0]; |
2737 | 2737 |
2738 Definition* array = call->ArgumentAt(0); | 2738 Definition* array = call->ArgumentAt(0); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2773 case kTypedDataFloat64ArrayCid: { | 2773 case kTypedDataFloat64ArrayCid: { |
2774 // Check that value is always double. | 2774 // Check that value is always double. |
2775 value_check = ICData::New(flow_graph_->parsed_function().function(), | 2775 value_check = ICData::New(flow_graph_->parsed_function().function(), |
2776 call->function_name(), | 2776 call->function_name(), |
2777 Object::empty_array(), // Dummy args. descr. | 2777 Object::empty_array(), // Dummy args. descr. |
2778 Isolate::kNoDeoptId, | 2778 Isolate::kNoDeoptId, |
2779 1); | 2779 1); |
2780 value_check.AddReceiverCheck(kDoubleCid, target); | 2780 value_check.AddReceiverCheck(kDoubleCid, target); |
2781 break; | 2781 break; |
2782 } | 2782 } |
2783 case kTypedDataUint32x4ArrayCid: { | 2783 case kTypedDataInt32x4ArrayCid: { |
2784 // Check that value is always Uint32x4. | 2784 // Check that value is always Int32x4. |
2785 value_check = ICData::New(flow_graph_->parsed_function().function(), | 2785 value_check = ICData::New(flow_graph_->parsed_function().function(), |
2786 call->function_name(), | 2786 call->function_name(), |
2787 Object::empty_array(), // Dummy args. descr. | 2787 Object::empty_array(), // Dummy args. descr. |
2788 Isolate::kNoDeoptId, | 2788 Isolate::kNoDeoptId, |
2789 1); | 2789 1); |
2790 value_check.AddReceiverCheck(kUint32x4Cid, target); | 2790 value_check.AddReceiverCheck(kInt32x4Cid, target); |
2791 break; | 2791 break; |
2792 } | 2792 } |
2793 case kTypedDataFloat32x4ArrayCid: { | 2793 case kTypedDataFloat32x4ArrayCid: { |
2794 // Check that value is always Float32x4. | 2794 // Check that value is always Float32x4. |
2795 value_check = ICData::New(flow_graph_->parsed_function().function(), | 2795 value_check = ICData::New(flow_graph_->parsed_function().function(), |
2796 call->function_name(), | 2796 call->function_name(), |
2797 Object::empty_array(), // Dummy args. descr. | 2797 Object::empty_array(), // Dummy args. descr. |
2798 Isolate::kNoDeoptId, | 2798 Isolate::kNoDeoptId, |
2799 1); | 2799 1); |
2800 value_check.AddReceiverCheck(kFloat32x4Cid, target); | 2800 value_check.AddReceiverCheck(kFloat32x4Cid, target); |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3129 (recognized_kind == MethodRecognizer::kMathCos)) { | 3129 (recognized_kind == MethodRecognizer::kMathCos)) { |
3130 MathUnaryInstr* math_unary = | 3130 MathUnaryInstr* math_unary = |
3131 new MathUnaryInstr(recognized_kind, | 3131 new MathUnaryInstr(recognized_kind, |
3132 new Value(call->ArgumentAt(0)), | 3132 new Value(call->ArgumentAt(0)), |
3133 call->deopt_id()); | 3133 call->deopt_id()); |
3134 ReplaceCall(call, math_unary); | 3134 ReplaceCall(call, math_unary); |
3135 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || | 3135 } else if ((recognized_kind == MethodRecognizer::kFloat32x4Zero) || |
3136 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || | 3136 (recognized_kind == MethodRecognizer::kFloat32x4Splat) || |
3137 (recognized_kind == MethodRecognizer::kFloat32x4Constructor)) { | 3137 (recognized_kind == MethodRecognizer::kFloat32x4Constructor)) { |
3138 TryInlineFloat32x4Constructor(call, recognized_kind); | 3138 TryInlineFloat32x4Constructor(call, recognized_kind); |
3139 } else if (recognized_kind == MethodRecognizer::kUint32x4BoolConstructor) { | 3139 } else if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { |
3140 TryInlineUint32x4Constructor(call, recognized_kind); | 3140 TryInlineInt32x4Constructor(call, recognized_kind); |
3141 } else if (recognized_kind == MethodRecognizer::kObjectConstructor) { | 3141 } else if (recognized_kind == MethodRecognizer::kObjectConstructor) { |
3142 // Remove the original push arguments. | 3142 // Remove the original push arguments. |
3143 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 3143 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
3144 PushArgumentInstr* push = call->PushArgumentAt(i); | 3144 PushArgumentInstr* push = call->PushArgumentAt(i); |
3145 push->ReplaceUsesWith(push->value()->definition()); | 3145 push->ReplaceUsesWith(push->value()->definition()); |
3146 push->RemoveFromGraph(); | 3146 push->RemoveFromGraph(); |
3147 } | 3147 } |
3148 // Manually replace call with global null constant. ReplaceCall can't | 3148 // Manually replace call with global null constant. ReplaceCall can't |
3149 // be used for definitions that are already in the graph. | 3149 // be used for definitions that are already in the graph. |
3150 call->ReplaceUsesWith(flow_graph_->constant_null()); | 3150 call->ReplaceUsesWith(flow_graph_->constant_null()); |
(...skipping 3834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6985 void ConstantPropagator::VisitFloat32x4Clamp(Float32x4ClampInstr* instr) { | 6985 void ConstantPropagator::VisitFloat32x4Clamp(Float32x4ClampInstr* instr) { |
6986 SetValue(instr, non_constant_); | 6986 SetValue(instr, non_constant_); |
6987 } | 6987 } |
6988 | 6988 |
6989 | 6989 |
6990 void ConstantPropagator::VisitFloat32x4With(Float32x4WithInstr* instr) { | 6990 void ConstantPropagator::VisitFloat32x4With(Float32x4WithInstr* instr) { |
6991 SetValue(instr, non_constant_); | 6991 SetValue(instr, non_constant_); |
6992 } | 6992 } |
6993 | 6993 |
6994 | 6994 |
6995 void ConstantPropagator::VisitFloat32x4ToUint32x4( | 6995 void ConstantPropagator::VisitFloat32x4ToInt32x4( |
6996 Float32x4ToUint32x4Instr* instr) { | 6996 Float32x4ToInt32x4Instr* instr) { |
6997 SetValue(instr, non_constant_); | 6997 SetValue(instr, non_constant_); |
6998 } | 6998 } |
6999 | 6999 |
7000 | 7000 |
7001 void ConstantPropagator::VisitUint32x4BoolConstructor( | 7001 void ConstantPropagator::VisitInt32x4BoolConstructor( |
7002 Uint32x4BoolConstructorInstr* instr) { | 7002 Int32x4BoolConstructorInstr* instr) { |
7003 SetValue(instr, non_constant_); | 7003 SetValue(instr, non_constant_); |
7004 } | 7004 } |
7005 | 7005 |
7006 | 7006 |
7007 void ConstantPropagator::VisitUint32x4GetFlag(Uint32x4GetFlagInstr* instr) { | 7007 void ConstantPropagator::VisitInt32x4GetFlag(Int32x4GetFlagInstr* instr) { |
7008 SetValue(instr, non_constant_); | 7008 SetValue(instr, non_constant_); |
7009 } | 7009 } |
7010 | 7010 |
7011 | 7011 |
7012 void ConstantPropagator::VisitUint32x4SetFlag(Uint32x4SetFlagInstr* instr) { | 7012 void ConstantPropagator::VisitInt32x4SetFlag(Int32x4SetFlagInstr* instr) { |
7013 SetValue(instr, non_constant_); | 7013 SetValue(instr, non_constant_); |
7014 } | 7014 } |
7015 | 7015 |
7016 | 7016 |
7017 void ConstantPropagator::VisitUint32x4Select(Uint32x4SelectInstr* instr) { | 7017 void ConstantPropagator::VisitInt32x4Select(Int32x4SelectInstr* instr) { |
7018 SetValue(instr, non_constant_); | 7018 SetValue(instr, non_constant_); |
7019 } | 7019 } |
7020 | 7020 |
7021 | 7021 |
7022 void ConstantPropagator::VisitUint32x4ToFloat32x4( | 7022 void ConstantPropagator::VisitInt32x4ToFloat32x4( |
7023 Uint32x4ToFloat32x4Instr* instr) { | 7023 Int32x4ToFloat32x4Instr* instr) { |
7024 SetValue(instr, non_constant_); | 7024 SetValue(instr, non_constant_); |
7025 } | 7025 } |
7026 | 7026 |
7027 | 7027 |
7028 void ConstantPropagator::VisitBinaryUint32x4Op(BinaryUint32x4OpInstr* instr) { | 7028 void ConstantPropagator::VisitBinaryInt32x4Op(BinaryInt32x4OpInstr* instr) { |
7029 SetValue(instr, non_constant_); | 7029 SetValue(instr, non_constant_); |
7030 } | 7030 } |
7031 | 7031 |
7032 | 7032 |
7033 void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) { | 7033 void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) { |
7034 const Object& value = instr->value()->definition()->constant_value(); | 7034 const Object& value = instr->value()->definition()->constant_value(); |
7035 if (IsNonConstant(value)) { | 7035 if (IsNonConstant(value)) { |
7036 SetValue(instr, non_constant_); | 7036 SetValue(instr, non_constant_); |
7037 } else if (IsConstant(value)) { | 7037 } else if (IsConstant(value)) { |
7038 // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin). | 7038 // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin). |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7090 const Object& value = instr->value()->definition()->constant_value(); | 7090 const Object& value = instr->value()->definition()->constant_value(); |
7091 if (IsNonConstant(value)) { | 7091 if (IsNonConstant(value)) { |
7092 SetValue(instr, non_constant_); | 7092 SetValue(instr, non_constant_); |
7093 } else if (IsConstant(value)) { | 7093 } else if (IsConstant(value)) { |
7094 // TODO(kmillikin): Handle conversion. | 7094 // TODO(kmillikin): Handle conversion. |
7095 SetValue(instr, non_constant_); | 7095 SetValue(instr, non_constant_); |
7096 } | 7096 } |
7097 } | 7097 } |
7098 | 7098 |
7099 | 7099 |
7100 void ConstantPropagator::VisitUnboxUint32x4(UnboxUint32x4Instr* instr) { | 7100 void ConstantPropagator::VisitUnboxInt32x4(UnboxInt32x4Instr* instr) { |
7101 const Object& value = instr->value()->definition()->constant_value(); | 7101 const Object& value = instr->value()->definition()->constant_value(); |
7102 if (IsNonConstant(value)) { | 7102 if (IsNonConstant(value)) { |
7103 SetValue(instr, non_constant_); | 7103 SetValue(instr, non_constant_); |
7104 } else if (IsConstant(value)) { | 7104 } else if (IsConstant(value)) { |
7105 // TODO(kmillikin): Handle conversion. | 7105 // TODO(kmillikin): Handle conversion. |
7106 SetValue(instr, non_constant_); | 7106 SetValue(instr, non_constant_); |
7107 } | 7107 } |
7108 } | 7108 } |
7109 | 7109 |
7110 | 7110 |
7111 void ConstantPropagator::VisitBoxUint32x4(BoxUint32x4Instr* instr) { | 7111 void ConstantPropagator::VisitBoxInt32x4(BoxInt32x4Instr* instr) { |
7112 const Object& value = instr->value()->definition()->constant_value(); | 7112 const Object& value = instr->value()->definition()->constant_value(); |
7113 if (IsNonConstant(value)) { | 7113 if (IsNonConstant(value)) { |
7114 SetValue(instr, non_constant_); | 7114 SetValue(instr, non_constant_); |
7115 } else if (IsConstant(value)) { | 7115 } else if (IsConstant(value)) { |
7116 // TODO(kmillikin): Handle conversion. | 7116 // TODO(kmillikin): Handle conversion. |
7117 SetValue(instr, non_constant_); | 7117 SetValue(instr, non_constant_); |
7118 } | 7118 } |
7119 } | 7119 } |
7120 | 7120 |
7121 | 7121 |
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7967 } | 7967 } |
7968 | 7968 |
7969 // Insert materializations at environment uses. | 7969 // Insert materializations at environment uses. |
7970 for (intptr_t i = 0; i < exits.length(); i++) { | 7970 for (intptr_t i = 0; i < exits.length(); i++) { |
7971 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7971 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
7972 } | 7972 } |
7973 } | 7973 } |
7974 | 7974 |
7975 | 7975 |
7976 } // namespace dart | 7976 } // namespace dart |
OLD | NEW |