public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PowerPC: Map IEEE 128-bit long double built-in functions
@ 2020-10-22 22:03 Michael Meissner
  2020-10-26 22:48 ` will schmidt
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Michael Meissner @ 2020-10-22 22:03 UTC (permalink / raw)
  To: gcc-patches, Michael Meissner, Segher Boessenkool,
	David Edelsohn, Bill Schmidt, Peter Bergner, Jeff Law,
	Jonathan Wakely

PowerPC: Map IEEE 128-bit long double built-in functions

This patch is revised from the first and second versions of the patch posted.
It now uses the names that are not in the user's namespace (i.e. __sinieee128
instead of sinf128) that Joseph Myers suggested.

In addition, I added the changes suggested by Segher the last time this patch
was submitted (changing where the default is, fixing the scalbl built-in name,
using strlen and xaprintf).

I have split all of these patches into separate patches to hopefully get them
into the tree.

This patch goes through the built-in functions and changes the name of the
math, scanf, and printf built-in functions to use the functions that GLIBC
provides when long double uses the IEEE 128-bit representation.

In addition, changing the name in GCC allows the Fortran compiler to
automatically use the correct name.

To map the math functions, typically this patch changes <name>l to
__<name>ieee128.  However there are some exceptions that are handled with this
patch.

To map the printf functions, <name> is mapped to __<name>ieee128.

To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128.

I have tested this patch with bootstrap builds on a little endian power9 system
running Linux.  With the other patches, I have built two full bootstrap builds
using this patch and the patches after this patch.  One build used the current
default for long double (IBM extended double) and the other build switched the
default to IEEE 128-bit.  I used the Advance Toolchain AT 14.0 compiler as the
library used by this compiler.  There are no regressions between the tests.
There are 3 fortran benchmarks (ieee/large_2.f90, default_format_2.f90, and
default_format_denormal_2.f90) that now pass.

Can I install this into the trunk?

We have gotten some requests to back port these changes to GCC 10.x.  At the
moment, I am not planning to do the back port, but I may need to in the future.

gcc/
2020-10-22  Michael Meissner  <meissner@linux.ibm.com>

	* config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Add
	support for mapping built-in function names for long double
	built-in functions if long double is IEEE 128-bit.

gcc/testsuite/
2020-10-22  Michael Meissner  <meissner@linux.ibm.com>

	* gcc.target/powerpc/float128-longdouble-math.c: New test.
	* gcc.target/powerpc/float128-longdouble-stdio.c: New test.
	* gcc.target/powerpc/float128-math.c: Adjust test for new name
	being generated.
---
 gcc/config/rs6000/rs6000.c                    | 135 ++++-
 .../powerpc/float128-longdouble-math.c        | 567 ++++++++++++++++++
 .../powerpc/float128-longdouble-stdio.c       |  37 ++
 .../gcc.target/powerpc/float128-math.c        |   6 +-
 4 files changed, 710 insertions(+), 35 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 141684e3157..8c2544ee88d 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -26893,56 +26893,127 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
    library before you can switch the real*16 type at compile time.
 
    We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name.  We
-   only do this if the default is that long double is IBM extended double, and
-   the user asked for IEEE 128-bit.  */
+   only do this transformation if the __float128 type is enabled.  This
+   prevents us from doing the transformation on older 32-bit ports that might
+   have enabled using IEEE 128-bit floating point as the default long double
+   type.  */
 
 static tree
 rs6000_mangle_decl_assembler_name (tree decl, tree id)
 {
-  if (!TARGET_IEEEQUAD_DEFAULT && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
-      && TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl) )
+  if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
+      && TREE_CODE (decl) == FUNCTION_DECL
+      && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
     {
       size_t len = IDENTIFIER_LENGTH (id);
       const char *name = IDENTIFIER_POINTER (id);
+      char *newname = NULL;
 
-      if (name[len - 1] == 'l')
+      /* See if it is one of the built-in functions with an unusual name.  */
+      switch (DECL_FUNCTION_CODE (decl))
 	{
-	  bool uses_ieee128_p = false;
-	  tree type = TREE_TYPE (decl);
-	  machine_mode ret_mode = TYPE_MODE (type);
+	case BUILT_IN_DREML:
+	  newname = xstrdup ("__remainderieee128");
+	  break;
 
-	  /* See if the function returns a IEEE 128-bit floating point type or
-	     complex type.  */
-	  if (ret_mode == TFmode || ret_mode == TCmode)
-	    uses_ieee128_p = true;
-	  else
-	    {
-	      function_args_iterator args_iter;
-	      tree arg;
+	case BUILT_IN_GAMMAL:
+	  newname = xstrdup ("__lgammaieee128");
+	  break;
+
+	case BUILT_IN_GAMMAL_R:
+	case BUILT_IN_LGAMMAL_R:
+	  newname = xstrdup ("__lgammaieee128_r");
+	  break;
+
+	case BUILT_IN_NEXTTOWARD:
+	  newname = xstrdup ("__nexttoward_to_ieee128");
+	  break;
+
+	case BUILT_IN_NEXTTOWARDF:
+	  newname = xstrdup ("__nexttowardf_to_ieee128");
+	  break;
+
+	case BUILT_IN_NEXTTOWARDL:
+	  newname = xstrdup ("__nexttowardieee128");
+	  break;
+
+	case BUILT_IN_POW10L:
+	  newname = xstrdup ("__exp10ieee128");
+	  break;
+
+	case BUILT_IN_SCALBL:
+	  newname = xstrdup ("__scalbieee128");
+	  break;
+
+	case BUILT_IN_SIGNIFICANDL:
+	  newname = xstrdup ("__significandieee128");
+	  break;
+
+	case BUILT_IN_SINCOSL:
+	  newname = xstrdup ("__sincosieee128");
+	  break;
 
-	      /* See if the function passes a IEEE 128-bit floating point type
-		 or complex type.  */
-	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
+	default:
+	  break;
+	}
+
+      /* Update the __builtin_*printf && __builtin_*scanf functions.  */
+      if (!newname)
+	{
+	  size_t printf_len = strlen ("printf");
+	  size_t scanf_len = strlen ("scanf");
+
+	  if (len >= printf_len
+	      && strcmp (name + len - printf_len, "printf") == 0)
+	    newname = xasprintf ("__%sieee128", name);
+
+	  else if (len >= scanf_len
+		   && strcmp (name + len - scanf_len, "scanf") == 0)
+	    newname = xasprintf ("__isoc99_%sieee128", name);
+
+	  else if (name[len - 1] == 'l')
+	    {
+	      bool uses_ieee128_p = false;
+	      tree type = TREE_TYPE (decl);
+	      machine_mode ret_mode = TYPE_MODE (type);
+
+	      /* See if the function returns a IEEE 128-bit floating point type or
+		 complex type.  */
+	      if (ret_mode == TFmode || ret_mode == TCmode)
+		uses_ieee128_p = true;
+	      else
 		{
-		  machine_mode arg_mode = TYPE_MODE (arg);
-		  if (arg_mode == TFmode || arg_mode == TCmode)
+		  function_args_iterator args_iter;
+		  tree arg;
+
+		  /* See if the function passes a IEEE 128-bit floating point type
+		     or complex type.  */
+		  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
 		    {
-		      uses_ieee128_p = true;
-		      break;
+		      machine_mode arg_mode = TYPE_MODE (arg);
+		      if (arg_mode == TFmode || arg_mode == TCmode)
+			{
+			  uses_ieee128_p = true;
+			  break;
+			}
 		    }
 		}
-	    }
 
-	  /* If we passed or returned an IEEE 128-bit floating point type,
-	     change the name.  */
-	  if (uses_ieee128_p)
-	    {
-	      char *name2 = (char *) alloca (len + 4);
-	      memcpy (name2, name, len - 1);
-	      strcpy (name2 + len - 1, "f128");
-	      id = get_identifier (name2);
+	      /* If we passed or returned an IEEE 128-bit floating point type,
+		 change the name.  Use __<name>ieee128, instead of <name>l.  */
+	      if (uses_ieee128_p)
+		newname = xasprintf ("__%.*sieee128", (int)(len - 1), name);
 	    }
 	}
+
+      if (newname)
+	{
+	  if (TARGET_DEBUG_BUILTIN)
+	    fprintf (stderr, "Map %s => %s\n", name, newname);
+
+	  id = get_identifier (newname);
+	  free (newname);
+	}
     }
 
   return id;
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
new file mode 100644
index 00000000000..50d40180fdc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
@@ -0,0 +1,567 @@
+/* { dg-require-effective-target ppc_float128_hw } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */
+
+/* Test if switching long double to IEEE 128-bit maps all of the math built-in
+   function names correctly.  We explicitly turn off PC-relative support to
+   make it simpler to compare the call without having a @notoc qualifier.  */
+
+/* Debugging support to use 'name' instead of '__builtin_name'.  Note if you
+   enable this, you will likely need additional flags to get all of the
+   functions defined.  */
+#ifdef DO_FUNC
+#ifndef DO_MATH_H
+#define DO_MATH_H	1
+#endif
+
+#define BUILTIN0(FUNC)                   FUNC ()
+#define BUILTIN1(FUNC, ARG1)             FUNC (ARG1)
+#define BUILTIN2(FUNC, ARG1, ARG2)       FUNC (ARG1, ARG2)
+#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) FUNC (ARG1, ARG2, ARG3)
+
+#else
+#define BUILTIN0(FUNC)                   __builtin_ ## FUNC ()
+#define BUILTIN1(FUNC, ARG1)             __builtin_ ## FUNC (ARG1)
+#define BUILTIN2(FUNC, ARG1, ARG2)       __builtin_ ## FUNC (ARG1, ARG2)
+#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) __builtin_ ## FUNC (ARG1, ARG2, ARG3)
+#endif
+
+/* Debugging support to compare using math.h with the raw built-in functions.  */
+#ifdef DO_MATH_H
+#define __STDC_WANT_IEC_60559_TYPES_EXT__	1
+#define __STDC_WANT_IEC_60559_FUNCS_EXT__	1
+#define _GNU_SOURCE				1
+#define _XOPEN_SOURCE				1
+
+#include <math.h>
+#include <complex.h>
+#endif
+
+/* Built-in functions that returns a long double and take one long double
+   argument.  */
+
+void
+return_ld_arg_ld (long double *p,
+		  long double *q)
+{
+  /* { dg-final { scan-assembler {\m__acoshieee128\M} } }  */
+  *p++ = BUILTIN1 (acoshl, *q++);
+
+  /* { dg-final { scan-assembler {\m__acosieee128\M} } }  */
+  *p++ = BUILTIN1 (acosl, *q++);
+
+  /* { dg-final { scan-assembler {\m__asinhieee128\M} } }  */
+  *p++ = BUILTIN1 (asinhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__asinieee128\M} } }  */
+  *p++ = BUILTIN1 (asinl, *q++);
+
+  /* { dg-final { scan-assembler {\m__atanhieee128\M} } }  */
+  *p++ = BUILTIN1 (atanhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__atanieee128\M} } }  */
+  *p++ = BUILTIN1 (atanl, *q++);
+
+  /* { dg-final { scan-assembler {\m__cbrtieee128\M} } }  */
+  *p++ = BUILTIN1 (cbrtl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2\M} } }  */
+  *p++ = BUILTIN1 (ceill, *q++);
+
+  /* { dg-final { scan-assembler {\m__coshieee128\M} } }  */
+  *p++ = BUILTIN1 (coshl, *q++);
+
+  /* { dg-final { scan-assembler {\m__cosieee128\M} } }  */
+  *p++ = BUILTIN1 (cosl, *q++);
+
+  /* { dg-final { scan-assembler {\m__erfcieee128\M} } }  */
+  *p++ = BUILTIN1 (erfcl, *q++);
+
+  /* { dg-final { scan-assembler {\m__erfieee128\M} } }  */
+  *p++ = BUILTIN1 (erfl, *q++);
+
+  /* { dg-final { scan-assembler {\m__exp10ieee128\M} } }  */
+  *p++ = BUILTIN1 (exp10l, *q++);
+
+  /* { dg-final { scan-assembler {\m__exp2ieee128\M} } }  */
+  *p++ = BUILTIN1 (exp2l, *q++);
+
+  /* { dg-final { scan-assembler {\m__expieee128\M} } }  */
+  *p++ = BUILTIN1 (expl, *q++);
+
+  /* { dg-final { scan-assembler {\m__expm1ieee128\M} } }  */
+  *p++ = BUILTIN1 (expm1l, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsabsqp\M} } }  */
+  *p++ = BUILTIN1 (fabsl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3\M} } }  */
+  *p++ = BUILTIN1 (floorl, *q++);
+
+  /* { dg-final { scan-assembler {\m__lgammaieee128\M} } }  */
+  *p++ = BUILTIN1 (gammal, *q++);
+
+  /* { dg-final { scan-assembler {\m__j0ieee128\M} } }  */
+  *p++ = BUILTIN1 (j0l, *q++);
+
+  /* { dg-final { scan-assembler {\m__j1ieee128\M} } }  */
+  *p++ = BUILTIN1 (j1l, *q++);
+
+  /* lgammaf128 mentioned previously.  */
+  *p++ = BUILTIN1 (lgammal, *q++);
+
+  /* { dg-final { scan-assembler {\m__log10ieee128\M} } }  */
+  *p++ = BUILTIN1 (log10l, *q++);
+
+  /* { dg-final { scan-assembler {\m__log1pieee128\M} } }  */
+  *p++ = BUILTIN1 (log1pl, *q++);
+
+  /* { dg-final { scan-assembler {\m__log2ieee128\M} } }  */
+  *p++ = BUILTIN1 (log2l, *q++);
+
+  /* { dg-final { scan-assembler {\m__logbieee128\M} } }  */
+  *p++ = BUILTIN1 (logbl, *q++);
+
+  /* { dg-final { scan-assembler {\m__logieee128\M} } }  */
+  *p++ = BUILTIN1 (logl, *q++);
+
+  /* { dg-final { scan-assembler {\m__nearbyintieee128\M} } }  */
+  *p++ = BUILTIN1 (nearbyintl, *q++);
+
+  /* { dg-final { scan-assembler {\m__exp10ieee128\M} } }  */
+  *p++ = BUILTIN1 (pow10l, *q++);
+
+  /* { dg-final { scan-assembler {\m__rintieee128\M} } }  */
+  *p++ = BUILTIN1 (rintl, *q++);
+
+  /* { dg-final { scan-assembler {\m__roundevenieee128\M} } }  */
+  *p++ = BUILTIN1 (roundevenl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,0\M} } }  */
+  *p++ = BUILTIN1 (roundl, *q++);
+
+  /* { dg-final { scan-assembler {\m__significandieee128\M} } }  */
+  *p++ = BUILTIN1 (significandl, *q++);
+
+  /* { dg-final { scan-assembler {\m__sinhieee128\M} } }  */
+  *p++ = BUILTIN1 (sinhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__sinieee128\M} } }  */
+  *p++ = BUILTIN1 (sinl, *q++);
+
+  /* { dg-final { scan-assembler {\m__sqrtieee128\M} } }  */
+  *p++ = BUILTIN1 (sqrtl, *q++);
+
+  /* { dg-final { scan-assembler {\m__tanhieee128\M} } }  */
+  *p++ = BUILTIN1 (tanhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__tanieee128\M} } }  */
+  *p++ = BUILTIN1 (tanl, *q++);
+
+  /* { dg-final { scan-assembler {\m__tgammaieee128\M} } }  */
+  *p++ = BUILTIN1 (tgammal, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1\M} } }  */
+  *p++ = BUILTIN1 (truncl, *q++);
+
+  /* { dg-final { scan-assembler {\m__y0ieee128\M} } }  */
+  *p++ = BUILTIN1 (y0l, *q++);
+
+  /* { dg-final { scan-assembler {\m__y1ieee128\M} } }  */
+  *p   = BUILTIN1 (y1l, *q);  
+
+}
+
+/* Built-in functions that returns a long double and take two long double
+   arguments.  */
+
+void
+return_ld_arg_ld_ld (long double *p,
+		     long double *q,
+		     long double *r)
+{
+  /* { dg-final { scan-assembler {\m__atan2ieee128\M} } }  */
+  *p++ = BUILTIN2 (atan2l, *q++, *r++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxscpsgnqp\M} } }  */
+  *p++ = BUILTIN2 (copysignl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__remainderieee128\M} } }  */
+  *p++ = BUILTIN2 (dreml, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__fdimieee128\M} } }  */
+  *p++ = BUILTIN2 (fdiml, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__fmaxieee128\M} } }  */
+  *p++ = BUILTIN2 (fmaxl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__fminieee128\M} } }  */
+  *p++ = BUILTIN2 (fminl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__fmodieee128\M} } }  */
+  *p++ = BUILTIN2 (fmodl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__hypotieee128\M} } }  */
+  *p++ = BUILTIN2 (hypotl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__nextafterieee128\M} } }  */
+  *p++ = BUILTIN2 (nextafterl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__nexttowardieee128\M} } }  */
+  *p++ = BUILTIN2 (nexttowardl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__powieee128\M} } }  */
+  *p++ = BUILTIN2 (powl, *q++, *r++);
+
+  /* remainderf128 mentioned previously.  */
+  *p++ = BUILTIN2 (remainderl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
+  *p   = BUILTIN2 (scalbl, *q, *r);  
+}
+
+/* Built-in function that returns a long double and take three long double
+   arguments.  */
+
+void
+return_ld_arg_ld_ld_ld (long double *p,
+			long double *q,
+			long double *r,
+			long double *s)
+{
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsmaddqp\M} } }  */
+  *p = BUILTIN3 (fmal, *q, *r, *s);
+}
+
+/* Built-in functions that returns a long double and take one
+   _Complex long double argument.  */
+
+void
+return_ld_arg_cld (long double *p,
+		   _Complex long double *q)
+{
+  /* { dg-final { scan-assembler {\m__cabsieee128\M} } }  */
+  *p++ = BUILTIN1 (cabsl, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (cargl, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (cimagl, *q++);
+
+  /* inline code.  */
+  *p   = BUILTIN1 (creall, *q);  
+}
+
+/* Built-in functions that returns a _Complex long double and takes one
+   _Complex long double argument.  */
+
+void
+return_cld_arg_cld (_Complex long double *p,
+		    _Complex long double *q)
+{
+  /* { dg-final { scan-assembler {\m__cacoshieee128\M} } }  */
+  *p++ = BUILTIN1 (cacoshl, *q++);
+
+  /* { dg-final { scan-assembler {\m__cacosieee128\M} } }  */
+  *p++ = BUILTIN1 (cacosl, *q++);
+
+  /* { dg-final { scan-assembler {\m__casinhieee128\M} } }  */
+  *p++ = BUILTIN1 (casinhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__casinieee128\M} } }  */
+  *p++ = BUILTIN1 (casinl, *q++);
+
+  /* { dg-final { scan-assembler {\m__catanhieee128\M} } }  */
+  *p++ = BUILTIN1 (catanhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__catanieee128\M} } }  */
+  *p++ = BUILTIN1 (catanl, *q++);
+
+  /* { dg-final { scan-assembler {\m__ccoshieee128\M} } }  */
+  *p++ = BUILTIN1 (ccoshl, *q++);
+
+  /* { dg-final { scan-assembler {\m__ccosieee128\M} } }  */
+  *p++ = BUILTIN1 (ccosl, *q++);
+
+  /* { dg-final { scan-assembler {\m__cexpieee128\M} } }  */
+  *p++ = BUILTIN1 (cexpl, *q++);
+
+  /* { dg-final { scan-assembler {\m__clogieee128\M} } }  */
+  *p++ = BUILTIN1 (clogl, *q++);
+
+  /* { dg-final { scan-assembler {\m__clog10ieee128\M} } }  */
+  *p++ = BUILTIN1 (clog10l, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (conjl, *q++);
+
+  /* { dg-final { scan-assembler {\m__cprojieee128\M} } }  */
+  *p++ = BUILTIN1 (cprojl, *q++);
+
+  /* { dg-final { scan-assembler {\m__csinhieee128\M} } }  */
+  *p++ = BUILTIN1 (csinhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__csinieee128\M} } }  */
+  *p++ = BUILTIN1 (csinl, *q++);
+
+  /* { dg-final { scan-assembler {\m__csqrtieee128\M} } }  */
+  *p++ = BUILTIN1 (csqrtl, *q++);
+
+  /* { dg-final { scan-assembler {\m__ctanhieee128\M} } }  */
+  *p++ = BUILTIN1 (ctanhl, *q++);
+
+  /* { dg-final { scan-assembler {\m__ctanieee128\M} } }  */
+  *p   = BUILTIN1 (ctanl, *q);  
+}
+
+/* Built-in functions that returns a _Complex long double and takes one
+   long double argument.  */
+
+void
+return_cld_arg_ld (_Complex long double *p,
+		   long double *q)
+{
+  /* { dg-final { scan-assembler {\m__sincosieee128\M} } }  */
+  *p = BUILTIN1 (cexpil, *q);
+}
+
+/* Built-in function that returns a _Complex long double and takes two
+   _Complex long double arguments.  */
+
+void
+return_cld_arg_cld_cld (_Complex long double *p,
+			_Complex long double *q,
+			_Complex long double *r)
+{
+  /* { dg-final { scan-assembler {\m__cpowieee128\M} } }  */
+  *p = BUILTIN2 (cpowl, *q, *r);
+}
+
+/* Built-in functions that returns a long double and takes a long double and a
+   pointer to an int arguments.  */
+
+void
+return_ld_arg_ld_pi (long double *p,
+		     long double *q,
+		     int **r)
+{
+  /* { dg-final { scan-assembler {\m__frexpieee128\M} } }  */
+  *p++ = BUILTIN2 (frexpl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__lgammaieee128_r\M} } }  */
+  *p++ = BUILTIN2 (gammal_r, *q++, *r++);
+
+  /* __lgammaieee128_r mentioned previously.  */
+  *p   = BUILTIN2 (lgammal_r, *q, *r);  
+}
+
+/* Built-in functions that returns a long double and takes a long double and an
+   int arguments.  */
+
+void
+return_ld_arg_ld_i (long double *p,
+		    long double *q,
+		    int *r)
+{
+  /* { dg-final { scan-assembler {\m__ldexpieee128\M} } }  */
+  *p++ = BUILTIN2 (ldexpl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__powikf2\M} } }  */
+  *p++ = BUILTIN2 (powil, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
+  *p   = BUILTIN2 (scalbnl, *q, *r);  
+}
+
+/* Built-in function that returns a long double and takes a long double and a
+   long arguments.  */
+
+void
+return_ld_arg_ld_l (long double *p,
+		    long double *q,
+		    long *r)
+{
+  /* { dg-final { scan-assembler {\m__scalblnieee128\M} } }  */
+  *p = BUILTIN2 (scalblnl, *q, *r);
+}
+
+/* Built-in functions that returns a long double and takes a long double and a
+   long long arguments.  */
+
+void
+return_ld_arg_i_ld (long double *p,
+		    int *q,
+		    long double *r)
+{
+  /* { dg-final { scan-assembler {\m__jnieee128\M} } }  */
+  *p++ = BUILTIN2 (jnl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__ynieee128\M} } }  */
+  *p   = BUILTIN2 (ynl, *q, *r);  
+}
+
+/* Built-in functions that returns a long double and takes a long double and a
+   pointer to a long double arguments.  */
+
+void
+return_ld_arg_ld_pld (long double *p,
+		      long double *q,
+		      long double **r)
+{
+  /* { dg-final { scan-assembler {\m__modfieee128\M} } }  */
+  *p = BUILTIN2 (modfl, *q, *r);
+}
+
+/* Built-in function that returns a long double and takes two long double and a
+   pointer to an int arguments.  */
+
+void
+return_ld_arg_ld_ld_pi (long double *p,
+			long double *q,
+			long double *r,
+			int **s)
+{
+  /* { dg-final { scan-assembler {\m__remquoieee128\M} } }  */
+  *p = BUILTIN3 (remquol, *q, *r, *s);
+}
+
+/* Built-in functions that returns a long double and take no arguments.  */
+
+void
+return_ld_no_arg (long double *p)
+{
+  /* inline code.  */
+  *p++ = BUILTIN0 (huge_vall);
+
+  /* inline code.  */
+  *p   = BUILTIN0 (infl);     
+}
+
+/* Built-in functions that return san int and takes one long double argument.  */
+
+void
+return_i_arg_ld (int *p,
+		 long double *q)
+{
+  /* { dg-final { scan-assembler {\m__ceilieee128\M} } }  */
+  *p++ = BUILTIN1 (iceill, *q++);
+
+  /* { dg-final { scan-assembler {\m__floorieee128\M} } }  */
+  *p++ = BUILTIN1 (ifloorl, *q++);
+
+  /* { dg-final { scan-assembler {\m__ilogbieee128\M} } }  */
+  *p++ = BUILTIN1 (ilogbl, *q++);
+
+  /* { dg-final { scan-assembler {\m__lrintieee128\M} } }  */
+  *p++ = BUILTIN1 (irintl, *q++);
+
+  /* { dg-final { scan-assembler {\m__lroundieee128\M} } }  */
+  *p++ = BUILTIN1 (iroundl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxscvqpswz\M} } }  */
+  *p++ = BUILTIN1 (signbitl, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (finitel, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (isinfl, *q++);
+
+  /* inline code.  */
+  *p   = BUILTIN1 (isnanl, *q);  
+}
+
+/* Built-in functions that returns a long and takes one long double argument.  */
+
+void
+return_l_arg_ld (long *p,
+		 long double *q)
+{
+  /* ceilf128 mentioned previouly.  */
+  *p++ = BUILTIN1 (lceill, *q++);
+
+  /* floorf128 mentioned previously.  */
+  *p++ = BUILTIN1 (lfloorl, *q++);
+
+  /* lrintf128 mentioned previously.  */
+  *p++ = BUILTIN1 (lrintl, *q++);
+
+  /* lroundf128 mentioned previously.  */
+  *p   = BUILTIN1 (lroundl, *q);  
+}
+
+/* Built-in functions that returns a long long and takes one long double
+   argument.  */
+
+void
+return_ll_arg_ld (long long *p,
+		  long double *r)
+{
+  /* ceilf128 mentioned previous.  */
+  *p++ = BUILTIN1 (llceill, *r++);
+
+  /* floorf128 mentioned previously.  */
+  *p++ = BUILTIN1 (llfloorl, *r++);
+
+  /* llrintf128 mentioned previously.  */
+  *p++ = BUILTIN1 (llrintl, *r++);
+
+  /* llroundf128 mentioned previously.  */
+  *p   = BUILTIN1 (llroundl, *r);  
+}
+
+/* Built-in function that returns a double and takes one double and one long
+   double arguments.  */
+
+void
+return_d_arg_d_ld (double *p,
+		   double *q,
+		   long double *r)
+{
+  /* { dg-final { scan-assembler {\m__nexttoward_to_ieee128\M} } }  */
+  *p = BUILTIN2 (nexttoward, *q, *r);
+}
+
+/* Built-in function that returns a float and takes one float and one long
+   double arguments.  */
+
+void
+return_f_arg_f_ld (float *p,
+		   float *q,
+		   long double *r)
+{
+  /* { dg-final { scan-assembler {\m__nexttowardf_to_ieee128\M} } }  */
+  *p = BUILTIN2 (nexttowardf, *q, *r);
+}
+
+/* Built-in function that returns void and takes one long double and two
+   pointers to long double arguments.  */
+
+void
+return_void_arg_ld_pld_pld (long double *p,
+			    long double **q,
+			    long double **r)
+{
+  /* __sincosieee128 mentioned previously.  */
+  BUILTIN3 (sincosl, *p, *q, *r);
+}
+
+/* Debug main program to determine if the library has all of the mapped
+   external functions.  Note, you need a new enough glibc to provide all of the
+   f128 functions.  */
+#ifdef DO_MAIN
+int
+main (void)
+{
+  return 0;
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
new file mode 100644
index 00000000000..570f3e071b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
@@ -0,0 +1,37 @@
+/* { dg-require-effective-target ppc_float128_hw } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */
+
+/* Test if switching long double to IEEE 128-bit maps the printf and scanf
+   function names correctly.  We explicitly turn off PC-relative support to
+   make it simpler to compare the call without having a @notoc qualifier.  */
+
+#include <stdlib.h>
+
+volatile long double x = 1.0L;
+volatile long double y, z;
+
+int
+main (void)
+{
+  char buffer[100];
+
+  /* { dg-final { scan-assembler {\m__sprintfieee128\M} } }  */
+  __builtin_sprintf (buffer, "%Lg", x);
+
+  /* { dg-final { scan-assembler {\m__printfieee128\M} } }  */
+  __builtin_printf ("x is %Lg [%s]\n", x, buffer);
+
+  /* { dg-final { scan-assembler {\m__isoc99_sscanfieee128\M} } }  */
+  __builtin_sscanf (buffer, "%Lg", &y);
+
+  __builtin_printf ("Type 1.0: ");
+
+  /* { dg-final { scan-assembler {\m__isoc99_scanfieee128\M} } }  */
+  __builtin_scanf ("%Lg", &z);
+
+  if (x != y || x != z)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-math.c b/gcc/testsuite/gcc.target/powerpc/float128-math.c
index 4ad3b5b8363..ea5cb43bcf1 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-math.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-math.c
@@ -10,11 +10,11 @@
 
 extern __float128 sinf128 (__float128);
 
-void foo (__float128 *p, long double *q, long double *r)
+void foo (__float128 *p, long double *q)
 {
   *p = sinf128 (*p);
   *q = __builtin_sinl (*q);
 }
 
-/* { dg-final { scan-assembler-times {\mbl sinf128\M} 2 } } */
-/* { dg-final { scan-assembler-not   {\mbl sinl\M}      } } */
+/* { dg-final { scan-assembler     {\mbl __sinieee128\M} } } */
+/* { dg-final { scan-assembler-not {\mbl sinl\M}         } } */
-- 
2.22.0


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

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PowerPC: Map IEEE 128-bit long double built-in functions
  2020-10-22 22:03 PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
@ 2020-10-26 22:48 ` will schmidt
  2020-11-03 22:13 ` Segher Boessenkool
  2020-11-05  0:13 ` Segher Boessenkool
  2 siblings, 0 replies; 5+ messages in thread
