]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Avoid "invalid" exceptions from powerpc fabsl (sNaN) (bug 20157).
authorJoseph Myers <joseph@codesourcery.com>
Fri, 27 May 2016 15:29:31 +0000 (15:29 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Fri, 27 May 2016 15:29:31 +0000 (15:29 +0000)
The powerpc implementations of fabsl for ldbl-128ibm (both powerpc32
and powerpc64) wrongly raise the "invalid" exception for sNaN
arguments.  fabs functions should be quiet for all inputs including
signaling NaNs.  The problem is the use of a comparison instruction
fcmpu to determine if the high part of the argument is negative and so
the low part needs to be negated; such instructions raise "invalid"
for sNaNs.

There is a pure integer implementation of fabsl in
sysdeps/ieee754/ldbl-128ibm/s_fabsl.c.  However, it's not necessary to
use it to avoid such exceptions.  The fsel instruction does not raise
exceptions for sNaNs, and can be used in place of the original
comparison.  (Note that if the high part is zero or a NaN, it does not
matter whether the low part is negated; the choice of whether the low
part of a zero is +0 or -0 does not affect the value, and the low part
of a NaN does not affect the value / payload either.)

The condition in GCC for fsel to be available is TARGET_PPC_GFXOPT,
corresponding to the _ARCH_PPCGR predefined macro.  fsel is available
on all 64-bit processors supported by GCC.  A few 32-bit processors
supported by GCC do not have TARGET_PPC_GFXOPT despite having hard
float support.  To support those processors, integer code (similar to
that in copysignl) is included for the !_ARCH_PPCGR case for
powerpc32.

Tested for powerpc32 (configurations with and without _ARCH_PPCGR) and
powerpc64.

[BZ #20157]
* sysdeps/powerpc/powerpc32/fpu/s_fabsl.S (__fabsl): Use fsel to
determine whether to negate low half if [_ARCH_PPCGR], and integer
comparison otherwise.
* sysdeps/powerpc/powerpc64/fpu/s_fabsl.S (__fabsl): Use fsel to
determine whether to negate low half.

ChangeLog
sysdeps/powerpc/powerpc32/fpu/s_fabsl.S
sysdeps/powerpc/powerpc64/fpu/s_fabsl.S

index 31736a6352a75a37f2b3c17e3720081c3530066c..f400460d755e2e52774a4d9d7badc6d12a2aa255 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2016-05-27  Joseph Myers  <joseph@codesourcery.com>
 
+       [BZ #20157]
+       * sysdeps/powerpc/powerpc32/fpu/s_fabsl.S (__fabsl): Use fsel to
+       determine whether to negate low half if [_ARCH_PPCGR], and integer
+       comparison otherwise.
+       * sysdeps/powerpc/powerpc64/fpu/s_fabsl.S (__fabsl): Use fsel to
+       determine whether to negate low half.
+
        * math/libm-test.inc (NO_TEST_INLINE_FLOAT): Remove macro.
        (NO_TEST_INLINE_DOUBLE): Likewise.
        (TEST_COND_x86_64): Likewise.
index 0462d2063027951ab657cababff9b4ad1dd36d07..866e817008e9000bf815c73833450cdeba518a81 100644 (file)
@@ -24,11 +24,28 @@ ENTRY(__fabsl)
 /* long double [f1,f2] fabs (long double [f1,f2] x);
    fabs(x,y) returns a value with the magnitude of x and
    with the sign bit of y.  */
+#ifdef _ARCH_PPCGR
+       /* fsel available.  */
        fmr     fp0,fp1
+#else
+       /* Use integer operations to test sign of high part to avoid
+          exceptions on sNaNs.  */
+       stwu    r1,-16(r1)
+       cfi_adjust_cfa_offset (16)
+       stfd    fp1,8(r1)
+#endif
        fabs    fp1,fp1
-       fcmpu   cr1,fp0,fp1
-       beqlr   cr1
+#ifdef _ARCH_PPCGR
+       fneg    fp3,fp2
+       fsel    fp2,fp0,fp2,fp3
+#else
+       lwz     r3,8+HIWORD(r1)
+       cmpwi   cr6,r3,0
+       addi    r1,r1,16
+       cfi_adjust_cfa_offset (-16)
+       bgelr   cr6
        fneg    fp2,fp2
+#endif
        blr
 END (__fabsl)
 
index 0462d2063027951ab657cababff9b4ad1dd36d07..1f8f05e091b0d49a0de2bc0d3cf0dbdf24e815e8 100644 (file)
@@ -26,9 +26,8 @@ ENTRY(__fabsl)
    with the sign bit of y.  */
        fmr     fp0,fp1
        fabs    fp1,fp1
-       fcmpu   cr1,fp0,fp1
-       beqlr   cr1
-       fneg    fp2,fp2
+       fneg    fp3,fp2
+       fsel    fp2,fp0,fp2,fp3
        blr
 END (__fabsl)