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

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 12342037: Handle negative input in inlined Math.round on Intel CPUs. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 3456 matching lines...) Expand 10 before | Expand all | Expand 10 after
3467 __ movq(output_reg, input_reg); 3467 __ movq(output_reg, input_reg);
3468 __ subq(output_reg, Immediate(1)); 3468 __ subq(output_reg, Immediate(1));
3469 DeoptimizeIf(overflow, instr->environment()); 3469 DeoptimizeIf(overflow, instr->environment());
3470 } 3470 }
3471 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 3471 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3472 __ cvttsd2si(output_reg, xmm_scratch); 3472 __ cvttsd2si(output_reg, xmm_scratch);
3473 __ cmpl(output_reg, Immediate(0x80000000)); 3473 __ cmpl(output_reg, Immediate(0x80000000));
3474 DeoptimizeIf(equal, instr->environment()); 3474 DeoptimizeIf(equal, instr->environment());
3475 } else { 3475 } else {
3476 Label negative_sign, done; 3476 Label negative_sign, done;
3477 // Deoptimize on negative inputs. 3477 // Deoptimize on unordered.
3478 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3478 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3479 __ ucomisd(input_reg, xmm_scratch); 3479 __ ucomisd(input_reg, xmm_scratch);
3480 DeoptimizeIf(parity_even, instr->environment()); 3480 DeoptimizeIf(parity_even, instr->environment());
3481 __ j(below, &negative_sign, Label::kNear); 3481 __ j(below, &negative_sign, Label::kNear);
3482 3482
3483 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3483 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3484 // Check for negative zero. 3484 // Check for negative zero.
3485 Label positive_sign; 3485 Label positive_sign;
3486 __ j(above, &positive_sign, Label::kNear); 3486 __ j(above, &positive_sign, Label::kNear);
3487 __ movmskpd(output_reg, input_reg); 3487 __ movmskpd(output_reg, input_reg);
(...skipping 23 matching lines...) Expand all
3511 3511
3512 __ bind(&done); 3512 __ bind(&done);
3513 } 3513 }
3514 } 3514 }
3515 3515
3516 3516
3517 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 3517 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
3518 const XMMRegister xmm_scratch = xmm0; 3518 const XMMRegister xmm_scratch = xmm0;
3519 Register output_reg = ToRegister(instr->result()); 3519 Register output_reg = ToRegister(instr->result());
3520 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3520 XMMRegister input_reg = ToDoubleRegister(instr->value());
3521 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5
3522 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5
3521 3523
3522 Label done; 3524 bool minus_zero_check =
3523 // xmm_scratch = 0.5 3525 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
3524 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE64); 3526
3527 __ movq(kScratchRegister, one_half, RelocInfo::NONE64);
3525 __ movq(xmm_scratch, kScratchRegister); 3528 __ movq(xmm_scratch, kScratchRegister);
3526 Label below_half;
3527 __ ucomisd(xmm_scratch, input_reg);
3528 // If input_reg is NaN, this doesn't jump.
3529 __ j(above, &below_half, Label::kNear);
3530 // input = input + 0.5
3531 // This addition might give a result that isn't the correct for
3532 // rounding, due to loss of precision, but only for a number that's
3533 // so big that the conversion below will overflow anyway.
3534 __ addsd(xmm_scratch, input_reg);
3535 // Compute Math.floor(input).
3536 // Use truncating instruction (OK because input is positive).
3537 __ cvttsd2si(output_reg, xmm_scratch);
3538 // Overflow is signalled with minint.
3539 __ cmpl(output_reg, Immediate(0x80000000));
3540 DeoptimizeIf(equal, instr->environment());
3541 __ jmp(&done);
3542 3529
3543 __ bind(&below_half); 3530 if (CpuFeatures::IsSupported(SSE4_1) && !minus_zero_check) {
3544 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3531 CpuFeatures::Scope scope(SSE4_1);
3545 // Bailout if negative (including -0). 3532 __ addsd(xmm_scratch, input_reg);
3546 __ movq(output_reg, input_reg); 3533 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3547 __ testq(output_reg, output_reg); 3534 __ cvttsd2si(output_reg, xmm_scratch);
3548 DeoptimizeIf(negative, instr->environment()); 3535 // Overflow is signalled with minint.
3536 __ cmpl(output_reg, Immediate(0x80000000));
3537 __ RecordComment("D2I conversion overflow");
3538 DeoptimizeIf(equal, instr->environment());
3549 } else { 3539 } else {
3550 // Bailout if below -0.5, otherwise round to (positive) zero, even 3540 Label done, round_to_zero, below_one_half, do_not_compensate;
3551 // if negative. 3541 __ ucomisd(xmm_scratch, input_reg);
3552 // xmm_scrach = -0.5 3542 __ j(above, &below_one_half);
3553 __ movq(kScratchRegister, 3543
3554 V8_INT64_C(0xBFE0000000000000), 3544 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3555 RelocInfo::NONE64); 3545 __ addsd(xmm_scratch, input_reg);
3546 __ cvttsd2si(output_reg, xmm_scratch);
3547 // Overflow is signalled with minint.
3548 __ cmpl(output_reg, Immediate(0x80000000));
3549 __ RecordComment("D2I conversion overflow");
3550 DeoptimizeIf(equal, instr->environment());
3551 __ jmp(&done);
3552
3553 __ bind(&below_one_half);
3554 __ movq(kScratchRegister, minus_one_half, RelocInfo::NONE64);
3556 __ movq(xmm_scratch, kScratchRegister); 3555 __ movq(xmm_scratch, kScratchRegister);
3556 __ ucomisd(xmm_scratch, input_reg);
3557 __ j(below_equal, &round_to_zero);
3558
3559 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3560 // compare and compensate.
3561 __ subsd(input_reg, xmm_scratch);
3562 __ cvttsd2si(output_reg, input_reg);
3563 // Catch minint due to overflow, and to prevent overflow when compensating.
3564 __ cmpl(output_reg, Immediate(0x80000000));
3565 __ RecordComment("D2I conversion overflow");
3566 DeoptimizeIf(equal, instr->environment());
3567
3568 __ cvtlsi2sd(xmm_scratch, output_reg);
3557 __ ucomisd(input_reg, xmm_scratch); 3569 __ ucomisd(input_reg, xmm_scratch);
3558 DeoptimizeIf(below, instr->environment()); 3570 __ j(equal, &done, Label::kNear);
3571 __ subl(output_reg, Immediate(1));
3572 // No overflow because we already ruled out minint.
3573 __ jmp(&done);
3574
3575 __ bind(&round_to_zero);
3576 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3577 // we can ignore the difference between a result of -0 and +0.
3578 if (minus_zero_check) {
3579 __ movq(output_reg, input_reg);
3580 __ testq(output_reg, output_reg);
3581 __ RecordComment("Minus zero");
3582 DeoptimizeIf(negative, instr->environment());
3583 }
3584 __ Set(output_reg, 0);
3585 __ bind(&done);
3559 } 3586 }
3560 __ xorl(output_reg, output_reg);
3561
3562 __ bind(&done);
3563 } 3587 }
3564 3588
3565 3589
3566 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 3590 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
3567 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3591 XMMRegister input_reg = ToDoubleRegister(instr->value());
3568 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 3592 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
3569 __ sqrtsd(input_reg, input_reg); 3593 __ sqrtsd(input_reg, input_reg);
3570 } 3594 }
3571 3595
3572 3596
(...skipping 2212 matching lines...) Expand 10 before | Expand all | Expand 10 after
5785 FixedArray::kHeaderSize - kPointerSize)); 5809 FixedArray::kHeaderSize - kPointerSize));
5786 __ bind(&done); 5810 __ bind(&done);
5787 } 5811 }
5788 5812
5789 5813
5790 #undef __ 5814 #undef __
5791 5815
5792 } } // namespace v8::internal 5816 } } // namespace v8::internal
5793 5817
5794 #endif // V8_TARGET_ARCH_X64 5818 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/assembler.cc ('K') | « src/ia32/lithium-ia32.cc ('k') | src/x64/lithium-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698