This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Avoid "invalid" exceptions from powerpc fabsl (sNaN) (bug 20157) [committed]


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.  Committed.

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.

diff --git a/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S b/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S
index 0462d20..866e817 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S
@@ -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)
 
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_fabsl.S b/sysdeps/powerpc/powerpc64/fpu/s_fabsl.S
index 0462d20..1f8f05e 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_fabsl.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_fabsl.S
@@ -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)
 

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]