[libgcc] Fix PowerPC libgcc issues with -mabi=ieeelongdouble

Message ID 20171215041013.GA15916@ibm-tiger.the-meissners.org
State New
Headers show
Series
  • [libgcc] Fix PowerPC libgcc issues with -mabi=ieeelongdouble
Related show

Commit Message

Michael Meissner Dec. 15, 2017, 4:10 a.m.
I am working on some patches to optionally enable multilibs for the PowerPC
long double support to be switchable between IBM extended double and IEEE
128-bit floating point.  While the patches to actually enable the multlibs need
some more tweaking, it did point up an issue in the libgcc _Float128 and IBM
extended double functions.

These patches use the correct types for IBM extended double and __float128 if
the IEEE default is used.  I have built the compiler with bootstrap builds and
there were no regressions in running the tests on a little endian power8
system.

In addition, I had fixed the previous changes to _divkc3.c and _mulkc3.c so
that these functions now include soft-fp.h and quad-float128.h, which provides
the appropriate prototypes.

I have also done a bootstrap build with my preliminary multilib patches, and it
built fine with both -mabi=ieeelongdouble and -mabi=ibmlongdouble
configurations.

Can I apply these patches to libgcc?

2017-12-14  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/_divkc3.c: Switch to using soft-fp.h and
	quad-float128.h include files and use the types that they define,
	instead of hand-rolling the types.
	* config/rs6000/_mulkc3.c: Likewise.
	* config/rs6000/ibm-ldouble.c: If we have __float128/_Float128,
	use __ieee128 for the IBM extended double type instead of long double.
	Change all functions.
	* config/rs6000/quad-float128.h (IBM128_TYPE): Always use
	__ieee128.
	(CVT_FLOAT128_TO_IBM128): Use long double instead of __float128 on
	systems where the default long double is IEEE 128-bit floating
	point.
	* config/rs6000/extendkftf2-sw.c (extendkftf2_sw): Likewise.
	* config/rs6000/trunctfkf2-sw.c (__trunctfkf2_sw): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

Comments

Segher Boessenkool Jan. 8, 2018, 11:01 a.m. | #1
On Thu, Dec 14, 2017 at 11:10:13PM -0500, Michael Meissner wrote:
> I am working on some patches to optionally enable multilibs for the PowerPC

> long double support to be switchable between IBM extended double and IEEE

> 128-bit floating point.  While the patches to actually enable the multlibs need

> some more tweaking, it did point up an issue in the libgcc _Float128 and IBM

> extended double functions.

> 

> These patches use the correct types for IBM extended double and __float128 if

> the IEEE default is used.  I have built the compiler with bootstrap builds and

> there were no regressions in running the tests on a little endian power8

> system.

> 

> In addition, I had fixed the previous changes to _divkc3.c and _mulkc3.c so

> that these functions now include soft-fp.h and quad-float128.h, which provides

> the appropriate prototypes.

> 

> I have also done a bootstrap build with my preliminary multilib patches, and it

> built fine with both -mabi=ieeelongdouble and -mabi=ibmlongdouble

> configurations.

> 

> Can I apply these patches to libgcc?


As far as I can follow, it's okay for trunk.  Please apply.  Thanks,


Segher


> 2017-12-14  Michael Meissner  <meissner@linux.vnet.ibm.com>

> 

> 	* config/rs6000/_divkc3.c: Switch to using soft-fp.h and

> 	quad-float128.h include files and use the types that they define,

> 	instead of hand-rolling the types.

> 	* config/rs6000/_mulkc3.c: Likewise.

> 	* config/rs6000/ibm-ldouble.c: If we have __float128/_Float128,

> 	use __ieee128 for the IBM extended double type instead of long double.

> 	Change all functions.

> 	* config/rs6000/quad-float128.h (IBM128_TYPE): Always use

> 	__ieee128.

> 	(CVT_FLOAT128_TO_IBM128): Use long double instead of __float128 on

> 	systems where the default long double is IEEE 128-bit floating

> 	point.

> 	* config/rs6000/extendkftf2-sw.c (extendkftf2_sw): Likewise.

