Fix powerpc64 lround, lroundf, llround, llroundf spurious "inexact" exceptions (bug 19235).

Similar to bug 19134 for powerpc32, the powerpc64 implementations of
lround, lroundf, llround, llroundf can raise spurious "inexact"
exceptions for integer arguments from adding 0.5 then converting to
integer (this does not apply to the power5+ version for double, which
uses the frin instruction which is defined never to raise "inexact"; I
don't know why power5+ doesn't use that version for float as well).

This patch fixes the bug in a similar way to the powerpc32 bug, by
testing for integers (adding and subtracting 2^52 and comparing with
the value before that addition and subtraction) and not adding 0.5 in
that case.

The powerpc maintainers may wish to look at making power5+ / power6x /
power8 use frin for float lround / llround as well as for double,
unless there's some reason I've missed that this isn't beneficial.

Tested for powerpc64.

	[BZ #19235]
	* sysdeps/powerpc/powerpc64/fpu/s_llround.S (__llround): Do not
	add 0.5 to integer arguments.
	* sysdeps/powerpc/powerpc64/fpu/s_llroundf.S (__llroundf):
	Likewise.
	(.LC2): New object.
This commit is contained in:
Joseph Myers 2015-11-12 16:24:00 +00:00
parent 1a44f1433e
commit 32b71ad358
3 changed files with 22 additions and 0 deletions

View File

@ -1,3 +1,12 @@
2015-11-12 Joseph Myers <joseph@codesourcery.com>
[BZ #19235]
* sysdeps/powerpc/powerpc64/fpu/s_llround.S (__llround): Do not
add 0.5 to integer arguments.
* sysdeps/powerpc/powerpc64/fpu/s_llroundf.S (__llroundf):
Likewise.
(.LC2): New object.
2015-11-11 Mike Frysinger <vapier@gentoo.org> 2015-11-11 Mike Frysinger <vapier@gentoo.org>
* scripts/pylintrc (reports): Set to no. * scripts/pylintrc (reports): Set to no.

View File

@ -55,6 +55,11 @@ ENTRY (__llround)
fcmpu cr1,fp1,fp12 /* x is negative? x < 0.0 */ fcmpu cr1,fp1,fp12 /* x is negative? x < 0.0 */
blt- cr6,.Lretzero /* 0.5 > x < -0.5 so just return 0. */ blt- cr6,.Lretzero /* 0.5 > x < -0.5 so just return 0. */
bge- cr7,.Lnobias /* 2^52 > x < -2^52 just convert with no bias. */ bge- cr7,.Lnobias /* 2^52 > x < -2^52 just convert with no bias. */
/* Test whether an integer to avoid spurious "inexact". */
fadd fp3,fp2,fp9
fsub fp3,fp3,fp9
fcmpu cr5,fp2,fp3
beq cr5,.Lnobias
fadd fp3,fp2,fp10 /* |x|+=0.5 bias to prepare to round. */ fadd fp3,fp2,fp10 /* |x|+=0.5 bias to prepare to round. */
bge cr1,.Lconvert /* x is positive so don't negate x. */ bge cr1,.Lconvert /* x is positive so don't negate x. */
fnabs fp3,fp3 /* -(|x|+=0.5) */ fnabs fp3,fp3 /* -(|x|+=0.5) */

View File

@ -23,6 +23,8 @@
.tc FD_41600000_0[TC],0x4160000000000000 .tc FD_41600000_0[TC],0x4160000000000000
.LC1: /* 0.5 */ .LC1: /* 0.5 */
.tc FD_3fe00000_0[TC],0x3fe0000000000000 .tc FD_3fe00000_0[TC],0x3fe0000000000000
.LC2: /* 2^52 */
.tc FD_43300000_0[TC],0x4330000000000000
.section ".text" .section ".text"
/* long long [r3] llroundf (float x [fp1]) /* long long [r3] llroundf (float x [fp1])
@ -47,6 +49,7 @@ ENTRY (__llroundf)
CALL_MCOUNT 0 CALL_MCOUNT 0
lfd fp9,.LC0@toc(2) /* Load 2^23 into fpr9. */ lfd fp9,.LC0@toc(2) /* Load 2^23 into fpr9. */
lfd fp10,.LC1@toc(2)/* Load 0.5 into fpr10. */ lfd fp10,.LC1@toc(2)/* Load 0.5 into fpr10. */
lfd fp11,.LC2@toc(2) /* Load 2^52 into fpr11. */
fabs fp2,fp1 /* Get the absolute value of x. */ fabs fp2,fp1 /* Get the absolute value of x. */
fsub fp12,fp10,fp10 /* Compute 0.0 into fp12. */ fsub fp12,fp10,fp10 /* Compute 0.0 into fp12. */
fcmpu cr6,fp2,fp10 /* if |x| < 0.5 */ fcmpu cr6,fp2,fp10 /* if |x| < 0.5 */
@ -54,6 +57,11 @@ ENTRY (__llroundf)
fcmpu cr1,fp1,fp12 /* x is negative? x < 0.0 */ fcmpu cr1,fp1,fp12 /* x is negative? x < 0.0 */
blt- cr6,.Lretzero /* 0.5 > x < -0.5 so just return 0. */ blt- cr6,.Lretzero /* 0.5 > x < -0.5 so just return 0. */
bge- cr7,.Lnobias /* 2^23 > x < -2^23 just convert with no bias. */ bge- cr7,.Lnobias /* 2^23 > x < -2^23 just convert with no bias. */
/* Test whether an integer to avoid spurious "inexact". */
fadd fp3,fp2,fp11
fsub fp3,fp3,fp11
fcmpu cr5,fp2,fp3
beq cr5,.Lnobias
fadd fp3,fp2,fp10 /* |x|+=0.5 bias to prepare to round. */ fadd fp3,fp2,fp10 /* |x|+=0.5 bias to prepare to round. */
bge cr1,.Lconvert /* x is positive so don't negate x. */ bge cr1,.Lconvert /* x is positive so don't negate x. */
fnabs fp3,fp3 /* -(|x|+=0.5) */ fnabs fp3,fp3 /* -(|x|+=0.5) */