Chromium Code Reviews| Index: src/arm64/lithium-codegen-arm64.cc |
| diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc |
| index 3ecd2403ba3b6aa0848006d90439a11b746e0bc3..bc57bc938e6ee24fcc72dd2a60f03cca5ac0a7a9 100644 |
| --- a/src/arm64/lithium-codegen-arm64.cc |
| +++ b/src/arm64/lithium-codegen-arm64.cc |
| @@ -3761,9 +3761,15 @@ void LCodeGen::DoMathExp(LMathExp* instr) { |
| } |
| -void LCodeGen::DoMathFloor(LMathFloor* instr) { |
| - // TODO(jbramley): If we could provide a double result, we could use frintm |
| - // and produce a valid double result in a single instruction. |
| +void LCodeGen::DoMathFloorD(LMathFloorD* instr) { |
| + DoubleRegister input = ToDoubleRegister(instr->value()); |
| + DoubleRegister result = ToDoubleRegister(instr->result()); |
| + |
| + __ Frintm(result, input); |
| +} |
| + |
| + |
| +void LCodeGen::DoMathFloorI(LMathFloorI* instr) { |
| DoubleRegister input = ToDoubleRegister(instr->value()); |
| Register result = ToRegister(instr->result()); |
| @@ -3996,8 +4002,37 @@ void LCodeGen::DoPower(LPower* instr) { |
| } |
| -void LCodeGen::DoMathRound(LMathRound* instr) { |
| - // TODO(jbramley): We could provide a double result here using frint. |
| +void LCodeGen::DoMathRoundD(LMathRoundD* instr) { |
| + DoubleRegister input = ToDoubleRegister(instr->value()); |
| + DoubleRegister result = ToDoubleRegister(instr->result()); |
| + DoubleRegister scratch_d = double_scratch(); |
| + |
| + ASSERT(!AreAliased(input, result, scratch_d)); |
| + |
| + Label done; |
| + |
| + __ Frinta(result, input); |
| + __ Fcmp(input, 0.0); |
| + __ Fccmp(result, input, ZFlag, lt); |
| + // The result is correct if the input was in [-0, +infinity], or was a |
| + // negative integral value. |
| + __ B(eq, &done); |
|
ulan
2014/04/30 09:18:41
I see how it handles 0.0 and negative integers, bu
Alexandre Rames
2014/04/30 09:31:06
If the input is greater or equal to zero, the 'lt'
|
| + |
| + // Here the input is negative, non integral, with an exponent lower than 52. |
| + // We do not have to worry about the 0.49999999999999994 (0x3fdfffffffffffff) |
| + // case. So we can safely add 0.5. |
| + __ Fmov(scratch_d, 0.5); |
| + __ Fadd(result, input, scratch_d); |
| + __ Frintm(result, result); |
| + // The range [-0.5, -0.0[ yielded +0.0. Force the sign to negative. |
| + __ Fabs(result, result); |
| + __ Fneg(result, result); |
| + |
| + __ Bind(&done); |
| +} |
| + |
| + |
| +void LCodeGen::DoMathRoundI(LMathRoundI* instr) { |
| DoubleRegister input = ToDoubleRegister(instr->value()); |
| DoubleRegister temp1 = ToDoubleRegister(instr->temp1()); |
| Register result = ToRegister(instr->result()); |
| @@ -4036,7 +4071,7 @@ void LCodeGen::DoMathRound(LMathRound* instr) { |
| // Since we're providing a 32-bit result, we can implement ties-to-infinity by |
| // adding 0.5 to the input, then taking the floor of the result. This does not |
| // work for very large positive doubles because adding 0.5 would cause an |
| - // intermediate rounding stage, so a different approach will be necessary if a |
| + // intermediate rounding stage, so a different approach is necessary when a |
| // double result is needed. |
| __ Fadd(temp1, input, dot_five); |
| __ Fcvtms(result, temp1); |