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
This commit is contained in:
parent
cfb5a7ee78
commit
dab8f48ebc
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user