Index: src/x64/lithium-codegen-x64.cc |
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
index 57db277577ef3d9ca3258731893664add185809b..808c4d87355f3626d5829df45f62745d893f236c 100644 |
--- a/src/x64/lithium-codegen-x64.cc |
+++ b/src/x64/lithium-codegen-x64.cc |
@@ -3031,7 +3031,6 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
XMMRegister xmm_scratch = xmm0; |
Register output_reg = ToRegister(instr->result()); |
XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
- Label done; |
if (CpuFeatures::IsSupported(SSE4_1)) { |
CpuFeatures::Scope scope(SSE4_1); |
@@ -3046,10 +3045,13 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
__ cmpl(output_reg, Immediate(0x80000000)); |
DeoptimizeIf(equal, instr->environment()); |
} else { |
+ Label negative_sign, done; |
// Deoptimize on negative inputs. |
__ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
__ ucomisd(input_reg, xmm_scratch); |
- DeoptimizeIf(below, instr->environment()); |
+ DeoptimizeIf(parity_even, instr->environment()); |
+ __ j(below, &negative_sign, Label::kNear); |
+ |
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
// Check for negative zero. |
Label positive_sign; |
@@ -3064,12 +3066,23 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
// Use truncating instruction (OK because input is positive). |
__ cvttsd2si(output_reg, input_reg); |
- |
// Overflow is signalled with minint. |
__ cmpl(output_reg, Immediate(0x80000000)); |
DeoptimizeIf(equal, instr->environment()); |
+ __ jmp(&done, Label::kNear); |
+ |
+ // Non-zero negative reaches here. |
+ __ bind(&negative_sign); |
+ // Truncate, then compare and compensate. |
+ __ cvttsd2si(output_reg, input_reg); |
+ __ cvtlsi2sd(xmm_scratch, output_reg); |
+ __ ucomisd(input_reg, xmm_scratch); |
+ __ j(equal, &done, Label::kNear); |
+ __ subl(output_reg, Immediate(1)); |
+ DeoptimizeIf(overflow, instr->environment()); |
+ |
+ __ bind(&done); |
} |
- __ bind(&done); |
} |