From: will schmidt @ 2020-10-26 22:48 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, Segher Boessenkool,
	David Edelsohn, Bill Schmidt, Peter Bergner, Jeff Law,
	Jonathan Wakely

On Thu, 2020-10-22 at 18:03 -0400, Michael Meissner via Gcc-patches wrote:
> PowerPC: Map IEEE 128-bit long double built-in functions
> 
> This patch is revised from the first and second versions of the patch posted.
> It now uses the names that are not in the user's namespace (i.e. __sinieee128
> instead of sinf128) that Joseph Myers suggested.
> 
> In addition, I added the changes suggested by Segher the last time this patch
> was submitted (changing where the default is, fixing the scalbl built-in name,
> using strlen and xaprintf).
> 
> I have split all of these patches into separate patches to hopefully get them
> into the tree.
> 
> This patch goes through the built-in functions and changes the name of the
> math, scanf, and printf built-in functions to use the functions that GLIBC
> provides when long double uses the IEEE 128-bit representation.
> 
> In addition, changing the name in GCC allows the Fortran compiler to
> automatically use the correct name.
> 
> To map the math functions, typically this patch changes <name>l to
> __<name>ieee128.  However there are some exceptions that are handled with this
> patch.
> 
> To map the printf functions, <name> is mapped to __<name>ieee128.
> 
> To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128.
> 
> I have tested this patch with bootstrap builds on a little endian power9 system
> running Linux.  With the other patches, I have built two full bootstrap builds
> using this patch and the patches after this patch.  One build used the current
> default for long double (IBM extended double) and the other build switched the
> default to IEEE 128-bit.  I used the Advance Toolchain AT 14.0 compiler as the
> library used by this compiler.  There are no regressions between the tests.
> There are 3 fortran benchmarks (ieee/large_2.f90, default_format_2.f90, and
> default_format_denormal_2.f90) that now pass.
> 
> Can I install this into the trunk?
> 
> We have gotten some requests to back port these changes to GCC 10.x.  At the
> moment, I am not planning to do the back port, but I may need to in the future.
> 
> gcc/
> 2020-10-22  Michael Meissner  <meissner@linux.ibm.com>
> 
> 	* config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Add
> 	support for mapping built-in function names for long double
> 	built-in functions if long double is IEEE 128-bit.

