[PATCH 1/9, revised] PowerPC: Map long double built-in functions if IEEE 128-bit long double.

Michael Meissner meissner@linux.ibm.com
Fri Oct 9 04:35:44 GMT 2020


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

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

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.

Normally the mapping is done in the math.h and stdio.h files.  However, not
everybody uses these files, which means we also need to change the external
name for the built-in function within the compiler.

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.

gcc/
2020-10-09  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-09  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                    | 162 ++++-
 .../powerpc/float128-longdouble-math.c        | 567 ++++++++++++++++++
 .../powerpc/float128-longdouble-stdio.c       |  37 ++
 .../gcc.target/powerpc/float128-math.c        |   6 +-
 4 files changed, 738 insertions(+), 34 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 b28f4adf464..4c141c9f276 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -26897,56 +26897,156 @@ 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);
+      const 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);
+	default:
+	  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
+	case BUILT_IN_DREML:
+	  newname = "__remainderieee128";
+	  break;
+
+	case BUILT_IN_GAMMAL:
+	  newname = "__lgammaieee128";
+	  break;
+
+	case BUILT_IN_GAMMAL_R:
+	case BUILT_IN_LGAMMAL_R:
+	  newname = "__lgammaieee128_r";
+	  break;
+
+	case BUILT_IN_NEXTTOWARD:
+	  newname = "__nexttoward_to_ieee128";
+	  break;
+
+	case BUILT_IN_NEXTTOWARDF:
+	  newname = "__nexttowardf_to_ieee128";
+	  break;
+
+	case BUILT_IN_NEXTTOWARDL:
+	  newname = "__nexttowardieee128";
+	  break;
+
+	case BUILT_IN_POW10L:
+	  newname = "__exp10ieee128";
+	  break;
+
+	case BUILT_IN_SCALBL:
+	  newname = "__scalbnieee128";
+	  break;
+
+	case BUILT_IN_SIGNIFICANDL:
+	  newname = "__significandieee128";
+	  break;
+
+	case BUILT_IN_SINCOSL:
+	  newname = "__sincosieee128";
+	  break;
+	}
+
+      /* Update the __builtin_*printf && __builtin_*scanf functions.  */
+      if (!newname)
+	{
+	  const size_t printf_len = sizeof ("printf") - 1;
+	  const size_t scanf_len = sizeof ("scanf") - 1;
+	  const size_t printf_extra
+	    = sizeof ("__") - 1 + sizeof ("ieee128") - 1;
+	  const size_t scanf_extra
+	    = sizeof ("__isoc99_") - 1 + sizeof ("ieee128") - 1;
+
+	  if (len >= printf_len
+	      && strcmp (name + len - printf_len, "printf") == 0)
+	    {
+	      char *name2 = (char *) alloca (len + 1 + printf_extra);
+	      strcpy (name2, "__");
+	      memcpy (name2 + 2, name, len);
+	      strcpy (name2 + 2 + len, "ieee128");
+	      newname = (const char *) name2;
+	    }
+
+	  else if (len >= scanf_len
+		   && strcmp (name + len - scanf_len, "scanf") == 0)
 	    {
-	      function_args_iterator args_iter;
-	      tree arg;
+	      char *name2 = (char *) alloca (len + 1 + scanf_extra);
+	      strcpy (name2, "__isoc99_");
+	      memcpy (name2 + sizeof ("__isoc99") - 1, name, len);
+	      strcpy (name2 + sizeof ("__isoc99") - 1 + len, "ieee128");
+	      newname = (const char *) name2;
+	    }
 
-	      /* See if the function passes a IEEE 128-bit floating point type
-		 or complex type.  */
-	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
+	  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)
+		{
+		  size_t prefix_len = sizeof ("__") - 1;
+		  size_t suffix_len = sizeof ("ieee128") - 1;
+		  char *name2 = (char *) alloca (len + prefix_len + suffix_len + 1);
+		  char *name3 = name2;
+
+		  memcpy (name3, "__", prefix_len);
+		  name3 += prefix_len;
+
+		  memcpy (name3, name, len - 1);	/* omit trailing 'l'.  */
+		  name3 += len - 1;
+
+		  memcpy (name3, "ieee128", suffix_len + 1);
+		  newname = (const char *) name2;
+		}
 	    }
 	}
+
+      if (newname)
+	{
+	  if (TARGET_DEBUG_BUILTIN)
+	    fprintf (stderr, "Map %s => %s\n", name, newname);
+
+	  id = get_identifier (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..77c7b41cec9
--- /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__isoc99sscanfieee128\M} } }  */
+  __builtin_sscanf (buffer, "%Lg", &y);
+
+  __builtin_printf ("Type 1.0: ");
+
+  /* { dg-final { scan-assembler {\m__isoc99scanfieee128\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


More information about the Gcc-patches mailing list