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

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

Issue 267283004: Adds unary double operations to ARM64, enables many tests. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/simulator_arm64.cc » ('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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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/globals.h" // Needed here to get TARGET_ARCH_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 summary->set_out(0, Location::RequiresRegister()); 661 summary->set_out(0, Location::RequiresRegister());
662 return summary; 662 return summary;
663 } 663 }
664 664
665 665
666 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, 666 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
667 BranchLabels labels) { 667 BranchLabels labels) {
668 if (operation_cid() == kSmiCid) { 668 if (operation_cid() == kSmiCid) {
669 return EmitSmiComparisonOp(compiler, locs(), kind()); 669 return EmitSmiComparisonOp(compiler, locs(), kind());
670 } else { 670 } else {
671 UNIMPLEMENTED(); 671 ASSERT(operation_cid() == kDoubleCid);
672 return VS; 672 return EmitDoubleComparisonOp(compiler, locs(), kind());
673 } 673 }
674 } 674 }
675 675
676 676
677 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 677 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
678 Label is_true, is_false; 678 Label is_true, is_false;
679 BranchLabels labels = { &is_true, &is_false, &is_false }; 679 BranchLabels labels = { &is_true, &is_false, &is_false };
680 Condition true_condition = EmitComparisonCode(compiler, labels); 680 Condition true_condition = EmitComparisonCode(compiler, labels);
681 EmitBranchOnCondition(compiler, true_condition, labels); 681 EmitBranchOnCondition(compiler, true_condition, labels);
682 // TODO(zra): instead of branching, use the csel instruction to get 682 // TODO(zra): instead of branching, use the csel instruction to get
(...skipping 1143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1826 temp2); 1826 temp2);
1827 __ Bind(&copy_double); 1827 __ Bind(&copy_double);
1828 __ LoadDFieldFromOffset(fpu_temp, value_reg, Double::value_offset()); 1828 __ LoadDFieldFromOffset(fpu_temp, value_reg, Double::value_offset());
1829 __ StoreDFieldToOffset(fpu_temp, temp, Double::value_offset()); 1829 __ StoreDFieldToOffset(fpu_temp, temp, Double::value_offset());
1830 __ b(&skip_store); 1830 __ b(&skip_store);
1831 } 1831 }
1832 1832
1833 // TODO(zra): Implement these when we add simd loads and stores. 1833 // TODO(zra): Implement these when we add simd loads and stores.
1834 { 1834 {
1835 __ Bind(&store_float32x4); 1835 __ Bind(&store_float32x4);
1836 __ hlt(0); // Unimplemented. 1836 __ Stop("Float32x4 Unimplemented");
1837 } 1837 }
1838 1838
1839 { 1839 {
1840 __ Bind(&store_float64x2); 1840 __ Bind(&store_float64x2);
1841 __ hlt(0); // Unimplemented. 1841 __ Stop("Float64x2 Unimplemented");
1842 } 1842 }
1843 1843
1844 __ Bind(&store_pointer); 1844 __ Bind(&store_pointer);
1845 } 1845 }
1846 1846
1847 if (ShouldEmitStoreBarrier()) { 1847 if (ShouldEmitStoreBarrier()) {
1848 Register value_reg = locs()->in(1).reg(); 1848 Register value_reg = locs()->in(1).reg();
1849 __ StoreIntoObject(instance_reg, 1849 __ StoreIntoObject(instance_reg,
1850 FieldAddress(instance_reg, offset_in_bytes_), 1850 FieldAddress(instance_reg, offset_in_bytes_),
1851 value_reg, 1851 value_reg,
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 __ Bind(slow_path->exit_label()); 2095 __ Bind(slow_path->exit_label());
2096 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); 2096 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes());
2097 __ LoadDFieldFromOffset(value, temp, Double::value_offset()); 2097 __ LoadDFieldFromOffset(value, temp, Double::value_offset());
2098 __ StoreDFieldToOffset(value, result_reg, Double::value_offset()); 2098 __ StoreDFieldToOffset(value, result_reg, Double::value_offset());
2099 __ b(&done); 2099 __ b(&done);
2100 } 2100 }
2101 2101
2102 // TODO(zra): Implement these when we add simd loads and stores. 2102 // TODO(zra): Implement these when we add simd loads and stores.
2103 { 2103 {
2104 __ Bind(&load_float32x4); 2104 __ Bind(&load_float32x4);
2105 __ hlt(0); // Unimplemented. 2105 __ Stop("Float32x4 Unimplemented");
2106 } 2106 }
2107 2107
2108 { 2108 {
2109 __ Bind(&load_float64x2); 2109 __ Bind(&load_float64x2);
2110 __ hlt(0); // Unimplemented. 2110 __ Stop("Float64x2 Unimplemented");
2111 } 2111 }
2112 2112
2113 __ Bind(&load_pointer); 2113 __ Bind(&load_pointer);
2114 } 2114 }
2115 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); 2115 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes());
2116 __ Bind(&done); 2116 __ Bind(&done);
2117 } 2117 }
2118 2118
2119 2119
2120 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { 2120 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const {
(...skipping 1229 matching lines...) Expand 10 before | Expand all | Expand 10 after
3350 return NULL; 3350 return NULL;
3351 } 3351 }
3352 3352
3353 3353
3354 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3354 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3355 UNIMPLEMENTED(); 3355 UNIMPLEMENTED();
3356 } 3356 }
3357 3357
3358 3358
3359 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const { 3359 LocationSummary* MathUnaryInstr::MakeLocationSummary(bool opt) const {
3360 UNIMPLEMENTED(); 3360 if ((kind() == MathUnaryInstr::kSin) || (kind() == MathUnaryInstr::kCos)) {
3361 return NULL; 3361 const intptr_t kNumInputs = 1;
3362 const intptr_t kNumTemps = 0;
3363 LocationSummary* summary =
3364 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
3365 summary->set_in(0, Location::FpuRegisterLocation(V0));
3366 summary->set_out(0, Location::FpuRegisterLocation(V0));
3367 return summary;
3368 }
3369 ASSERT((kind() == MathUnaryInstr::kSqrt) ||
3370 (kind() == MathUnaryInstr::kDoubleSquare));
3371 const intptr_t kNumInputs = 1;
3372 const intptr_t kNumTemps = 0;
3373 LocationSummary* summary =
3374 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3375 summary->set_in(0, Location::RequiresFpuRegister());
3376 summary->set_out(0, Location::RequiresFpuRegister());
3377 return summary;
3362 } 3378 }
3363 3379
3364 3380
3365 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3381 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3366 UNIMPLEMENTED(); 3382 if (kind() == MathUnaryInstr::kSqrt) {
3383 VRegister val = locs()->in(0).fpu_reg();
3384 VRegister result = locs()->out(0).fpu_reg();
3385 __ fsqrtd(result, val);
3386 } else if (kind() == MathUnaryInstr::kDoubleSquare) {
3387 VRegister val = locs()->in(0).fpu_reg();
3388 VRegister result = locs()->out(0).fpu_reg();
3389 __ fmuld(result, val, val);
3390 } else {
3391 ASSERT((kind() == MathUnaryInstr::kSin) ||
3392 (kind() == MathUnaryInstr::kCos));
3393 __ CallRuntime(TargetFunction(), InputCount());
3394 }
3367 } 3395 }
3368 3396
3369 3397
3370 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const { 3398 LocationSummary* MathMinMaxInstr::MakeLocationSummary(bool opt) const {
3371 UNIMPLEMENTED(); 3399 UNIMPLEMENTED();
3372 return NULL; 3400 return NULL;
3373 } 3401 }
3374 3402
3375 3403
3376 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3404 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 29 matching lines...) Expand all
3406 // Remove inverted smi-tag. 3434 // Remove inverted smi-tag.
3407 __ andi(result, result, ~kSmiTagMask); 3435 __ andi(result, result, ~kSmiTagMask);
3408 break; 3436 break;
3409 default: 3437 default:
3410 UNREACHABLE(); 3438 UNREACHABLE();
3411 } 3439 }
3412 } 3440 }
3413 3441
3414 3442
3415 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const { 3443 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(bool opt) const {
3416 UNIMPLEMENTED(); 3444 const intptr_t kNumInputs = 1;
3417 return NULL; 3445 const intptr_t kNumTemps = 0;
3446 LocationSummary* summary =
3447 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3448 summary->set_in(0, Location::RequiresFpuRegister());
3449 summary->set_out(0, Location::RequiresFpuRegister());
3450 return summary;
3418 } 3451 }
3419 3452
3420 3453
3421 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3454 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3422 UNIMPLEMENTED(); 3455 VRegister result = locs()->out(0).fpu_reg();
3456 VRegister value = locs()->in(0).fpu_reg();
3457 __ fnegd(result, value);
3423 } 3458 }
3424 3459
3425 3460
3426 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const { 3461 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(bool opt) const {
3427 UNIMPLEMENTED(); 3462 const intptr_t kNumInputs = 1;
3428 return NULL; 3463 const intptr_t kNumTemps = 0;
3464 LocationSummary* result =
3465 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3466 result->set_in(0, Location::WritableRegister());
3467 result->set_out(0, Location::RequiresFpuRegister());
3468 return result;
3429 } 3469 }
3430 3470
3431 3471
3432 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3472 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3433 UNIMPLEMENTED(); 3473 Register value = locs()->in(0).reg();
3474 VRegister result = locs()->out(0).fpu_reg();
3475 __ SmiUntag(value);
3476 __ scvtfd(result, value);
3434 } 3477 }
3435 3478
3436 3479
3437 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const { 3480 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(bool opt) const {
3438 UNIMPLEMENTED(); 3481 const intptr_t kNumInputs = 1;
3439 return NULL; 3482 const intptr_t kNumTemps = 0;
3483 LocationSummary* result =
3484 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
3485 result->set_in(0, Location::RegisterLocation(R1));
3486 result->set_out(0, Location::RegisterLocation(R0));
3487 return result;
3440 } 3488 }
3441 3489
3442 3490
3443 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3491 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3444 UNIMPLEMENTED(); 3492 const Register result = locs()->out(0).reg();
3493 const Register value_obj = locs()->in(0).reg();
3494 ASSERT(result == R0);
3495 ASSERT(result != value_obj);
3496 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset());
3497
3498 Label do_call, done;
3499 // First check for NaN. Checking for minint after the conversion doesn't work
3500 // on ARM64 because fcvtzds gives 0 for NaN.
3501 __ fcmpd(VTMP, VTMP);
3502 __ b(&do_call, VS);
3503
3504 __ fcvtzds(result, VTMP);
3505 // Overflow is signaled with minint.
3506
3507 // Check for overflow and that it fits into Smi.
3508 __ CompareImmediate(result, 0xC000000000000000, PP);
3509 __ b(&do_call, MI);
3510 __ SmiTag(result);
3511 __ b(&done);
3512 __ Bind(&do_call);
3513 __ Push(value_obj);
3514 ASSERT(instance_call()->HasICData());
3515 const ICData& ic_data = *instance_call()->ic_data();
3516 ASSERT((ic_data.NumberOfChecks() == 1));
3517 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
3518
3519 const intptr_t kNumberOfArguments = 1;
3520 compiler->GenerateStaticCall(deopt_id(),
3521 instance_call()->token_pos(),
3522 target,
3523 kNumberOfArguments,
3524 Object::null_array(), // No argument names.,
3525 locs());
3526 __ Bind(&done);
3445 } 3527 }
3446 3528
3447 3529
3448 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const { 3530 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(bool opt) const {
3449 UNIMPLEMENTED(); 3531 const intptr_t kNumInputs = 1;
3450 return NULL; 3532 const intptr_t kNumTemps = 0;
3533 LocationSummary* result = new LocationSummary(
3534 kNumInputs, kNumTemps, LocationSummary::kNoCall);
3535 result->set_in(0, Location::RequiresFpuRegister());
3536 result->set_out(0, Location::RequiresRegister());
3537 return result;
3451 } 3538 }
3452 3539
3453 3540
3454 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3541 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3455 UNIMPLEMENTED(); 3542 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi);
3543 const Register result = locs()->out(0).reg();
3544 const VRegister value = locs()->in(0).fpu_reg();
3545 // First check for NaN. Checking for minint after the conversion doesn't work
3546 // on ARM64 because fcvtzds gives 0 for NaN.
3547 // TODO(zra): Check spec that this is true.
3548 __ fcmpd(value, value);
3549 __ b(deopt, VS);
3550
3551 __ fcvtzds(result, value);
3552 // Check for overflow and that it fits into Smi.
3553 __ CompareImmediate(result, 0xC000000000000000, PP);
3554 __ b(deopt, MI);
3555 __ SmiTag(result);
3456 } 3556 }
3457 3557
3458 3558
3459 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { 3559 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const {
3460 UNIMPLEMENTED(); 3560 UNIMPLEMENTED();
3461 return NULL; 3561 return NULL;
3462 } 3562 }
3463 3563
3464 3564
3465 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3565 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 17 matching lines...) Expand all
3483 return NULL; 3583 return NULL;
3484 } 3584 }
3485 3585
3486 3586
3487 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3587 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3488 UNIMPLEMENTED(); 3588 UNIMPLEMENTED();
3489 } 3589 }
3490 3590
3491 3591
3492 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const { 3592 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(bool opt) const {
3493 UNIMPLEMENTED(); 3593 ASSERT((InputCount() == 1) || (InputCount() == 2));
3494 return NULL; 3594 const intptr_t kNumTemps = 0;
3595 LocationSummary* result =
3596 new LocationSummary(InputCount(), kNumTemps, LocationSummary::kCall);
3597 result->set_in(0, Location::FpuRegisterLocation(V0));
3598 if (InputCount() == 2) {
3599 result->set_in(1, Location::FpuRegisterLocation(V1));
3600 }
3601 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
3602 result->AddTemp(Location::FpuRegisterLocation(V30));
3603 }
3604 result->set_out(0, Location::FpuRegisterLocation(V0));
3605 return result;
3495 } 3606 }
3496 3607
3497 3608
3498 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3609 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3499 UNIMPLEMENTED(); 3610 // For pow-function return NaN if exponent is NaN.
3611 Label skip_call;
3612 if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
3613 // Pseudo code:
3614 // if (exponent == 0.0) return 1.0;
3615 // if (base == 1.0) return 1.0;
3616 // if (base.isNaN || exponent.isNaN) {
3617 // return double.NAN;
3618 // }
3619 // if (base != -Infinity && exponent == 0.5) {
3620 // if (base == 0.0) return 0.0;
3621 // return sqrt(value);
3622 // }
3623 const VRegister base = locs()->in(0).fpu_reg();
3624 const VRegister exp = locs()->in(1).fpu_reg();
3625 const VRegister result = locs()->out(0).fpu_reg();
3626 const VRegister saved_base = locs()->temp(0).fpu_reg();
3627 ASSERT((base == result) && (result != saved_base));
3628
3629 Label try_sqrt, check_base, return_nan;
3630 __ fmovdd(saved_base, base);
3631 __ LoadDImmediate(VTMP, 0.0, PP);
3632 __ LoadDImmediate(result, 1.0, PP);
3633 // exponent == 0.0 -> return 1.0;
3634 __ fcmpd(exp, VTMP);
3635 __ b(&check_base, VS); // NaN -> check base.
3636 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0.
3637
3638 __ Bind(&check_base);
3639 // Note: 'exp' could be NaN.
3640 // base == 1.0 -> return 1.0;
3641 __ fcmpd(saved_base, result);
3642 __ b(&return_nan, VS);
3643 __ b(&skip_call, EQ); // base is 1.0, result is 1.0.
3644
3645 __ fcmpd(saved_base, exp);
3646 __ b(&try_sqrt, VC); // // Neither 'exp' nor 'base' is NaN.
3647
3648 __ Bind(&return_nan);
3649 __ LoadDImmediate(result, NAN, PP);
3650 __ b(&skip_call);
3651
3652 Label do_pow, return_zero;
3653 __ Bind(&try_sqrt);
3654
3655 // Before calling pow, check if we could use sqrt instead of pow.
3656 __ LoadDImmediate(result, -INFINITY, PP);
3657
3658 // base == -Infinity -> call pow;
3659 __ fcmpd(saved_base, result);
3660 __ b(&do_pow, EQ);
3661
3662 // exponent == 0.5 ?
3663 __ LoadDImmediate(result, 0.5, PP);
3664 __ fcmpd(exp, result);
3665 __ b(&do_pow, NE);
3666
3667 // base == 0 -> return 0;
3668 __ fcmpd(base, VTMP);
3669 __ b(&return_zero, EQ);
3670
3671 __ fsqrtd(result, saved_base);
3672 __ b(&skip_call);
3673
3674 __ Bind(&return_zero);
3675 __ fmovdd(result, VTMP);
3676 __ b(&skip_call);
3677
3678 __ Bind(&do_pow);
3679 __ fmovdd(base, saved_base); // Restore base.
3680 }
3681
3682 __ CallRuntime(TargetFunction(), InputCount());
3683 __ Bind(&skip_call);
3500 } 3684 }
3501 3685
3502 3686
3503 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const { 3687 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(bool opt) const {
3504 // Only use this instruction in optimized code. 3688 // Only use this instruction in optimized code.
3505 ASSERT(opt); 3689 ASSERT(opt);
3506 const intptr_t kNumInputs = 1; 3690 const intptr_t kNumInputs = 1;
3507 LocationSummary* summary = 3691 LocationSummary* summary =
3508 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall); 3692 new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
3509 if (representation() == kUnboxedDouble) { 3693 if (representation() == kUnboxedDouble) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3543 } else { 3727 } else {
3544 ASSERT(representation() == kTagged); 3728 ASSERT(representation() == kTagged);
3545 Register out = locs()->out(0).reg(); 3729 Register out = locs()->out(0).reg();
3546 Register in = in_loc.reg(); 3730 Register in = in_loc.reg();
3547 __ mov(out, in); 3731 __ mov(out, in);
3548 } 3732 }
3549 } 3733 }
3550 3734
3551 3735
3552 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const { 3736 LocationSummary* MergedMathInstr::MakeLocationSummary(bool opt) const {
3737 if (kind() == MergedMathInstr::kTruncDivMod) {
3738 const intptr_t kNumInputs = 2;
3739 const intptr_t kNumTemps = 0;
3740 LocationSummary* summary =
3741 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3742 summary->set_in(0, Location::RequiresRegister());
3743 summary->set_in(1, Location::RequiresRegister());
3744 // Output is a pair of registers.
3745 summary->set_out(0, Location::Pair(Location::RequiresRegister(),
3746 Location::RequiresRegister()));
3747 return summary;
3748 }
3553 UNIMPLEMENTED(); 3749 UNIMPLEMENTED();
3554 return NULL; 3750 return NULL;
3555 } 3751 }
3556 3752
3557 3753
3558 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3754 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3755 Label* deopt = NULL;
3756 if (CanDeoptimize()) {
3757 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
3758 }
3759 if (kind() == MergedMathInstr::kTruncDivMod) {
3760 const Register left = locs()->in(0).reg();
3761 const Register right = locs()->in(1).reg();
3762 ASSERT(locs()->out(0).IsPairLocation());
3763 const PairLocation* pair = locs()->out(0).AsPairLocation();
3764 const Register result_div = pair->At(0).reg();
3765 const Register result_mod = pair->At(1).reg();
3766 const Range* right_range = InputAt(1)->definition()->range();
3767 if ((right_range == NULL) || right_range->Overlaps(0, 0)) {
3768 // Handle divide by zero in runtime.
3769 __ CompareRegisters(right, ZR);
3770 __ b(deopt, EQ);
3771 }
3772
3773 __ Asr(result_mod, left, kSmiTagSize); // SmiUntag left.
3774 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right.
3775
3776 __ sdiv(result_div, result_mod, TMP);
3777
3778 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
3779 // case we cannot tag the result.
3780 __ CompareImmediate(result_div, 0x4000000000000000, PP);
3781 __ b(deopt, EQ);
3782 // result_mod <- left - right * result_div.
3783 __ msub(result_mod, TMP, result_div, result_mod);
3784 __ SmiTag(result_div);
3785 __ SmiTag(result_mod);
3786 // Correct MOD result:
3787 // res = left % right;
3788 // if (res < 0) {
3789 // if (right < 0) {
3790 // res = res - right;
3791 // } else {
3792 // res = res + right;
3793 // }
3794 // }
3795 Label done;
3796 __ CompareRegisters(result_mod, ZR);;
3797 __ b(&done, GE);
3798 // Result is negative, adjust it.
3799 __ CompareRegisters(right, ZR);
3800 __ sub(TMP2, result_mod, Operand(right));
3801 __ add(TMP, result_mod, Operand(right));
3802 __ csel(result_mod, TMP, TMP2, GE);
3803 __ Bind(&done);
3804
3805 return;
3806 }
3807 if (kind() == MergedMathInstr::kSinCos) {
3808 UNIMPLEMENTED();
3809 }
3559 UNIMPLEMENTED(); 3810 UNIMPLEMENTED();
3560 } 3811 }
3561 3812
3562 3813
3563 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( 3814 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
3564 bool opt) const { 3815 bool opt) const {
3565 return MakeCallSummary(); 3816 return MakeCallSummary();
3566 } 3817 }
3567 3818
3568 3819
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
4003 compiler->GenerateCall(token_pos(), 4254 compiler->GenerateCall(token_pos(),
4004 &label, 4255 &label,
4005 PcDescriptors::kOther, 4256 PcDescriptors::kOther,
4006 locs()); 4257 locs());
4007 __ Drop(ArgumentCount()); // Discard arguments. 4258 __ Drop(ArgumentCount()); // Discard arguments.
4008 } 4259 }
4009 4260
4010 } // namespace dart 4261 } // namespace dart
4011 4262
4012 #endif // defined TARGET_ARCH_ARM64 4263 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/simulator_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698