> 	* config/rs6000/trunctfkf2-sw.c (__trunctfkf2_sw): Likewise.

Patch

Index: libgcc/config/rs6000/_divkc3.c
===================================================================
--- libgcc/config/rs6000/_divkc3.c	(revision 255658)
+++ libgcc/config/rs6000/_divkc3.c	(working copy)
@@ -23,12 +23,12 @@  see the files COPYING3 and COPYING.RUNTI
 
 /* This is a temporary specialization of code from libgcc/libgcc2.c.  */
 
-typedef float KFtype __attribute__ ((mode (KF)));
-typedef __complex float KCtype __attribute__ ((mode (KC)));
+#include "soft-fp.h"
+#include "quad-float128.h"
 
-#define COPYSIGN(x,y) __builtin_copysignq (x, y)
-#define INFINITY __builtin_infq ()
-#define FABS __builtin_fabsq
+#define COPYSIGN(x,y) __builtin_copysignf128 (x, y)
+#define INFINITY __builtin_inff128 ()
+#define FABS __builtin_fabsf128
 #define isnan __builtin_isnan
 #define isinf __builtin_isinf
 #define isfinite __builtin_isfinite
@@ -37,13 +37,11 @@  typedef __complex float KCtype __attribu
 #define __divkc3 __divkc3_sw
 #endif
 