possibly redundant "built-in functions" in there, but OK. 

> 
> gcc/testsuite/
> 2020-10-22  Michael Meissner  <meissner@linux.ibm.com>
> 
> 	* gcc.target/powerpc/float128-longdouble-math.c: New test.
> 	* gcc.target/powerpc/float128-longdouble-stdio.c: New test.
> 	* gcc.target/powerpc/float128-math.c: Adjust test for new name
> 	being generated.
> ---
>  gcc/config/rs6000/rs6000.c                    | 135 ++++-
>  .../powerpc/float128-longdouble-math.c        | 567 ++++++++++++++++++
>  .../powerpc/float128-longdouble-stdio.c       |  37 ++
>  .../gcc.target/powerpc/float128-math.c        |   6 +-
>  4 files changed, 710 insertions(+), 35 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> 
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index 141684e3157..8c2544ee88d 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -26893,56 +26893,127 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
>     library before you can switch the real*16 type at compile time.
> 
>     We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name.  We
> -   only do this if the default is that long double is IBM extended double, and
> -   the user asked for IEEE 128-bit.  */
> +   only do this transformation if the __float128 type is enabled.  This
> +   prevents us from doing the transformation on older 32-bit ports that might
> +   have enabled using IEEE 128-bit floating point as the default long double
> +   type.  */
> 

ok


