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

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
« no previous file with comments | « src/ia32/lithium-ia32.cc ('k') | src/x64/lithium-x64.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 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 3468 matching lines...) Expand 10 before | Expand all | Expand 10 after
3479 __ movq(output_reg, input_reg); 3479 __ movq(output_reg, input_reg);
3480 __ subq(output_reg, Immediate(1)); 3480 __ subq(output_reg, Immediate(1));
3481 DeoptimizeIf(overflow, instr->environment()); 3481 DeoptimizeIf(overflow, instr->environment());
3482 } 3482 }
3483 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 3483 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3484 __ cvttsd2si(output_reg, xmm_scratch); 3484 __ cvttsd2si(output_reg, xmm_scratch);
3485 __ cmpl(output_reg, Immediate(0x80000000)); 3485 __ cmpl(output_reg, Immediate(0x80000000));
3486 DeoptimizeIf(equal, instr->environment()); 3486 DeoptimizeIf(equal, instr->environment());
3487 } else { 3487 } else {
3488 Label negative_sign, done; 3488 Label negative_sign, done;
3489 // Deoptimize on negative inputs. 3489 // Deoptimize on unordered.
3490 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3490 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3491 __ ucomisd(input_reg, xmm_scratch); 3491 __ ucomisd(input_reg, xmm_scratch);
3492 DeoptimizeIf(parity_even, instr->environment()); 3492 DeoptimizeIf(parity_even, instr->environment());
3493 __ j(below, &negative_sign, Label::kNear); 3493 __ j(below, &negative_sign, Label::kNear);
3494 3494
3495 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3495 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3496 // Check for negative zero. 3496 // Check for negative zero.
3497 Label positive_sign; 3497 Label positive_sign;
3498 __ j(above, &positive_sign, Label::kNear); 3498 __ j(above, &positive_sign, Label::kNear);
3499 __ movmskpd(output_reg, input_reg); 3499 __ movmskpd(output_reg, input_reg);
(...skipping 23 matching lines...) Expand all
3523 3523
3524 __ bind(&done); 3524 __ bind(&done);
3525 } 3525 }
3526 } 3526 }
3527 3527
3528 3528
3529 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 3529 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
3530 const XMMRegister xmm_scratch = xmm0; 3530 const XMMRegister xmm_scratch = xmm0;
3531 Register output_reg = ToRegister(instr->result()); 3531 Register output_reg = ToRegister(instr->result());
3532 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3532 XMMRegister input_reg = ToDoubleRegister(instr->value());
3533 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5
3534 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5
3533 3535
3534 Label done; 3536 bool minus_zero_check =
3535 // xmm_scratch = 0.5 3537 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
3536 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE64); 3538
3539 __ movq(kScratchRegister, one_half, RelocInfo::NONE64);
3537 __ movq(xmm_scratch, kScratchRegister); 3540 __ movq(xmm_scratch, kScratchRegister);
3538 Label below_half;
3539 __ ucomisd(xmm_scratch, input_reg);
3540 // If input_reg is NaN, this doesn't jump.
3541 __ j(above, &below_half, Label::kNear);
3542 // input = input + 0.5
3543 // This addition might give a result that isn't the correct for
3544 // rounding, due to loss of precision, but only for a number that's
3545 // so big that the conversion below will overflow anyway.
3546 __ addsd(xmm_scratch, input_reg);
3547 // Compute Math.floor(input).
3548 // Use truncating instruction (OK because input is positive).
3549 __ cvttsd2si(output_reg, xmm_scratch);
3550 // Overflow is signalled with minint.
3551 __ cmpl(output_reg, Immediate(0x80000000));
3552 DeoptimizeIf(equal, instr->environment());
3553 __ jmp(&done);
3554 3541
3555 __ bind(&below_half); 3542 if (CpuFeatures::IsSupported(SSE4_1) && !minus_zero_check) {
3556 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3543 CpuFeatures::Scope scope(SSE4_1);
3557 // Bailout if negative (including -0). 3544 __ addsd(xmm_scratch, input_reg);
3558 __ movq(output_reg, input_reg); 3545 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3559 __ testq(output_reg, output_reg); 3546 __ cvttsd2si(output_reg, xmm_scratch);
3560 DeoptimizeIf(negative, instr->environment()); 3547 // Overflow is signalled with minint.
3548 __ cmpl(output_reg, Immediate(0x80000000));
3549 __ RecordComment("D2I conversion overflow");
3550 DeoptimizeIf(equal, instr->environment());
3561 } else { 3551 } else {
3562 // Bailout if below -0.5, otherwise round to (positive) zero, even 3552 Label done, round_to_zero, below_one_half, do_not_compensate;
3563 // if negative. 3553 __ ucomisd(xmm_scratch, input_reg);
3564 // xmm_scrach = -0.5 3554 __ j(above, &below_one_half);
3565 __ movq(kScratchRegister, 3555
3566 V8_INT64_C(0xBFE0000000000000), 3556 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3567 RelocInfo::NONE64); 3557 __ addsd(xmm_scratch, input_reg);
3558 __ cvttsd2si(output_reg, xmm_scratch);
3559 // Overflow is signalled with minint.
3560 __ cmpl(output_reg, Immediate(0x80000000));
3561 __ RecordComment("D2I conversion overflow");
3562 DeoptimizeIf(equal, instr->environment());
3563 __ jmp(&done);
3564
3565 __ bind(&below_one_half);
3566 __ movq(kScratchRegister, minus_one_half, RelocInfo::NONE64);
3568 __ movq(xmm_scratch, kScratchRegister); 3567 __ movq(xmm_scratch, kScratchRegister);
3568 __ ucomisd(xmm_scratch, input_reg);
3569 __ j(below_equal, &round_to_zero);
3570
3571 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3572 // compare and compensate.
3573 __ subsd(input_reg, xmm_scratch);
3574 __ cvttsd2si(output_reg, input_reg);
3575 // Catch minint due to overflow, and to prevent overflow when compensating.
3576 __ cmpl(output_reg, Immediate(0x80000000));
3577 __ RecordComment("D2I conversion overflow");
3578 DeoptimizeIf(equal, instr->environment());
3579
3580 __ cvtlsi2sd(xmm_scratch, output_reg);
3569 __ ucomisd(input_reg, xmm_scratch); 3581 __ ucomisd(input_reg, xmm_scratch);
3570 DeoptimizeIf(below, instr->environment()); 3582 __ j(equal, &done, Label::kNear);
3583 __ subl(output_reg, Immediate(1));
3584 // No overflow because we already ruled out minint.
3585 __ jmp(&done);
3586
3587 __ bind(&round_to_zero);
3588 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3589 // we can ignore the difference between a result of -0 and +0.
3590 if (minus_zero_check) {
3591 __ movq(output_reg, input_reg);
3592 __ testq(output_reg, output_reg);
3593 __ RecordComment("Minus zero");
3594 DeoptimizeIf(negative, instr->environment());
3595 }
3596 __ Set(output_reg, 0);
3597 __ bind(&done);
3571 } 3598 }
3572 __ xorl(output_reg, output_reg);
3573
3574 __ bind(&done);
3575 } 3599 }
3576 3600
3577 3601
3578 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { 3602 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
3579 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3603 XMMRegister input_reg = ToDoubleRegister(instr->value());
3580 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); 3604 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
3581 __ sqrtsd(input_reg, input_reg); 3605 __ sqrtsd(input_reg, input_reg);
3582 } 3606 }
3583 3607
3584 3608
(...skipping 2212 matching lines...) Expand 10 before | Expand all | Expand 10 after
5797 FixedArray::kHeaderSize - kPointerSize)); 5821 FixedArray::kHeaderSize - kPointerSize));
5798 __ bind(&done); 5822 __ bind(&done);
5799 } 5823 }
5800 5824
5801 5825
5802 #undef __ 5826 #undef __
5803 5827
5804 } } // namespace v8::internal 5828 } } // namespace v8::internal
5805 5829
5806 #endif // V8_TARGET_ARCH_X64 5830 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « 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