-extern KCtype __divkc3 (KFtype, KFtype, KFtype, KFtype);
-
-KCtype
-__divkc3 (KFtype a, KFtype b, KFtype c, KFtype d)
+TCtype
+__divkc3 (TFtype a, TFtype b, TFtype c, TFtype d)
 {
-  KFtype denom, ratio, x, y;
-  KCtype res;
+  TFtype denom, ratio, x, y;
+  TCtype res;
 
   /* ??? We can get better behavior from logarithmic scaling instead of
      the division.  But that would mean starting to link libgcc against
Index: libgcc/config/rs6000/ibm-ldouble.c
===================================================================
--- libgcc/config/rs6000/ibm-ldouble.c	(revision 255658)
+++ libgcc/config/rs6000/ibm-ldouble.c	(working copy)
@@ -56,6 +56,15 @@  see the files COPYING3 and COPYING.RUNTI
 
 #define nonfinite(a) unlikely (! isless (fabs (a), inf ()))
 
+/* If we have __float128/_Float128, use __ibm128 instead of long double.  On
+   other systems, use long double, because __ibm128 might not have been
+   created.  */
+#ifdef __FLOAT128__
+#define IBM128_TYPE __ibm128
+#else
+#define IBM128_TYPE long double
+#endif
+
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
 # define _strong_alias(name, aliasname) \
@@ -65,10 +74,10 @@  see the files COPYING3 and COPYING.RUNTI
    but GCC currently generates poor code when a union is used to turn
    a long double into a pair of doubles.  */
 
-long double __gcc_qadd (double, double, double, double);
-long double __gcc_qsub (double, double, double, double);
-long double __gcc_qmul (double, double, double, double);
-long double __gcc_qdiv (double, double, double, double);
+IBM128_TYPE __gcc_qadd (double, double, double, double);
+IBM128_TYPE __gcc_qsub (double, double, double, double);
+IBM128_TYPE __gcc_qmul (double, double, double, double);
+IBM128_TYPE __gcc_qdiv (double, double, double, double);
 
 #if defined __ELF__ && defined SHARED \
     && (defined __powerpc64__ || !(defined __linux__ || defined __gnu_hurd__))
@@ -88,17 +97,17 @@  __asm__ (".symver __gcc_qadd,_xlqadd@GCC
 	 ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4");
 #endif
 
-/* Combine two 'double' values into one 'long double' and return the result.  */
-static inline long double
+/* Combine two 'double' values into one 'IBM128_TYPE' and return the result.  */
+static inline IBM128_TYPE
 pack_ldouble (double dh, double dl)
 {
-#if defined (__LONG_DOUBLE_128__) \
+#if defined (__LONG_DOUBLE_128__) && defined (__LONG_DOUBLE_IBM128__)	\
     && !(defined (_SOFT_FLOAT) || defined (__NO_FPRS__))
   return __builtin_pack_longdouble (dh, dl);
 #else
   union
   {
-    long double ldval;
+    IBM128_TYPE ldval;
     double dval[2];
   } x;
   x.dval[0] = dh;
@@ -107,8 +116,8 @@  pack_ldouble (double dh, double dl)
 #endif
 }
 
-/* Add two 'long double' values and return the result.	*/
-long double
+/* Add two 'IBM128_TYPE' values and return the result.	*/
+IBM128_TYPE
 __gcc_qadd (double a, double aa, double c, double cc)
 {
   double xh, xl, z, q, zz;
@@ -147,7 +156,7 @@  __gcc_qadd (double a, double aa, double 
   return pack_ldouble (xh, xl);
 }
 
-long double
+IBM128_TYPE
 __gcc_qsub (double a, double b, double c, double d)
 {
   return __gcc_qadd (a, b, -c, -d);
@@ -157,7 +166,7 @@  __gcc_qsub (double a, double b, double c
 static double fmsub (double, double, double);
 #endif
 
-long double
+IBM128_TYPE
 __gcc_qmul (double a, double b, double c, double d)
 {
   double xh, xl, t, tau, u, v, w;
@@ -181,7 +190,7 @@  __gcc_qmul (double a, double b, double c
   tau += v + w;	    /* Add in other second-order terms.	 */
   u = t + tau;
 
-  /* Construct long double result.  */
+  /* Construct IBM128_TYPE result.  */
   if (nonfinite (u))
     return u;
   xh = u;
@@ -189,7 +198,7 @@  __gcc_qmul (double a, double b, double c
   return pack_ldouble (xh, xl);
 }
 
-long double
+IBM128_TYPE
 __gcc_qdiv (double a, double b, double c, double d)
 {
   double xh, xl, s, sigma, t, tau, u, v, w;
@@ -226,7 +235,7 @@  __gcc_qdiv (double a, double b, double c
   tau = ((v-sigma)+w)/c;   /* Correction to t.  */
   u = t + tau;
 
-  /* Construct long double result.  */
+  /* Construct IBM128_TYPE result.  */
   if (nonfinite (u))
     return u;
   xh = u;
@@ -236,32 +245,32 @@  __gcc_qdiv (double a, double b, double c
 
 #if defined (_SOFT_DOUBLE) && defined (__LONG_DOUBLE_128__)
 
-long double __gcc_qneg (double, double);
+IBM128_TYPE __gcc_qneg (double, double);
 int __gcc_qeq (double, double, double, double);
 int __gcc_qne (double, double, double, double);
 int __gcc_qge (double, double, double, double);
 int __gcc_qle (double, double, double, double);
-long double __gcc_stoq (float);
-long double __gcc_dtoq (double);
+IBM128_TYPE __gcc_stoq (float);
+IBM128_TYPE __gcc_dtoq (double);
 float __gcc_qtos (double, double);
 double __gcc_qtod (double, double);
 int __gcc_qtoi (double, double);
 unsigned int __gcc_qtou (double, double);
-long double __gcc_itoq (int);
-long double __gcc_utoq (unsigned int);
+IBM128_TYPE __gcc_itoq (int);
+IBM128_TYPE __gcc_utoq (unsigned int);
 
 extern int __eqdf2 (double, double);
 extern int __ledf2 (double, double);
 extern int __gedf2 (double, double);
 
-/* Negate 'long double' value and return the result.	*/
-long double
+/* Negate 'IBM128_TYPE' value and return the result.	*/
+IBM128_TYPE
 __gcc_qneg (double a, double aa)
 {
   return pack_ldouble (-a, -aa);
 }
 
-/* Compare two 'long double' values for equality.  */
+/* Compare two 'IBM128_TYPE' values for equality.  */
 int
 __gcc_qeq (double a, double aa, double c, double cc)
 {
@@ -272,7 +281,7 @@  __gcc_qeq (double a, double aa, double c
 
 strong_alias (__gcc_qeq, __gcc_qne);
 
-/* Compare two 'long double' values for less than or equal.  */
+/* Compare two 'IBM128_TYPE' values for less than or equal.  */
 int
 __gcc_qle (double a, double aa, double c, double cc)
 {
@@ -283,7 +292,7 @@  __gcc_qle (double a, double aa, double c
 
 strong_alias (__gcc_qle, __gcc_qlt);
 
-/* Compare two 'long double' values for greater than or equal.  */
+/* Compare two 'IBM128_TYPE' values for greater than or equal.  */
 int
 __gcc_qge (double a, double aa, double c, double cc)
 {
@@ -294,35 +303,35 @@  __gcc_qge (double a, double aa, double c
 
 strong_alias (__gcc_qge, __gcc_qgt);
 
-/* Convert single to long double.  */
-long double
+/* Convert single to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_stoq (float a)
 {
   return pack_ldouble ((double) a, 0.0);
 }
 
-/* Convert double to long double.  */
-long double
+/* Convert double to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_dtoq (double a)
 {
   return pack_ldouble (a, 0.0);
 }
 
-/* Convert long double to single.  */
+/* Convert IBM128_TYPE to single.  */
 float
 __gcc_qtos (double a, double aa __attribute__ ((__unused__)))
 {
   return (float) a;
 }
 
-/* Convert long double to double.  */
+/* Convert IBM128_TYPE to double.  */
 double
 __gcc_qtod (double a, double aa __attribute__ ((__unused__)))
 {
   return a;
 }
 
-/* Convert long double to int.  */
+/* Convert IBM128_TYPE to int.  */
 int
 __gcc_qtoi (double a, double aa)
 {
@@ -330,7 +339,7 @@  __gcc_qtoi (double a, double aa)
   return (int) z;
 }
 
-/* Convert long double to unsigned int.  */
+/* Convert IBM128_TYPE to unsigned int.  */
 unsigned int
 __gcc_qtou (double a, double aa)
 {
@@ -338,15 +347,15 @@  __gcc_qtou (double a, double aa)
   return (unsigned int) z;
 }
 
-/* Convert int to long double.  */
-long double
+/* Convert int to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_itoq (int a)
 {
   return __gcc_dtoq ((double) a);
 }
 
-/* Convert unsigned int to long double.  */
-long double
+/* Convert unsigned int to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_utoq (unsigned int a)
 {
   return __gcc_dtoq ((double) a);
@@ -361,7 +370,7 @@  int __gcc_qunord (double, double, double
 extern int __eqdf2 (double, double);
 extern int __unorddf2 (double, double);
 
-/* Compare two 'long double' values for unordered.  */
+/* Compare two 'IBM128_TYPE' values for unordered.  */
 int
 __gcc_qunord (double a, double aa, double c, double cc)
 {
@@ -389,7 +398,7 @@  fmsub (double a, double b, double c)
     FP_DECL_Q(V);
     FP_DECL_D(R);
     double r;
-    long double u, x, y, z;
+    IBM128_TYPE u, x, y, z;
 
     FP_INIT_ROUNDMODE;
     FP_UNPACK_RAW_D (A, a);
Index: libgcc/config/rs6000/quad-float128.h
===================================================================
--- libgcc/config/rs6000/quad-float128.h	(revision 255658)
+++ libgcc/config/rs6000/quad-float128.h	(working copy)
@@ -51,12 +51,7 @@  typedef __complex float TCtype __attribu
 
 #include <quad.h>
 
-#ifdef __LONG_DOUBLE_IEEE128__
-#define IBM128_TYPE		__ibm128
-
-#else
-#define IBM128_TYPE		long double
-#endif
+#define IBM128_TYPE	__ibm128
 
 /* Add prototypes of the library functions created.  In case the appropriate
    int/long types are not declared in scope by the time quad.h is included,
@@ -185,7 +180,7 @@  union ibm128_union {
 #define CVT_FLOAT128_TO_IBM128(RESULT, VALUE)				\
 {									\
   double __high, __low;							\
-  __float128 __value = (VALUE);						\
+  TFtype __value = (VALUE);						\
   union ibm128_union u;							\
 									\
   __high = (double) __value;						\
@@ -196,7 +191,7 @@  union ibm128_union {
     {									\
       double __high_temp;						\
 									\
-      __low = (double) (__value - (__float128) __high);			\
+      __low = (double) (__value - (TFtype) __high);			\
       /* Renormalize low/high and move them into canonical IBM long	\
 	 double form.  */						\
       __high_temp = __high + __low;					\
@@ -220,13 +215,13 @@  union ibm128_union {
 									\
   /* Handle the special cases of NAN and infinity.  */			\
   if (__builtin_isnan (__high) || __builtin_isinf (__high))		\
-    RESULT = (__float128) __high;					\
+    RESULT = (TFtype) __high;						\
 									\
   /* If low is 0.0, there no need to do the add.  In addition,		\
      avoiding the add produces the correct sign if high is -0.0.  */	\
   else if (__low == 0.0)						\
-    RESULT = (__float128) __high;					\
+    RESULT = (TFtype) __high;						\
 									\
   else									\
-    RESULT = ((__float128) __high) + ((__float128) __low);		\
+    RESULT = ((TFtype) __high) + ((TFtype) __low);			\
 }
Index: libgcc/config/rs6000/extendkftf2-sw.c
===================================================================
--- libgcc/config/rs6000/extendkftf2-sw.c	(revision 255658)
+++ libgcc/config/rs6000/extendkftf2-sw.c	(working copy)
@@ -44,7 +44,7 @@ 
 #endif
 
 IBM128_TYPE
-__extendkftf2_sw (__float128 value)
+__extendkftf2_sw (TFtype value)
 {
   IBM128_TYPE ret;
 
Index: libgcc/config/rs6000/trunctfkf2-sw.c
===================================================================
--- libgcc/config/rs6000/trunctfkf2-sw.c	(revision 255658)
+++ libgcc/config/rs6000/trunctfkf2-sw.c	(working copy)
@@ -43,10 +43,10 @@ 
 #define __trunctfkf2_sw __trunctfkf2
 #endif
 
-__float128
+TFtype
 __trunctfkf2_sw (IBM128_TYPE value)
 {
-  __float128 ret;
+  TFtype ret;
 
   CVT_IBM128_TO_FLOAT128 (ret, value);
   return ret;
Index: libgcc/config/rs6000/_mulkc3.c
===================================================================
--- libgcc/config/rs6000/_mulkc3.c	(revision 255658)
+++ libgcc/config/rs6000/_mulkc3.c	(working copy)
@@ -23,11 +23,11 @@  see the files COPYING3 and COPYING.RUNTI
 
 /* This is a temporary specialization of code from libgcc/libgcc2.c.  */
 
-typedef float KFtype __attribute__ ((mode (KF)));
-typedef __complex float KCtype __attribute__ ((mode (KC)));
+#include "soft-fp.h"
+#include "quad-float128.h"
 
-#define COPYSIGN(x,y) __builtin_copysignq (x, y)
-#define INFINITY __builtin_infq ()
+#define COPYSIGN(x,y) __builtin_copysignf128 (x, y)
+#define INFINITY __builtin_inff128 ()
 #define isnan __builtin_isnan
 #define isinf __builtin_isinf
 
@@ -35,13 +35,11 @@  typedef __complex float KCtype __attribu
 #define __mulkc3 __mulkc3_sw
 #endif
 
-extern KCtype __mulkc3 (KFtype, KFtype, KFtype, KFtype);
-
-KCtype
-__mulkc3 (KFtype a, KFtype b, KFtype c, KFtype d)
+TCtype
+__mulkc3 (TFtype a, TFtype b, TFtype c, TFtype d)
 {
-  KFtype ac, bd, ad, bc, x, y;
-  KCtype res;
+  TFtype ac, bd, ad, bc, x, y;
+  TCtype res;
 
   ac = a * c;
   bd = b * d;