>  static tree
>  rs6000_mangle_decl_assembler_name (tree decl, tree id)
>  {
> -  if (!TARGET_IEEEQUAD_DEFAULT && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
> -      && TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl) )
> +  if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
> +      && TREE_CODE (decl) == FUNCTION_DECL
> +      && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
>      {
>        size_t len = IDENTIFIER_LENGTH (id);
>        const char *name = IDENTIFIER_POINTER (id);
> +      char *newname = NULL;
> 
> -      if (name[len - 1] == 'l')
> +      /* See if it is one of the built-in functions with an unusual name.  */
> +      switch (DECL_FUNCTION_CODE (decl))
>  	{
> -	  bool uses_ieee128_p = false;
> -	  tree type = TREE_TYPE (decl);
> -	  machine_mode ret_mode = TYPE_MODE (type);
> +	case BUILT_IN_DREML:
> +	  newname = xstrdup ("__remainderieee128");
> +	  break;
> 
> -	  /* See if the function returns a IEEE 128-bit floating point type or
> -	     complex type.  */
> -	  if (ret_mode == TFmode || ret_mode == TCmode)
> -	    uses_ieee128_p = true;
> -	  else
> -	    {
> -	      function_args_iterator args_iter;
> -	      tree arg;
> +	case BUILT_IN_GAMMAL:
> +	  newname = xstrdup ("__lgammaieee128");
> +	  break;
> +
> +	case BUILT_IN_GAMMAL_R:
> +	case BUILT_IN_LGAMMAL_R:
> +	  newname = xstrdup ("__lgammaieee128_r");
> +	  break;
> +
> +	case BUILT_IN_NEXTTOWARD:
> +	  newname = xstrdup ("__nexttoward_to_ieee128");
> +	  break;
> +
> +	case BUILT_IN_NEXTTOWARDF:
> +	  newname = xstrdup ("__nexttowardf_to_ieee128");
> +	  break;
> +
> +	case BUILT_IN_NEXTTOWARDL:
> +	  newname = xstrdup ("__nexttowardieee128");
> +	  break;
> +
> +	case BUILT_IN_POW10L:
> +	  newname = xstrdup ("__exp10ieee128");
> +	  break;
> +
> +	case BUILT_IN_SCALBL:
> +	  newname = xstrdup ("__scalbieee128");
> +	  break;
> +
> +	case BUILT_IN_SIGNIFICANDL:
> +	  newname = xstrdup ("__significandieee128");
> +	  break;
> +
> +	case BUILT_IN_SINCOSL:
> +	  newname = xstrdup ("__sincosieee128");
> +	  break;
> 
> -	      /* See if the function passes a IEEE 128-bit floating point type
> -		 or complex type.  */
> -	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
> +	default:
> +	  break;
> +	}
> +
> +      /* Update the __builtin_*printf && __builtin_*scanf functions.  */

Given your patch description:
	To map the printf functions, <name> is mapped to
	__<name>ieee128.>  To map the scanf functions, <name> is
	 mapped to __isoc99_<name>ieee128.

It may be worthwhile to update that comment to STL 
	/* Map the __builtin_*printf and __builtin_*scanf functions
	to their __<>ieee128 and __isoc99_<>ieee128 counterparts.  */


> +      if (!newname)
> +	{
> +	  size_t printf_len = strlen ("printf");
> +	  size_t scanf_len = strlen ("scanf");
> +
> +	  if (len >= printf_len
> +	      && strcmp (name + len - printf_len, "printf") == 0)
> +	    newname = xasprintf ("__%sieee128", name);
> +
> +	  else if (len >= scanf_len
> +		   && strcmp (name + len - scanf_len, "scanf") == 0)
> +	    newname = xasprintf ("__isoc99_%sieee128", name);


Ok, i think.  The len >= scanf_len check there gives me pause, but I
expect those are there to help protect the strcmp() from badness, so
OK. 


> +
> +	  else if (name[len - 1] == 'l')
> +	    {
> +	      bool uses_ieee128_p = false;
> +	      tree type = TREE_TYPE (decl);
> +	      machine_mode ret_mode = TYPE_MODE (type);
> +
> +	      /* See if the function returns a IEEE 128-bit floating point type or
> +		 complex type.  */
> +	      if (ret_mode == TFmode || ret_mode == TCmode)
> +		uses_ieee128_p = true;
> +	      else
>  		{
> -		  machine_mode arg_mode = TYPE_MODE (arg);
> -		  if (arg_mode == TFmode || arg_mode == TCmode)
> +		  function_args_iterator args_iter;
> +		  tree arg;
> +
> +		  /* See if the function passes a IEEE 128-bit floating point type
> +		     or complex type.  */
> +		  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
>  		    {
> -		      uses_ieee128_p = true;
> -		      break;
> +		      machine_mode arg_mode = TYPE_MODE (arg);
> +		      if (arg_mode == TFmode || arg_mode == TCmode)
> +			{
> +			  uses_ieee128_p = true;
> +			  break;
> +			}

ok

>  		    }
>  		}
> -	    }
> 
> -	  /* If we passed or returned an IEEE 128-bit floating point type,
> -	     change the name.  */
> -	  if (uses_ieee128_p)
> -	    {
> -	      char *name2 = (char *) alloca (len + 4);
> -	      memcpy (name2, name, len - 1);
> -	      strcpy (name2 + len - 1, "f128");
> -	      id = get_identifier (name2);
> +	      /* If we passed or returned an IEEE 128-bit floating point type,
> +		 change the name.  Use __<name>ieee128, instead of <name>l.  */
> +	      if (uses_ieee128_p)
> +		newname = xasprintf ("__%.*sieee128", (int)(len - 1), name);

ok

>  	    }
>  	}
> +
> +      if (newname)
> +	{
> +	  if (TARGET_DEBUG_BUILTIN)
> +	    fprintf (stderr, "Map %s => %s\n", name, newname);
> +
> +	  id = get_identifier (newname);
> +	  free (newname);
> +	}
>      }
> 
>    return id;

ok


> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> new file mode 100644
> index 00000000000..50d40180fdc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> @@ -0,0 +1,567 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */
> +
> +/* Test if switching long double to IEEE 128-bit maps all of the math built-in
> +   function names correctly.  We explicitly turn off PC-relative support to
> +   make it simpler to compare the call without having a @notoc qualifier.  */
> +
> +/* Debugging support to use 'name' instead of '__builtin_name'.  Note if you
> +   enable this, you will likely need additional flags to get all of the
> +   functions defined.  */
> +#ifdef DO_FUNC
> +#ifndef DO_MATH_H
> +#define DO_MATH_H	1
> +#endif
> +
> +#define BUILTIN0(FUNC)                   FUNC ()
> +#define BUILTIN1(FUNC, ARG1)             FUNC (ARG1)
> +#define BUILTIN2(FUNC, ARG1, ARG2)       FUNC (ARG1, ARG2)
> +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) FUNC (ARG1, ARG2, ARG3)
> +
> +#else
> +#define BUILTIN0(FUNC)                   __builtin_ ## FUNC ()
> +#define BUILTIN1(FUNC, ARG1)             __builtin_ ## FUNC (ARG1)
> +#define BUILTIN2(FUNC, ARG1, ARG2)       __builtin_ ## FUNC (ARG1, ARG2)
> +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) __builtin_ ## FUNC (ARG1, ARG2, ARG3)
> +#endif
> +
> +/* Debugging support to compare using math.h with the raw built-in functions.  */
> +#ifdef DO_MATH_H
> +#define __STDC_WANT_IEC_60559_TYPES_EXT__	1
> +#define __STDC_WANT_IEC_60559_FUNCS_EXT__	1
> +#define _GNU_SOURCE				1
> +#define _XOPEN_SOURCE				1
> +
> +#include <math.h>
> +#include <complex.h>
> +#endif
> +
> +/* Built-in functions that returns a long double and take one long double
> +   argument.  */
> +
> +void
> +return_ld_arg_ld (long double *p,
> +		  long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__acoshieee128\M} } }  */
> +  *p++ = BUILTIN1 (acoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__acosieee128\M} } }  */
> +  *p++ = BUILTIN1 (acosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__asinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (asinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__asinieee128\M} } }  */
> +  *p++ = BUILTIN1 (asinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__atanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (atanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__atanieee128\M} } }  */
> +  *p++ = BUILTIN1 (atanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cbrtieee128\M} } }  */
> +  *p++ = BUILTIN1 (cbrtl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2\M} } }  */
> +  *p++ = BUILTIN1 (ceill, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__coshieee128\M} } }  */
> +  *p++ = BUILTIN1 (coshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cosieee128\M} } }  */
> +  *p++ = BUILTIN1 (cosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__erfcieee128\M} } }  */
> +  *p++ = BUILTIN1 (erfcl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__erfieee128\M} } }  */
> +  *p++ = BUILTIN1 (erfl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__exp10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (exp10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__exp2ieee128\M} } }  */
> +  *p++ = BUILTIN1 (exp2l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__expieee128\M} } }  */
> +  *p++ = BUILTIN1 (expl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__expm1ieee128\M} } }  */
> +  *p++ = BUILTIN1 (expm1l, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsabsqp\M} } }  */
> +  *p++ = BUILTIN1 (fabsl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3\M} } }  */
> +  *p++ = BUILTIN1 (floorl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__lgammaieee128\M} } }  */
> +  *p++ = BUILTIN1 (gammal, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__j0ieee128\M} } }  */
> +  *p++ = BUILTIN1 (j0l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__j1ieee128\M} } }  */
> +  *p++ = BUILTIN1 (j1l, *q++);
> +
> +  /* lgammaf128 mentioned previously.  */

Good comment.  A few more spaces below where something similar may be
helpful.
Was/is this one the lgammaieee128 reference 9 lines up?


> +  *p++ = BUILTIN1 (lgammal, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__log10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (log10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__log1pieee128\M} } }  */
> +  *p++ = BUILTIN1 (log1pl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__log2ieee128\M} } }  */
> +  *p++ = BUILTIN1 (log2l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__logbieee128\M} } }  */
> +  *p++ = BUILTIN1 (logbl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__logieee128\M} } }  */
> +  *p++ = BUILTIN1 (logl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__nearbyintieee128\M} } }  */
> +  *p++ = BUILTIN1 (nearbyintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__exp10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (pow10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__rintieee128\M} } }  */
> +  *p++ = BUILTIN1 (rintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__roundevenieee128\M} } }  */
> +  *p++ = BUILTIN1 (roundevenl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,0\M} } }  */
> +  *p++ = BUILTIN1 (roundl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__significandieee128\M} } }  */
> +  *p++ = BUILTIN1 (significandl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__sinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (sinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__sinieee128\M} } }  */
> +  *p++ = BUILTIN1 (sinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__sqrtieee128\M} } }  */
> +  *p++ = BUILTIN1 (sqrtl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__tanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (tanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__tanieee128\M} } }  */
> +  *p++ = BUILTIN1 (tanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__tgammaieee128\M} } }  */
> +  *p++ = BUILTIN1 (tgammal, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1\M} } }  */
> +  *p++ = BUILTIN1 (truncl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__y0ieee128\M} } }  */
> +  *p++ = BUILTIN1 (y0l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__y1ieee128\M} } }  */
> +  *p   = BUILTIN1 (y1l, *q);  
> +
> +}
> +
> +/* Built-in functions that returns a long double and take two long double
> +   arguments.  */
> +
> +void
> +return_ld_arg_ld_ld (long double *p,
> +		     long double *q,
> +		     long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__atan2ieee128\M} } }  */
> +  *p++ = BUILTIN2 (atan2l, *q++, *r++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxscpsgnqp\M} } }  */
> +  *p++ = BUILTIN2 (copysignl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__remainderieee128\M} } }  */
> +  *p++ = BUILTIN2 (dreml, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fdimieee128\M} } }  */
> +  *p++ = BUILTIN2 (fdiml, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fmaxieee128\M} } }  */
> +  *p++ = BUILTIN2 (fmaxl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fminieee128\M} } }  */
> +  *p++ = BUILTIN2 (fminl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fmodieee128\M} } }  */
> +  *p++ = BUILTIN2 (fmodl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__hypotieee128\M} } }  */
> +  *p++ = BUILTIN2 (hypotl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__nextafterieee128\M} } }  */
> +  *p++ = BUILTIN2 (nextafterl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__nexttowardieee128\M} } }  */
> +  *p++ = BUILTIN2 (nexttowardl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__powieee128\M} } }  */
> +  *p++ = BUILTIN2 (powl, *q++, *r++);
> +
> +  /* remainderf128 mentioned previously.  */
> +  *p++ = BUILTIN2 (remainderl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
> +  *p   = BUILTIN2 (scalbl, *q, *r);  
> +}
> +
> +/* Built-in function that returns a long double and take three long double
> +   arguments.  */
> +
> +void
> +return_ld_arg_ld_ld_ld (long double *p,
> +			long double *q,
> +			long double *r,
> +			long double *s)
> +{
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsmaddqp\M} } }  */
> +  *p = BUILTIN3 (fmal, *q, *r, *s);
> +}
> +
> +/* Built-in functions that returns a long double and take one
> +   _Complex long double argument.  */
> +
> +void
> +return_ld_arg_cld (long double *p,
> +		   _Complex long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__cabsieee128\M} } }  */
> +  *p++ = BUILTIN1 (cabsl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (cargl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (cimagl, *q++);
> +
> +  /* inline code.  */
> +  *p   = BUILTIN1 (creall, *q);  

These three already handled?


> +}
> +
> +/* Built-in functions that returns a _Complex long double and takes one
> +   _Complex long double argument.  */
> +
> +void
> +return_cld_arg_cld (_Complex long double *p,
> +		    _Complex long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__cacoshieee128\M} } }  */
> +  *p++ = BUILTIN1 (cacoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cacosieee128\M} } }  */
> +  *p++ = BUILTIN1 (cacosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__casinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (casinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__casinieee128\M} } }  */
> +  *p++ = BUILTIN1 (casinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__catanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (catanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__catanieee128\M} } }  */
> +  *p++ = BUILTIN1 (catanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ccoshieee128\M} } }  */
> +  *p++ = BUILTIN1 (ccoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ccosieee128\M} } }  */
> +  *p++ = BUILTIN1 (ccosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cexpieee128\M} } }  */
> +  *p++ = BUILTIN1 (cexpl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__clogieee128\M} } }  */
> +  *p++ = BUILTIN1 (clogl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__clog10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (clog10l, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (conjl, *q++);

And this one? 

> +
> +  /* { dg-final { scan-assembler {\m__cprojieee128\M} } }  */
> +  *p++ = BUILTIN1 (cprojl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__csinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (csinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__csinieee128\M} } }  */
> +  *p++ = BUILTIN1 (csinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__csqrtieee128\M} } }  */
> +  *p++ = BUILTIN1 (csqrtl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ctanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (ctanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ctanieee128\M} } }  */
> +  *p   = BUILTIN1 (ctanl, *q);  
> +}
> +
> +/* Built-in functions that returns a _Complex long double and takes one
> +   long double argument.  */
> +
> +void
> +return_cld_arg_ld (_Complex long double *p,
> +		   long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__sincosieee128\M} } }  */
> +  *p = BUILTIN1 (cexpil, *q);
> +}
> +
> +/* Built-in function that returns a _Complex long double and takes two
> +   _Complex long double arguments.  */
> +
> +void
> +return_cld_arg_cld_cld (_Complex long double *p,
> +			_Complex long double *q,
> +			_Complex long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__cpowieee128\M} } }  */
> +  *p = BUILTIN2 (cpowl, *q, *r);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   pointer to an int arguments.  */
> +
> +void
> +return_ld_arg_ld_pi (long double *p,
> +		     long double *q,
> +		     int **r)
> +{
> +  /* { dg-final { scan-assembler {\m__frexpieee128\M} } }  */
> +  *p++ = BUILTIN2 (frexpl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__lgammaieee128_r\M} } }  */
> +  *p++ = BUILTIN2 (gammal_r, *q++, *r++);
> +
> +  /* __lgammaieee128_r mentioned previously.  */
> +  *p   = BUILTIN2 (lgammal_r, *q, *r);  
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and an
> +   int arguments.  */
> +
> +void
> +return_ld_arg_ld_i (long double *p,
> +		    long double *q,
> +		    int *r)
> +{
> +  /* { dg-final { scan-assembler {\m__ldexpieee128\M} } }  */
> +  *p++ = BUILTIN2 (ldexpl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__powikf2\M} } }  */
> +  *p++ = BUILTIN2 (powil, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
> +  *p   = BUILTIN2 (scalbnl, *q, *r);  
> +}
> +
> +/* Built-in function that returns a long double and takes a long double and a
> +   long arguments.  */
> +
> +void
> +return_ld_arg_ld_l (long double *p,
> +		    long double *q,
> +		    long *r)
> +{
> +  /* { dg-final { scan-assembler {\m__scalblnieee128\M} } }  */
> +  *p = BUILTIN2 (scalblnl, *q, *r);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   long long arguments.  */
> +
> +void
> +return_ld_arg_i_ld (long double *p,
> +		    int *q,
> +		    long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__jnieee128\M} } }  */
> +  *p++ = BUILTIN2 (jnl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__ynieee128\M} } }  */
> +  *p   = BUILTIN2 (ynl, *q, *r);  
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   pointer to a long double arguments.  */
> +
> +void
> +return_ld_arg_ld_pld (long double *p,
> +		      long double *q,
> +		      long double **r)
> +{
> +  /* { dg-final { scan-assembler {\m__modfieee128\M} } }  */
> +  *p = BUILTIN2 (modfl, *q, *r);
> +}
> +
> +/* Built-in function that returns a long double and takes two long double and a
> +   pointer to an int arguments.  */
> +
> +void
> +return_ld_arg_ld_ld_pi (long double *p,
> +			long double *q,
> +			long double *r,
> +			int **s)
> +{
> +  /* { dg-final { scan-assembler {\m__remquoieee128\M} } }  */
> +  *p = BUILTIN3 (remquol, *q, *r, *s);
> +}
> +
> +/* Built-in functions that returns a long double and take no arguments.  */
> +
> +void
> +return_ld_no_arg (long double *p)
> +{
> +  /* inline code.  */
> +  *p++ = BUILTIN0 (huge_vall);
> +
> +  /* inline code.  */
> +  *p   = BUILTIN0 (infl);     
> +}
> +
> +/* Built-in functions that return san int and takes one long double argument.  */
> +
> +void
> +return_i_arg_ld (int *p,
> +		 long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__ceilieee128\M} } }  */
> +  *p++ = BUILTIN1 (iceill, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__floorieee128\M} } }  */
> +  *p++ = BUILTIN1 (ifloorl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ilogbieee128\M} } }  */
> +  *p++ = BUILTIN1 (ilogbl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__lrintieee128\M} } }  */
> +  *p++ = BUILTIN1 (irintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__lroundieee128\M} } }  */
> +  *p++ = BUILTIN1 (iroundl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxscvqpswz\M} } }  */
> +  *p++ = BUILTIN1 (signbitl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (finitel, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (isinfl, *q++);
> +
> +  /* inline code.  */
> +  *p   = BUILTIN1 (isnanl, *q);  
> +}
> +
> +/* Built-in functions that returns a long and takes one long double argument.  */
> +
> +void
> +return_l_arg_ld (long *p,
> +		 long double *q)
> +{
> +  /* ceilf128 mentioned previouly.  */
> +  *p++ = BUILTIN1 (lceill, *q++);
> +
> +  /* floorf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (lfloorl, *q++);
> +
> +  /* lrintf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (lrintl, *q++);
> +
> +  /* lroundf128 mentioned previously.  */
> +  *p   = BUILTIN1 (lroundl, *q);  
> +}
> +
> +/* Built-in functions that returns a long long and takes one long double
> +   argument.  */
> +
> +void
> +return_ll_arg_ld (long long *p,
> +		  long double *r)
> +{
> +  /* ceilf128 mentioned previous.  */
> +  *p++ = BUILTIN1 (llceill, *r++);
> +
> +  /* floorf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (llfloorl, *r++);
> +
> +  /* llrintf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (llrintl, *r++);
> +
> +  /* llroundf128 mentioned previously.  */
> +  *p   = BUILTIN1 (llroundl, *r);  
> +}
> +
> +/* Built-in function that returns a double and takes one double and one long
> +   double arguments.  */
> +
> +void
> +return_d_arg_d_ld (double *p,
> +		   double *q,
> +		   long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__nexttoward_to_ieee128\M} } }  */
> +  *p = BUILTIN2 (nexttoward, *q, *r);
> +}
> +
> +/* Built-in function that returns a float and takes one float and one long
> +   double arguments.  */
> +
> +void
> +return_f_arg_f_ld (float *p,
> +		   float *q,
> +		   long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__nexttowardf_to_ieee128\M} } }  */
> +  *p = BUILTIN2 (nexttowardf, *q, *r);
> +}
> +
> +/* Built-in function that returns void and takes one long double and two
> +   pointers to long double arguments.  */
> +
> +void
> +return_void_arg_ld_pld_pld (long double *p,
> +			    long double **q,
> +			    long double **r)
> +{
> +  /* __sincosieee128 mentioned previously.  */
> +  BUILTIN3 (sincosl, *p, *q, *r);
> +}
> +
> +/* Debug main program to determine if the library has all of the mapped
> +   external functions.  Note, you need a new enough glibc to provide all of the
> +   f128 functions.  */
> +#ifdef DO_MAIN

I don't see any obvious hook for setting DO_MAIN under a debug flag. 
(Which is fine, just a nit and to indicate I've read this far.. )

> +int
> +main (void)
> +{
> +  return 0;
> +}
> +#endif
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> new file mode 100644
> index 00000000000..570f3e071b9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> @@ -0,0 +1,37 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */
> +
> +/* Test if switching long double to IEEE 128-bit maps the printf and scanf
> +   function names correctly.  We explicitly turn off PC-relative support to
> +   make it simpler to compare the call without having a @notoc qualifier.  */
> +
> +#include <stdlib.h>
> +
> +volatile long double x = 1.0L;
> +volatile long double y, z;
> +
> +int
> +main (void)
> +{
> +  char buffer[100];
> +
> +  /* { dg-final { scan-assembler {\m__sprintfieee128\M} } }  */
> +  __builtin_sprintf (buffer, "%Lg", x);
> +
> +  /* { dg-final { scan-assembler {\m__printfieee128\M} } }  */
> +  __builtin_printf ("x is %Lg [%s]\n", x, buffer);
> +
> +  /* { dg-final { scan-assembler {\m__isoc99_sscanfieee128\M} } }  */
> +  __builtin_sscanf (buffer, "%Lg", &y);
> +
> +  __builtin_printf ("Type 1.0: ");

Does "Type 1.0" have meaning?

> +
> +  /* { dg-final { scan-assembler {\m__isoc99_scanfieee128\M} } }  */
> +  __builtin_scanf ("%Lg", &z);
> +
> +  if (x != y || x != z)
> +    abort ();
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-math.c b/gcc/testsuite/gcc.target/powerpc/float128-math.c
> index 4ad3b5b8363..ea5cb43bcf1 100644
> --- a/gcc/testsuite/gcc.target/powerpc/float128-math.c
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-math.c
> @@ -10,11 +10,11 @@
> 
>  extern __float128 sinf128 (__float128);
> 
> -void foo (__float128 *p, long double *q, long double *r)
> +void foo (__float128 *p, long double *q)
>  {
>    *p = sinf128 (*p);
>    *q = __builtin_sinl (*q);
>  }
> 
> -/* { dg-final { scan-assembler-times {\mbl sinf128\M} 2 } } */
> -/* { dg-final { scan-assembler-not   {\mbl sinl\M}      } } */
> +/* { dg-final { scan-assembler     {\mbl __sinieee128\M} } } */
> +/* { dg-final { scan-assembler-not {\mbl sinl\M}         } } */
> -- 
> 2.22.0
> 

no functional issues jumped out..  lgtm, 
thanks
-Will

> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PowerPC: Map IEEE 128-bit long double built-in functions
  2020-10-22 22:03 PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
  2020-10-26 22:48 ` will schmidt
@ 2020-11-03 22:13 ` Segher Boessenkool
  2020-11-05  0:13 ` Segher Boessenkool
  2 siblings, 0 replies; 5+ messages in thread
From: Segher Boessenkool @ 2020-11-03 22:13 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, David Edelsohn, Bill Schmidt,
	Peter Bergner, Jeff Law, Jonathan Wakely

I'll ping it myself then!


Segher


On Thu, Oct 22, 2020 at 06:03:46PM -0400, Michael Meissner wrote:
> PowerPC: Map IEEE 128-bit long double built-in functions
> 
> This patch is revised from the first and second versions of the patch posted.
> It now uses the names that are not in the user's namespace (i.e. __sinieee128
> instead of sinf128) that Joseph Myers suggested.
> 
> In addition, I added the changes suggested by Segher the last time this patch
> was submitted (changing where the default is, fixing the scalbl built-in name,
> using strlen and xaprintf).
> 
> I have split all of these patches into separate patches to hopefully get them
> into the tree.
> 
> This patch goes through the built-in functions and changes the name of the
> math, scanf, and printf built-in functions to use the functions that GLIBC
> provides when long double uses the IEEE 128-bit representation.
> 
> In addition, changing the name in GCC allows the Fortran compiler to
> automatically use the correct name.
> 
> To map the math functions, typically this patch changes <name>l to
> __<name>ieee128.  However there are some exceptions that are handled with this
> patch.
> 
> To map the printf functions, <name> is mapped to __<name>ieee128.
> 
> To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128.
> 
> I have tested this patch with bootstrap builds on a little endian power9 system
> running Linux.  With the other patches, I have built two full bootstrap builds
> using this patch and the patches after this patch.  One build used the current
> default for long double (IBM extended double) and the other build switched the
> default to IEEE 128-bit.  I used the Advance Toolchain AT 14.0 compiler as the
> library used by this compiler.  There are no regressions between the tests.
> There are 3 fortran benchmarks (ieee/large_2.f90, default_format_2.f90, and
> default_format_denormal_2.f90) that now pass.
> 
> Can I install this into the trunk?
> 
> We have gotten some requests to back port these changes to GCC 10.x.  At the
> moment, I am not planning to do the back port, but I may need to in the future.
> 
> gcc/
> 2020-10-22  Michael Meissner  <meissner@linux.ibm.com>
> 
> 	* config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Add
> 	support for mapping built-in function names for long double
> 	built-in functions if long double is IEEE 128-bit.
> 
> gcc/testsuite/
> 2020-10-22  Michael Meissner  <meissner@linux.ibm.com>
> 
> 	* gcc.target/powerpc/float128-longdouble-math.c: New test.
> 	* gcc.target/powerpc/float128-longdouble-stdio.c: New test.
> 	* gcc.target/powerpc/float128-math.c: Adjust test for new name
> 	being generated.
> ---
>  gcc/config/rs6000/rs6000.c                    | 135 ++++-
>  .../powerpc/float128-longdouble-math.c        | 567 ++++++++++++++++++
>  .../powerpc/float128-longdouble-stdio.c       |  37 ++
>  .../gcc.target/powerpc/float128-math.c        |   6 +-
>  4 files changed, 710 insertions(+), 35 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> 
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index 141684e3157..8c2544ee88d 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -26893,56 +26893,127 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
>     library before you can switch the real*16 type at compile time.
>  
>     We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name.  We
> -   only do this if the default is that long double is IBM extended double, and
> -   the user asked for IEEE 128-bit.  */
> +   only do this transformation if the __float128 type is enabled.  This
> +   prevents us from doing the transformation on older 32-bit ports that might
> +   have enabled using IEEE 128-bit floating point as the default long double
> +   type.  */
>  
>  static tree
>  rs6000_mangle_decl_assembler_name (tree decl, tree id)
>  {
> -  if (!TARGET_IEEEQUAD_DEFAULT && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
> -      && TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl) )
> +  if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
> +      && TREE_CODE (decl) == FUNCTION_DECL
> +      && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
>      {
>        size_t len = IDENTIFIER_LENGTH (id);
>        const char *name = IDENTIFIER_POINTER (id);
> +      char *newname = NULL;
>  
> -      if (name[len - 1] == 'l')
> +      /* See if it is one of the built-in functions with an unusual name.  */
> +      switch (DECL_FUNCTION_CODE (decl))
>  	{
> -	  bool uses_ieee128_p = false;
> -	  tree type = TREE_TYPE (decl);
> -	  machine_mode ret_mode = TYPE_MODE (type);
> +	case BUILT_IN_DREML:
> +	  newname = xstrdup ("__remainderieee128");
> +	  break;
>  
> -	  /* See if the function returns a IEEE 128-bit floating point type or
> -	     complex type.  */
> -	  if (ret_mode == TFmode || ret_mode == TCmode)
> -	    uses_ieee128_p = true;
> -	  else
> -	    {
> -	      function_args_iterator args_iter;
> -	      tree arg;
> +	case BUILT_IN_GAMMAL:
> +	  newname = xstrdup ("__lgammaieee128");
> +	  break;
> +
> +	case BUILT_IN_GAMMAL_R:
> +	case BUILT_IN_LGAMMAL_R:
> +	  newname = xstrdup ("__lgammaieee128_r");
> +	  break;
> +
> +	case BUILT_IN_NEXTTOWARD:
> +	  newname = xstrdup ("__nexttoward_to_ieee128");
> +	  break;
> +
> +	case BUILT_IN_NEXTTOWARDF:
> +	  newname = xstrdup ("__nexttowardf_to_ieee128");
> +	  break;
> +
> +	case BUILT_IN_NEXTTOWARDL:
> +	  newname = xstrdup ("__nexttowardieee128");
> +	  break;
> +
> +	case BUILT_IN_POW10L:
> +	  newname = xstrdup ("__exp10ieee128");
> +	  break;
> +
> +	case BUILT_IN_SCALBL:
> +	  newname = xstrdup ("__scalbieee128");
> +	  break;
> +
> +	case BUILT_IN_SIGNIFICANDL:
> +	  newname = xstrdup ("__significandieee128");
> +	  break;
> +
> +	case BUILT_IN_SINCOSL:
> +	  newname = xstrdup ("__sincosieee128");
> +	  break;
>  
> -	      /* See if the function passes a IEEE 128-bit floating point type
> -		 or complex type.  */
> -	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
> +	default:
> +	  break;
> +	}
> +
> +      /* Update the __builtin_*printf && __builtin_*scanf functions.  */
> +      if (!newname)
> +	{
> +	  size_t printf_len = strlen ("printf");
> +	  size_t scanf_len = strlen ("scanf");
> +
> +	  if (len >= printf_len
> +	      && strcmp (name + len - printf_len, "printf") == 0)
> +	    newname = xasprintf ("__%sieee128", name);
> +
> +	  else if (len >= scanf_len
> +		   && strcmp (name + len - scanf_len, "scanf") == 0)
> +	    newname = xasprintf ("__isoc99_%sieee128", name);
> +
> +	  else if (name[len - 1] == 'l')
> +	    {
> +	      bool uses_ieee128_p = false;
> +	      tree type = TREE_TYPE (decl);
> +	      machine_mode ret_mode = TYPE_MODE (type);
> +
> +	      /* See if the function returns a IEEE 128-bit floating point type or
> +		 complex type.  */
> +	      if (ret_mode == TFmode || ret_mode == TCmode)
> +		uses_ieee128_p = true;
> +	      else
>  		{
> -		  machine_mode arg_mode = TYPE_MODE (arg);
> -		  if (arg_mode == TFmode || arg_mode == TCmode)
> +		  function_args_iterator args_iter;
> +		  tree arg;
> +
> +		  /* See if the function passes a IEEE 128-bit floating point type
> +		     or complex type.  */
> +		  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
>  		    {
> -		      uses_ieee128_p = true;
> -		      break;
> +		      machine_mode arg_mode = TYPE_MODE (arg);
> +		      if (arg_mode == TFmode || arg_mode == TCmode)
> +			{
> +			  uses_ieee128_p = true;
> +			  break;
> +			}
>  		    }
>  		}
> -	    }
>  
> -	  /* If we passed or returned an IEEE 128-bit floating point type,
> -	     change the name.  */
> -	  if (uses_ieee128_p)
> -	    {
> -	      char *name2 = (char *) alloca (len + 4);
> -	      memcpy (name2, name, len - 1);
> -	      strcpy (name2 + len - 1, "f128");
> -	      id = get_identifier (name2);
> +	      /* If we passed or returned an IEEE 128-bit floating point type,
> +		 change the name.  Use __<name>ieee128, instead of <name>l.  */
> +	      if (uses_ieee128_p)
> +		newname = xasprintf ("__%.*sieee128", (int)(len - 1), name);
>  	    }
>  	}
> +
> +      if (newname)
> +	{
> +	  if (TARGET_DEBUG_BUILTIN)
> +	    fprintf (stderr, "Map %s => %s\n", name, newname);
> +
> +	  id = get_identifier (newname);
> +	  free (newname);
> +	}
>      }
>  
>    return id;
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> new file mode 100644
> index 00000000000..50d40180fdc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> @@ -0,0 +1,567 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */
> +
> +/* Test if switching long double to IEEE 128-bit maps all of the math built-in
> +   function names correctly.  We explicitly turn off PC-relative support to
> +   make it simpler to compare the call without having a @notoc qualifier.  */
> +
> +/* Debugging support to use 'name' instead of '__builtin_name'.  Note if you
> +   enable this, you will likely need additional flags to get all of the
> +   functions defined.  */
> +#ifdef DO_FUNC
> +#ifndef DO_MATH_H
> +#define DO_MATH_H	1
> +#endif
> +
> +#define BUILTIN0(FUNC)                   FUNC ()
> +#define BUILTIN1(FUNC, ARG1)             FUNC (ARG1)
> +#define BUILTIN2(FUNC, ARG1, ARG2)       FUNC (ARG1, ARG2)
> +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) FUNC (ARG1, ARG2, ARG3)
> +
> +#else
> +#define BUILTIN0(FUNC)                   __builtin_ ## FUNC ()
> +#define BUILTIN1(FUNC, ARG1)             __builtin_ ## FUNC (ARG1)
> +#define BUILTIN2(FUNC, ARG1, ARG2)       __builtin_ ## FUNC (ARG1, ARG2)
> +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) __builtin_ ## FUNC (ARG1, ARG2, ARG3)
> +#endif
> +
> +/* Debugging support to compare using math.h with the raw built-in functions.  */
> +#ifdef DO_MATH_H
> +#define __STDC_WANT_IEC_60559_TYPES_EXT__	1
> +#define __STDC_WANT_IEC_60559_FUNCS_EXT__	1
> +#define _GNU_SOURCE				1
> +#define _XOPEN_SOURCE				1
> +
> +#include <math.h>
> +#include <complex.h>
> +#endif
> +
> +/* Built-in functions that returns a long double and take one long double
> +   argument.  */
> +
> +void
> +return_ld_arg_ld (long double *p,
> +		  long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__acoshieee128\M} } }  */
> +  *p++ = BUILTIN1 (acoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__acosieee128\M} } }  */
> +  *p++ = BUILTIN1 (acosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__asinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (asinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__asinieee128\M} } }  */
> +  *p++ = BUILTIN1 (asinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__atanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (atanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__atanieee128\M} } }  */
> +  *p++ = BUILTIN1 (atanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cbrtieee128\M} } }  */
> +  *p++ = BUILTIN1 (cbrtl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2\M} } }  */
> +  *p++ = BUILTIN1 (ceill, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__coshieee128\M} } }  */
> +  *p++ = BUILTIN1 (coshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cosieee128\M} } }  */
> +  *p++ = BUILTIN1 (cosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__erfcieee128\M} } }  */
> +  *p++ = BUILTIN1 (erfcl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__erfieee128\M} } }  */
> +  *p++ = BUILTIN1 (erfl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__exp10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (exp10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__exp2ieee128\M} } }  */
> +  *p++ = BUILTIN1 (exp2l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__expieee128\M} } }  */
> +  *p++ = BUILTIN1 (expl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__expm1ieee128\M} } }  */
> +  *p++ = BUILTIN1 (expm1l, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsabsqp\M} } }  */
> +  *p++ = BUILTIN1 (fabsl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3\M} } }  */
> +  *p++ = BUILTIN1 (floorl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__lgammaieee128\M} } }  */
> +  *p++ = BUILTIN1 (gammal, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__j0ieee128\M} } }  */
> +  *p++ = BUILTIN1 (j0l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__j1ieee128\M} } }  */
> +  *p++ = BUILTIN1 (j1l, *q++);
> +
> +  /* lgammaf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (lgammal, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__log10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (log10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__log1pieee128\M} } }  */
> +  *p++ = BUILTIN1 (log1pl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__log2ieee128\M} } }  */
> +  *p++ = BUILTIN1 (log2l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__logbieee128\M} } }  */
> +  *p++ = BUILTIN1 (logbl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__logieee128\M} } }  */
> +  *p++ = BUILTIN1 (logl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__nearbyintieee128\M} } }  */
> +  *p++ = BUILTIN1 (nearbyintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__exp10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (pow10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__rintieee128\M} } }  */
> +  *p++ = BUILTIN1 (rintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__roundevenieee128\M} } }  */
> +  *p++ = BUILTIN1 (roundevenl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,0\M} } }  */
> +  *p++ = BUILTIN1 (roundl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__significandieee128\M} } }  */
> +  *p++ = BUILTIN1 (significandl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__sinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (sinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__sinieee128\M} } }  */
> +  *p++ = BUILTIN1 (sinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__sqrtieee128\M} } }  */
> +  *p++ = BUILTIN1 (sqrtl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__tanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (tanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__tanieee128\M} } }  */
> +  *p++ = BUILTIN1 (tanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__tgammaieee128\M} } }  */
> +  *p++ = BUILTIN1 (tgammal, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1\M} } }  */
> +  *p++ = BUILTIN1 (truncl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__y0ieee128\M} } }  */
> +  *p++ = BUILTIN1 (y0l, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__y1ieee128\M} } }  */
> +  *p   = BUILTIN1 (y1l, *q);  
> +
> +}
> +
> +/* Built-in functions that returns a long double and take two long double
> +   arguments.  */
> +
> +void
> +return_ld_arg_ld_ld (long double *p,
> +		     long double *q,
> +		     long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__atan2ieee128\M} } }  */
> +  *p++ = BUILTIN2 (atan2l, *q++, *r++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxscpsgnqp\M} } }  */
> +  *p++ = BUILTIN2 (copysignl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__remainderieee128\M} } }  */
> +  *p++ = BUILTIN2 (dreml, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fdimieee128\M} } }  */
> +  *p++ = BUILTIN2 (fdiml, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fmaxieee128\M} } }  */
> +  *p++ = BUILTIN2 (fmaxl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fminieee128\M} } }  */
> +  *p++ = BUILTIN2 (fminl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__fmodieee128\M} } }  */
> +  *p++ = BUILTIN2 (fmodl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__hypotieee128\M} } }  */
> +  *p++ = BUILTIN2 (hypotl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__nextafterieee128\M} } }  */
> +  *p++ = BUILTIN2 (nextafterl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__nexttowardieee128\M} } }  */
> +  *p++ = BUILTIN2 (nexttowardl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__powieee128\M} } }  */
> +  *p++ = BUILTIN2 (powl, *q++, *r++);
> +
> +  /* remainderf128 mentioned previously.  */
> +  *p++ = BUILTIN2 (remainderl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
> +  *p   = BUILTIN2 (scalbl, *q, *r);  
> +}
> +
> +/* Built-in function that returns a long double and take three long double
> +   arguments.  */
> +
> +void
> +return_ld_arg_ld_ld_ld (long double *p,
> +			long double *q,
> +			long double *r,
> +			long double *s)
> +{
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsmaddqp\M} } }  */
> +  *p = BUILTIN3 (fmal, *q, *r, *s);
> +}
> +
> +/* Built-in functions that returns a long double and take one
> +   _Complex long double argument.  */
> +
> +void
> +return_ld_arg_cld (long double *p,
> +		   _Complex long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__cabsieee128\M} } }  */
> +  *p++ = BUILTIN1 (cabsl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (cargl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (cimagl, *q++);
> +
> +  /* inline code.  */
> +  *p   = BUILTIN1 (creall, *q);  
> +}
> +
> +/* Built-in functions that returns a _Complex long double and takes one
> +   _Complex long double argument.  */
> +
> +void
> +return_cld_arg_cld (_Complex long double *p,
> +		    _Complex long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__cacoshieee128\M} } }  */
> +  *p++ = BUILTIN1 (cacoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cacosieee128\M} } }  */
> +  *p++ = BUILTIN1 (cacosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__casinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (casinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__casinieee128\M} } }  */
> +  *p++ = BUILTIN1 (casinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__catanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (catanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__catanieee128\M} } }  */
> +  *p++ = BUILTIN1 (catanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ccoshieee128\M} } }  */
> +  *p++ = BUILTIN1 (ccoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ccosieee128\M} } }  */
> +  *p++ = BUILTIN1 (ccosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cexpieee128\M} } }  */
> +  *p++ = BUILTIN1 (cexpl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__clogieee128\M} } }  */
> +  *p++ = BUILTIN1 (clogl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__clog10ieee128\M} } }  */
> +  *p++ = BUILTIN1 (clog10l, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (conjl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__cprojieee128\M} } }  */
> +  *p++ = BUILTIN1 (cprojl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__csinhieee128\M} } }  */
> +  *p++ = BUILTIN1 (csinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__csinieee128\M} } }  */
> +  *p++ = BUILTIN1 (csinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__csqrtieee128\M} } }  */
> +  *p++ = BUILTIN1 (csqrtl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ctanhieee128\M} } }  */
> +  *p++ = BUILTIN1 (ctanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ctanieee128\M} } }  */
> +  *p   = BUILTIN1 (ctanl, *q);  
> +}
> +
> +/* Built-in functions that returns a _Complex long double and takes one
> +   long double argument.  */
> +
> +void
> +return_cld_arg_ld (_Complex long double *p,
> +		   long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__sincosieee128\M} } }  */
> +  *p = BUILTIN1 (cexpil, *q);
> +}
> +
> +/* Built-in function that returns a _Complex long double and takes two
> +   _Complex long double arguments.  */
> +
> +void
> +return_cld_arg_cld_cld (_Complex long double *p,
> +			_Complex long double *q,
> +			_Complex long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__cpowieee128\M} } }  */
> +  *p = BUILTIN2 (cpowl, *q, *r);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   pointer to an int arguments.  */
> +
> +void
> +return_ld_arg_ld_pi (long double *p,
> +		     long double *q,
> +		     int **r)
> +{
> +  /* { dg-final { scan-assembler {\m__frexpieee128\M} } }  */
> +  *p++ = BUILTIN2 (frexpl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__lgammaieee128_r\M} } }  */
> +  *p++ = BUILTIN2 (gammal_r, *q++, *r++);
> +
> +  /* __lgammaieee128_r mentioned previously.  */
> +  *p   = BUILTIN2 (lgammal_r, *q, *r);  
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and an
> +   int arguments.  */
> +
> +void
> +return_ld_arg_ld_i (long double *p,
> +		    long double *q,
> +		    int *r)
> +{
> +  /* { dg-final { scan-assembler {\m__ldexpieee128\M} } }  */
> +  *p++ = BUILTIN2 (ldexpl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__powikf2\M} } }  */
> +  *p++ = BUILTIN2 (powil, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
> +  *p   = BUILTIN2 (scalbnl, *q, *r);  
> +}
> +
> +/* Built-in function that returns a long double and takes a long double and a
> +   long arguments.  */
> +
> +void
> +return_ld_arg_ld_l (long double *p,
> +		    long double *q,
> +		    long *r)
> +{
> +  /* { dg-final { scan-assembler {\m__scalblnieee128\M} } }  */
> +  *p = BUILTIN2 (scalblnl, *q, *r);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   long long arguments.  */
> +
> +void
> +return_ld_arg_i_ld (long double *p,
> +		    int *q,
> +		    long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__jnieee128\M} } }  */
> +  *p++ = BUILTIN2 (jnl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\m__ynieee128\M} } }  */
> +  *p   = BUILTIN2 (ynl, *q, *r);  
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   pointer to a long double arguments.  */
> +
> +void
> +return_ld_arg_ld_pld (long double *p,
> +		      long double *q,
> +		      long double **r)
> +{
> +  /* { dg-final { scan-assembler {\m__modfieee128\M} } }  */
> +  *p = BUILTIN2 (modfl, *q, *r);
> +}
> +
> +/* Built-in function that returns a long double and takes two long double and a
> +   pointer to an int arguments.  */
> +
> +void
> +return_ld_arg_ld_ld_pi (long double *p,
> +			long double *q,
> +			long double *r,
> +			int **s)
> +{
> +  /* { dg-final { scan-assembler {\m__remquoieee128\M} } }  */
> +  *p = BUILTIN3 (remquol, *q, *r, *s);
> +}
> +
> +/* Built-in functions that returns a long double and take no arguments.  */
> +
> +void
> +return_ld_no_arg (long double *p)
> +{
> +  /* inline code.  */
> +  *p++ = BUILTIN0 (huge_vall);
> +
> +  /* inline code.  */
> +  *p   = BUILTIN0 (infl);     
> +}
> +
> +/* Built-in functions that return san int and takes one long double argument.  */
> +
> +void
> +return_i_arg_ld (int *p,
> +		 long double *q)
> +{
> +  /* { dg-final { scan-assembler {\m__ceilieee128\M} } }  */
> +  *p++ = BUILTIN1 (iceill, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__floorieee128\M} } }  */
> +  *p++ = BUILTIN1 (ifloorl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__ilogbieee128\M} } }  */
> +  *p++ = BUILTIN1 (ilogbl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__lrintieee128\M} } }  */
> +  *p++ = BUILTIN1 (irintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\m__lroundieee128\M} } }  */
> +  *p++ = BUILTIN1 (iroundl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxscvqpswz\M} } }  */
> +  *p++ = BUILTIN1 (signbitl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (finitel, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (isinfl, *q++);
> +
> +  /* inline code.  */
> +  *p   = BUILTIN1 (isnanl, *q);  
> +}
> +
> +/* Built-in functions that returns a long and takes one long double argument.  */
> +
> +void
> +return_l_arg_ld (long *p,
> +		 long double *q)
> +{
> +  /* ceilf128 mentioned previouly.  */
> +  *p++ = BUILTIN1 (lceill, *q++);
> +
> +  /* floorf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (lfloorl, *q++);
> +
> +  /* lrintf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (lrintl, *q++);
> +
> +  /* lroundf128 mentioned previously.  */
> +  *p   = BUILTIN1 (lroundl, *q);  
> +}
> +
> +/* Built-in functions that returns a long long and takes one long double
> +   argument.  */
> +
> +void
> +return_ll_arg_ld (long long *p,
> +		  long double *r)
> +{
> +  /* ceilf128 mentioned previous.  */
> +  *p++ = BUILTIN1 (llceill, *r++);
> +
> +  /* floorf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (llfloorl, *r++);
> +
> +  /* llrintf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (llrintl, *r++);
> +
> +  /* llroundf128 mentioned previously.  */
> +  *p   = BUILTIN1 (llroundl, *r);  
> +}
> +
> +/* Built-in function that returns a double and takes one double and one long
> +   double arguments.  */
> +
> +void
> +return_d_arg_d_ld (double *p,
> +		   double *q,
> +		   long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__nexttoward_to_ieee128\M} } }  */
> +  *p = BUILTIN2 (nexttoward, *q, *r);
> +}
> +
> +/* Built-in function that returns a float and takes one float and one long
> +   double arguments.  */
> +
> +void
> +return_f_arg_f_ld (float *p,
> +		   float *q,
> +		   long double *r)
> +{
> +  /* { dg-final { scan-assembler {\m__nexttowardf_to_ieee128\M} } }  */
> +  *p = BUILTIN2 (nexttowardf, *q, *r);
> +}
> +
> +/* Built-in function that returns void and takes one long double and two
> +   pointers to long double arguments.  */
> +
> +void
> +return_void_arg_ld_pld_pld (long double *p,
> +			    long double **q,
> +			    long double **r)
> +{
> +  /* __sincosieee128 mentioned previously.  */
> +  BUILTIN3 (sincosl, *p, *q, *r);
> +}
> +
> +/* Debug main program to determine if the library has all of the mapped
> +   external functions.  Note, you need a new enough glibc to provide all of the
> +   f128 functions.  */
> +#ifdef DO_MAIN
> +int
> +main (void)
> +{
> +  return 0;
> +}
> +#endif
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> new file mode 100644
> index 00000000000..570f3e071b9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> @@ -0,0 +1,37 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */
> +
> +/* Test if switching long double to IEEE 128-bit maps the printf and scanf
> +   function names correctly.  We explicitly turn off PC-relative support to
> +   make it simpler to compare the call without having a @notoc qualifier.  */
> +
> +#include <stdlib.h>
> +
> +volatile long double x = 1.0L;
> +volatile long double y, z;
> +
> +int
> +main (void)
> +{
> +  char buffer[100];
> +
> +  /* { dg-final { scan-assembler {\m__sprintfieee128\M} } }  */
> +  __builtin_sprintf (buffer, "%Lg", x);
> +
> +  /* { dg-final { scan-assembler {\m__printfieee128\M} } }  */
> +  __builtin_printf ("x is %Lg [%s]\n", x, buffer);
> +
> +  /* { dg-final { scan-assembler {\m__isoc99_sscanfieee128\M} } }  */
> +  __builtin_sscanf (buffer, "%Lg", &y);
> +
> +  __builtin_printf ("Type 1.0: ");
> +
> +  /* { dg-final { scan-assembler {\m__isoc99_scanfieee128\M} } }  */
> +  __builtin_scanf ("%Lg", &z);
> +
> +  if (x != y || x != z)
> +    abort ();
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-math.c b/gcc/testsuite/gcc.target/powerpc/float128-math.c
> index 4ad3b5b8363..ea5cb43bcf1 100644
> --- a/gcc/testsuite/gcc.target/powerpc/float128-math.c
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-math.c
> @@ -10,11 +10,11 @@
>  
>  extern __float128 sinf128 (__float128);
>  
> -void foo (__float128 *p, long double *q, long double *r)
> +void foo (__float128 *p, long double *q)
>  {
>    *p = sinf128 (*p);
>    *q = __builtin_sinl (*q);
>  }
>  
> -/* { dg-final { scan-assembler-times {\mbl sinf128\M} 2 } } */
> -/* { dg-final { scan-assembler-not   {\mbl sinl\M}      } } */
> +/* { dg-final { scan-assembler     {\mbl __sinieee128\M} } } */
> +/* { dg-final { scan-assembler-not {\mbl sinl\M}         } } */
> -- 
> 2.22.0
> 
> 
> -- 
> Michael Meissner, IBM
> IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
> email: meissner@linux.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PowerPC: Map IEEE 128-bit long double built-in functions
  2020-10-22 22:03 PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
  2020-10-26 22:48 ` will schmidt
  2020-11-03 22:13 ` Segher Boessenkool
@ 2020-11-05  0:13 ` Segher Boessenkool
  2020-11-05  1:39   ` Michael Meissner
  2 siblings, 1 reply; 5+ messages in thread
From: Segher Boessenkool @ 2020-11-05  0:13 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, David Edelsohn, Bill Schmidt,
	Peter Bergner, Jeff Law, Jonathan Wakely

Hi!

On Thu, Oct 22, 2020 at 06:03:46PM -0400, Michael Meissner wrote:
> To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128.

Is that correct?  What if you are compiling for c90?

> 	* config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Add
> 	support for mapping built-in function names for long double
> 	built-in functions if long double is IEEE 128-bit.

"Map the built-in function names" etc.

> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -26893,56 +26893,127 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
>     library before you can switch the real*16 type at compile time.
>  
>     We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name.  We
> -   only do this if the default is that long double is IBM extended double, and
> -   the user asked for IEEE 128-bit.  */
> +   only do this transformation if the __float128 type is enabled.  This
> +   prevents us from doing the transformation on older 32-bit ports that might
> +   have enabled using IEEE 128-bit floating point as the default long double
> +   type.  */

I don't see why that is the right thing to do?  You'll have exactly
these same problems on 32-bit!

Hrm, we talked about that before I guess?  Do you just need to change
this comment now?

> +	default:
> +	  break;
> +	}

That is useless, just leave it out?  The end of a switch will always
fall through, and it is normal idiom to use that.

> +      /* Update the __builtin_*printf && __builtin_*scanf functions.  */

"and" :-)

> +	  else if (name[len - 1] == 'l')
> +	    {
> +	      bool uses_ieee128_p = false;
> +	      tree type = TREE_TYPE (decl);
> +	      machine_mode ret_mode = TYPE_MODE (type);
> +
> +	      /* See if the function returns a IEEE 128-bit floating point type or
> +		 complex type.  */
> +	      if (ret_mode == TFmode || ret_mode == TCmode)
> +		uses_ieee128_p = true;
> +	      else
>  		{
> -		  machine_mode arg_mode = TYPE_MODE (arg);
> -		  if (arg_mode == TFmode || arg_mode == TCmode)
> +		  function_args_iterator args_iter;
> +		  tree arg;

(declare that right before the FOREACH)

> +
> +		  /* See if the function passes a IEEE 128-bit floating point type
> +		     or complex type.  */
> +		  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
>  		    {
> -		      uses_ieee128_p = true;
> -		      break;
> +		      machine_mode arg_mode = TYPE_MODE (arg);
> +		      if (arg_mode == TFmode || arg_mode == TCmode)
> +			{
> +			  uses_ieee128_p = true;
> +			  break;
> +			}
>  		    }
>  		}

There is no point in doing all these early-outs in an initialisation
function, making it much harder to read :-(

> +	      /* If we passed or returned an IEEE 128-bit floating point type,
> +		 change the name.  Use __<name>ieee128, instead of <name>l.  */
> +	      if (uses_ieee128_p)
> +		newname = xasprintf ("__%.*sieee128", (int)(len - 1), name);

(int) (len - 1)

Please comment what the - 1 does, and/or what this is for at all.  (In
the code / in a comment, not to me, I figured it out after a while.)

> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> @@ -0,0 +1,567 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */

So why do you need power10_ok?  You need power9_ok of course, but why
power10?  You can specify -mno-pcrel always.

> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2\M} } }  */

The " +" should be just a " ".
Not every assembler variant uses plain numbers for registers.  That is
not currently an issue of course, but why not just do it right in the
first place :-)

You can do
  {\mxsrqpi r?[0-9]+,r?[0-9]+,r?[0-9]+,2\M}
or simpler,
  {\mxsrqpi r?\d+,r?\d+,r?\d+,2\M}
or even simpler
  {(?n)\mxsrqpi .*,2\M}
(if you don't mind the number of operands in that last case).

> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3\M} } }  */

(same as above)

> +  /* lgammaf128 mentioned previously.  */
> +  *p++ = BUILTIN1 (lgammal, *q++);

What does that comment mean?  Should you have used scan-assembler-times
perhaps?

> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1\M} } }  */

(one more)

> +  /* remainderf128 mentioned previously.  */
> +  *p++ = BUILTIN2 (remainderl, *q++, *r++);

(similar to the lgammal case)

> +  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
> +  *p   = BUILTIN2 (scalbl, *q, *r);  

(trailing spaces)

> +  /* { dg-final { scan-assembler {\m__cabsieee128\M} } }  */
> +  *p++ = BUILTIN1 (cabsl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (cargl, *q++);
> +
> +  /* inline code.  */
> +  *p++ = BUILTIN1 (cimagl, *q++);
> +
> +  /* inline code.  */
> +  *p   = BUILTIN1 (creall, *q);  

(trailing spaces)

So no checking here at all?  Aww :-)

> +  /* inline code.  */
> +  *p++ = BUILTIN1 (conjl, *q++);

(another)

> +  /* __lgammaieee128_r mentioned previously.  */
> +  *p   = BUILTIN2 (lgammal_r, *q, *r);  

(-times again; and trailing spaces)

> +  /* { dg-final { scan-assembler {\m__scalbnieee128\M} } }  */
> +  *p   = BUILTIN2 (scalbnl, *q, *r);  

(guess)

(Many more later.  I don't care in a testcase, but just make your editor
not make you do this?  :-) )

> +/* Debug main program to determine if the library has all of the mapped
> +   external functions.  Note, you need a new enough glibc to provide all of the
> +   f128 functions.  */
> +#ifdef DO_MAIN
> +int
> +main (void)
> +{
> +  return 0;
> +}
> +#endif

You don't need that #ifdef/#endif, that will always just compile?  Oh,
and you don't mention this is to check if linking works, with a manual
command line, aha.

Do you want to make this a link test then?  I guess it is hard to detect
whether you have a new enough glibc though :-/

> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> @@ -0,0 +1,37 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi -mabi=ieeelongdouble" } */

Same power10_ok issue as the other test.


Segher

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PowerPC: Map IEEE 128-bit long double built-in functions
  2020-11-05  0:13 ` Segher Boessenkool
@ 2020-11-05  1:39   ` Michael Meissner
  0 siblings, 0 replies; 5+ messages in thread
From: Michael Meissner @ 2020-11-05  1:39 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Michael Meissner, gcc-patches, David Edelsohn, Bill Schmidt,
	Peter Bergner, Jeff Law, Jonathan Wakely

On Wed, Nov 04, 2020 at 06:13:57PM -0600, Segher Boessenkool wrote:
> Hi!
> 
> On Thu, Oct 22, 2020 at 06:03:46PM -0400, Michael Meissner wrote:
> > To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128.
> 
> Is that correct?  What if you are compiling for c90?

That is the name in GLIBC.

> > 	* config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Add
> > 	support for mapping built-in function names for long double
> > 	built-in functions if long double is IEEE 128-bit.
> 
> "Map the built-in function names" etc.
> 
> > --- a/gcc/config/rs6000/rs6000.c
> > +++ b/gcc/config/rs6000/rs6000.c
> > @@ -26893,56 +26893,127 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
> >     library before you can switch the real*16 type at compile time.
> >  
> >     We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name.  We
> > -   only do this if the default is that long double is IBM extended double, and
> > -   the user asked for IEEE 128-bit.  */
> > +   only do this transformation if the __float128 type is enabled.  This
> > +   prevents us from doing the transformation on older 32-bit ports that might
> > +   have enabled using IEEE 128-bit floating point as the default long double
> > +   type.  */
> 
> I don't see why that is the right thing to do?  You'll have exactly
> these same problems on 32-bit!

The comment is refering to the remote possiblity that 32-bit VxWorks was
configured to use IEEE long double as the only long double type.  However, you
had to use several non-default options to do this.  All other historic 32-bit
implementations did not allow IEEE long double.

> 
> Hrm, we talked about that before I guess?  Do you just need to change
> this comment now?
> 
> > +	default:
> > +	  break;
> > +	}
> 
> That is useless, just leave it out?  The end of a switch will always
> fall through, and it is normal idiom to use that.

And it will get a warning that some enumeration elements did not have case
elements.

> > +      /* Update the __builtin_*printf && __builtin_*scanf functions.  */
> 
> "and" :-)
> 
> > +	  else if (name[len - 1] == 'l')
> > +	    {
> > +	      bool uses_ieee128_p = false;
> > +	      tree type = TREE_TYPE (decl);
> > +	      machine_mode ret_mode = TYPE_MODE (type);
> > +
> > +	      /* See if the function returns a IEEE 128-bit floating point type or
> > +		 complex type.  */
> > +	      if (ret_mode == TFmode || ret_mode == TCmode)
> > +		uses_ieee128_p = true;
> > +	      else
> >  		{
> > -		  machine_mode arg_mode = TYPE_MODE (arg);
> > -		  if (arg_mode == TFmode || arg_mode == TCmode)
> > +		  function_args_iterator args_iter;
> > +		  tree arg;
> 
> (declare that right before the FOREACH)
> 
> > +
> > +		  /* See if the function passes a IEEE 128-bit floating point type
> > +		     or complex type.  */
> > +		  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
> >  		    {
> > -		      uses_ieee128_p = true;
> > -		      break;
> > +		      machine_mode arg_mode = TYPE_MODE (arg);
> > +		      if (arg_mode == TFmode || arg_mode == TCmode)
> > +			{
> > +			  uses_ieee128_p = true;
> > +			  break;
> > +			}
> >  		    }
> >  		}
> 
> There is no point in doing all these early-outs in an initialisation
> function, making it much harder to read :-(
> 
> > +	      /* If we passed or returned an IEEE 128-bit floating point type,
> > +		 change the name.  Use __<name>ieee128, instead of <name>l.  */
> > +	      if (uses_ieee128_p)
> > +		newname = xasprintf ("__%.*sieee128", (int)(len - 1), name);
> 
> (int) (len - 1)
> 
> Please comment what the - 1 does, and/or what this is for at all.  (In
> the code / in a comment, not to me, I figured it out after a while.)

The comment just above the line says what it does.  I.e. it does not copy the
'l' in the name (i.e. sinl).

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

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-11-05  1:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-22 22:03 PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
2020-10-26 22:48 ` will schmidt
2020-11-03 22:13 ` Segher Boessenkool
2020-11-05  0:13 ` Segher Boessenkool
2020-11-05  1:39   ` Michael Meissner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).