ARM: Implement correct rounding in the lithium codegenerator.

This patch provides testing for values that have a fraction part of 0.5 and uses a different rounding method for them. The original method of VFPTruncating the value with round-to-nearest is not correct because it does not round to the larger number in case of a tie.

BUG=http://code.google.com/p/v8/issues/detail?id=958

Review URL: http://codereview.chromium.org/6840051

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7627 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent cfb5a7ee
......@@ -2861,9 +2861,49 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
DoubleRegister input = ToDoubleRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());
Register scratch1 = scratch0();
Register scratch2 = result;
__ EmitVFPTruncate(kRoundToNearest,
Register scratch1 = result;
Register scratch2 = scratch0();
Label done, check_sign_on_zero;
// Extract exponent bits.
__ vmov(scratch1, input.high());
__ ubfx(scratch2,
scratch1,
HeapNumber::kExponentShift,
HeapNumber::kExponentBits);
// If the number is in ]-0.5, +0.5[, the result is +/- 0.
__ cmp(scratch2, Operand(HeapNumber::kExponentBias - 2));
__ mov(result, Operand(0), LeaveCC, le);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ b(le, &check_sign_on_zero);
} else {
__ b(le, &done);
}
// The following conversion will not work with numbers
// outside of ]-2^32, 2^32[.
__ cmp(scratch2, Operand(HeapNumber::kExponentBias + 32));
DeoptimizeIf(ge, instr->environment());
// Save the original sign for later comparison.
__ and_(scratch2, scratch1, Operand(HeapNumber::kSignMask));
__ vmov(double_scratch0(), 0.5);
__ vadd(input, input, double_scratch0());
// Check sign of the result: if the sign changed, the input
// value was in ]0.5, 0[ and the result should be -0.
__ vmov(scratch1, input.high());
__ eor(scratch1, scratch1, Operand(scratch2), SetCC);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(mi, instr->environment());
} else {
__ mov(result, Operand(0), LeaveCC, mi);
__ b(mi, &done);
}
__ EmitVFPTruncate(kRoundToMinusInf,
double_scratch0().low(),
input,
scratch1,
......@@ -2873,14 +2913,14 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// Test for -0.
Label done;
__ cmp(result, Operand(0));
__ b(ne, &done);
__ bind(&check_sign_on_zero);
__ vmov(scratch1, input.high());
__ tst(scratch1, Operand(HeapNumber::kSignMask));
DeoptimizeIf(ne, instr->environment());
__ bind(&done);
}
__ bind(&done);
}
......
......@@ -61,9 +61,6 @@ debug-liveedit-patch-positions-replace: SKIP
##############################################################################
[ $arch == arm ]
# Code is bugged. Remove this when fixed.
math-round: PASS || FAIL
# Slow tests which times out in debug mode.
try: PASS, SKIP if $mode == debug
debug-scripts-request: PASS, SKIP if $mode == debug
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment