public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
@ 2020-11-19 23:58 Michael Meissner
  2020-12-04  4:31 ` Ping " Michael Meissner
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Michael Meissner @ 2020-11-19 23:58 UTC (permalink / raw)
  To: gcc-patches, Michael Meissner, Segher Boessenkool,
	David Edelsohn, Bill Schmidt, Peter Bergner

[PATCH] PowerPC: Map IEEE 128-bit long double built-in functions.

I posted this patch by accident to an internal IBM mailing list instead of
gcc-patches.

This patch replaces patches previously submitted:

September 24th, 2020:
Message-ID: <20200924203159.GA31597@ibm-toto.the-meissners.org>

October 9th, 2020:
Message-ID: <20201009043543.GA11343@ibm-toto.the-meissners.org>

October 24th, 2020:
Message-ID: <20201022220346.GA8151@ibm-toto.the-meissners.org>

This patch maps the built-in functions that take or return long double
arguments on systems where long double is IEEE 128-bit.

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.

With the other IEEE long double patches, I have tested this patch by building 3
bootstrap compilers on a little endian power9 system, using the Advance
Toolchain AT14.0 library, which uses GLIBC 2.32:

    1)	One compiler defaulted long double to IBM extended double;
    2)	One compiler defaulted long double to IEEE 128-bit; (and)
    3)	One compiler defaulted long double to 64 bit.

I was able to bootstrap each compiler and run make check.  In addition for the
compilers using the two 128-bit long double types (IBM, IEEE), I have built the
spec 2017 benchmark for both power9 and power10.

At the moment, there are some differences between between the three runs for
make check.  I have some patches to fix these issue that I've done in the past,
and I will be working on resubmitting them in the future.

In addition, there are 3 fortran benchmarks (ieee/large_2.f90,
default_format_2.f90, and default_format_denormal_2.f90) that now pass when the
long double default is IEEE 128-bit.

Can I check this into the master branch?

gcc/
2020-11-17  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-11-17  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.  Add support for running test on power10.  Add
	support for running if long double defaults to 64-bits.
---
 gcc/config/rs6000/rs6000.c                    | 135 ++++--
 .../powerpc/float128-longdouble-math.c        | 442 ++++++++++++++++++
 .../powerpc/float128-longdouble-stdio.c       |  36 ++
 .../gcc.target/powerpc/float128-math.c        |  16 +-
 4 files changed, 589 insertions(+), 40 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 a5188553593..35e9c844e17 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -27065,57 +27065,128 @@ 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
+  if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
       && TREE_CODE (decl) == FUNCTION_DECL
-      && DECL_IS_UNDECLARED_BUILTIN (decl))
+      && DECL_IS_UNDECLARED_BUILTIN (decl)
+      && DECL_BUILT_IN_CLASS (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 and __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..07934bb7357
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
@@ -0,0 +1,442 @@
+/* { dg-require-effective-target ppc_float128_hw } */
+/* { dg-options "-mdejagnu-cpu=power9 -O2 -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble" } */
+
+/* Test if switching long double to IEEE 128-bit maps all of the math built-in
+   function names correctly.  We leave off the \M in matching the calls, so
+   power10 will match using bl foo@notoc.  */
+
+#ifdef DO_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 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
+
+/* 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 {\mbl __acoshieee128} } }  */
+  *p++ = BUILTIN1 (acoshl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __acosieee128} } }  */
+  *p++ = BUILTIN1 (acosl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __asinhieee128} } }  */
+  *p++ = BUILTIN1 (asinhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __asinieee128} } }  */
+  *p++ = BUILTIN1 (asinl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __atanhieee128} } }  */
+  *p++ = BUILTIN1 (atanhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __atanieee128} } }  */
+  *p++ = BUILTIN1 (atanl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __cbrtieee128} } }  */
+  *p++ = BUILTIN1 (cbrtl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2} } }  */
+  *p++ = BUILTIN1 (ceill, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __coshieee128} } }  */
+  *p++ = BUILTIN1 (coshl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __cosieee128} } }  */
+  *p++ = BUILTIN1 (cosl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __erfcieee128} } }  */
+  *p++ = BUILTIN1 (erfcl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __erfieee128} } }  */
+  *p++ = BUILTIN1 (erfl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __exp10ieee128} } }  */
+  *p++ = BUILTIN1 (exp10l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __exp2ieee128} } }  */
+  *p++ = BUILTIN1 (exp2l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __expieee128} } }  */
+  *p++ = BUILTIN1 (expl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __expm1ieee128} } }  */
+  *p++ = BUILTIN1 (expm1l, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsabsqp} } }  */
+  *p++ = BUILTIN1 (fabsl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3} } }  */
+  *p++ = BUILTIN1 (floorl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __lgammaieee128} } }  */
+  *p++ = BUILTIN1 (gammal, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __j0ieee128} } }  */
+  *p++ = BUILTIN1 (j0l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __j1ieee128} } }  */
+  *p++ = BUILTIN1 (j1l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __log10ieee128} } }  */
+  *p++ = BUILTIN1 (log10l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __log1pieee128} } }  */
+  *p++ = BUILTIN1 (log1pl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __log2ieee128} } }  */
+  *p++ = BUILTIN1 (log2l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __logbieee128} } }  */
+  *p++ = BUILTIN1 (logbl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __logieee128} } }  */
+  *p++ = BUILTIN1 (logl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __nearbyintieee128} } }  */
+  *p++ = BUILTIN1 (nearbyintl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __exp10ieee128} } }  */
+  *p++ = BUILTIN1 (pow10l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __rintieee128} } }  */
+  *p++ = BUILTIN1 (rintl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __roundevenieee128} } }  */
+  *p++ = BUILTIN1 (roundevenl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,0} } }  */
+  *p++ = BUILTIN1 (roundl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __significandieee128} } }  */
+  *p++ = BUILTIN1 (significandl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __sinhieee128} } }  */
+  *p++ = BUILTIN1 (sinhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __sinieee128} } }  */
+  *p++ = BUILTIN1 (sinl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __sqrtieee128} } }  */
+  *p++ = BUILTIN1 (sqrtl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __tanhieee128} } }  */
+  *p++ = BUILTIN1 (tanhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __tanieee128} } }  */
+  *p++ = BUILTIN1 (tanl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __tgammaieee128} } }  */
+  *p++ = BUILTIN1 (tgammal, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1} } }  */
+  *p++ = BUILTIN1 (truncl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __y0ieee128} } }  */
+  *p++ = BUILTIN1 (y0l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __y1ieee128} } }  */
+  *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 {\mbl __atan2ieee128} } }  */
+  *p++ = BUILTIN2 (atan2l, *q++, *r++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxscpsgnqp} } }  */
+  *p++ = BUILTIN2 (copysignl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __remainderieee128} } }  */
+  *p++ = BUILTIN2 (dreml, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __fdimieee128} } }  */
+  *p++ = BUILTIN2 (fdiml, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __fmaxieee128} } }  */
+  *p++ = BUILTIN2 (fmaxl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __fminieee128} } }  */
+  *p++ = BUILTIN2 (fminl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __fmodieee128} } }  */
+  *p++ = BUILTIN2 (fmodl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __hypotieee128} } }  */
+  *p++ = BUILTIN2 (hypotl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __nextafterieee128} } }  */
+  *p++ = BUILTIN2 (nextafterl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __nexttowardieee128} } }  */
+  *p++ = BUILTIN2 (nexttowardl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __powieee128} } }  */
+  *p++ = BUILTIN2 (powl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __scalbnieee128} } }  */
+  *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} } }  */
+  *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 {\mbl __cabsieee128} } }  */
+  *p++ = BUILTIN1 (cabsl, *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 {\mbl __cacoshieee128} } }  */
+  *p++ = BUILTIN1 (cacoshl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __cacosieee128} } }  */
+  *p++ = BUILTIN1 (cacosl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __casinhieee128} } }  */
+  *p++ = BUILTIN1 (casinhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __casinieee128} } }  */
+  *p++ = BUILTIN1 (casinl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __catanhieee128} } }  */
+  *p++ = BUILTIN1 (catanhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __catanieee128} } }  */
+  *p++ = BUILTIN1 (catanl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __ccoshieee128} } }  */
+  *p++ = BUILTIN1 (ccoshl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __ccosieee128} } }  */
+  *p++ = BUILTIN1 (ccosl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __cexpieee128} } }  */
+  *p++ = BUILTIN1 (cexpl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __clogieee128} } }  */
+  *p++ = BUILTIN1 (clogl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __clog10ieee128} } }  */
+  *p++ = BUILTIN1 (clog10l, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __cprojieee128} } }  */
+  *p++ = BUILTIN1 (cprojl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __csinhieee128} } }  */
+  *p++ = BUILTIN1 (csinhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __csinieee128} } }  */
+  *p++ = BUILTIN1 (csinl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __csqrtieee128} } }  */
+  *p++ = BUILTIN1 (csqrtl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __ctanhieee128} } }  */
+  *p++ = BUILTIN1 (ctanhl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __ctanieee128} } }  */
+  *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 {\mbl __sincosieee128} } }  */
+  *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 {\mbl __cpowieee128} } }  */
+  *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 {\mbl __frexpieee128} } }  */
+  *p++ = BUILTIN2 (frexpl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __lgammaieee128_r} } }  */
+  *p++ = BUILTIN2 (gammal_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 {\mbl __ldexpieee128} } }  */
+  *p++ = BUILTIN2 (ldexpl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __powikf2} } }  */
+  *p++ = BUILTIN2 (powil, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __scalbnieee128} } }  */
+  *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 {\mbl __scalblnieee128} } }  */
+  *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 {\mbl __jnieee128} } }  */
+  *p++ = BUILTIN2 (jnl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mbl __ynieee128} } }  */
+  *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 {\mbl __modfieee128} } }  */
+  *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 {\mbl __remquoieee128} } }  */
+  *p = BUILTIN3 (remquol, *q, *r, *s);
+}
+
+/* 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 {\mbl __ceilieee128} } }  */
+  *p++ = BUILTIN1 (iceill, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __floorieee128} } }  */
+  *p++ = BUILTIN1 (ifloorl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __ilogbieee128} } }  */
+  *p++ = BUILTIN1 (ilogbl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __lrintieee128} } }  */
+  *p++ = BUILTIN1 (irintl, *q++);
+
+  /* { dg-final { scan-assembler {\mbl __lroundieee128} } }  */
+  *p++ = BUILTIN1 (iroundl, *q++);
+
+  /* inline code.  */
+  /* { dg-final { scan-assembler {\mxscvqpswz} } }  */
+  *p++ = BUILTIN1 (signbitl, *q++);
+}
+
+/* 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 {\mbl __nexttoward_to_ieee128} } }  */
+  *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 {\mbl __nexttowardf_to_ieee128} } }  */
+  *p = BUILTIN2 (nexttowardf, *q, *r);
+}
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..39e59d949f9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
@@ -0,0 +1,36 @@
+/* { dg-require-effective-target ppc_float128_hw } */
+/* { dg-options "-mdejagnu-cpu=power9 -O2 -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble" } */
+
+/* Test if switching long double to IEEE 128-bit maps the printf and scanf
+   function names correctly.  We leave off the \M in matching the calls, so
+   power10 will match using bl foo@notoc.  */
+
+#include <stdlib.h>
+
+volatile long double x = 1.0L;
+volatile long double y, z;
+
+int
+main (void)
+{
+  char buffer[100];
+
+  /* { dg-final { scan-assembler {\mbl __sprintfieee128} } }  */
+  __builtin_sprintf (buffer, "%Lg", x);
+
+  /* { dg-final { scan-assembler {\mbl __printfieee128} } }  */
+  __builtin_printf ("x is %Lg [%s]\n", x, buffer);
+
+  /* { dg-final { scan-assembler {\mbl __isoc99_sscanfieee128} } }  */
+  __builtin_sscanf (buffer, "%Lg", &y);
+
+  __builtin_printf ("Type 1.0: ");
+
+  /* { dg-final { scan-assembler {\mbl __isoc99_scanfieee128} } }  */
+  __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..d1e22239718 100644
--- a/gcc/testsuite/gcc.target/powerpc/float128-math.c
+++ b/gcc/testsuite/gcc.target/powerpc/float128-math.c
@@ -1,20 +1,20 @@
-/* { dg-do compile { target { powerpc*-*-linux* } } } */
 /* { dg-require-effective-target ppc_float128_sw } */
 /* { dg-require-effective-target vsx_hw } */
-/* { dg-options "-mvsx -O2 -mfloat128 -mabi=ieeelongdouble -Wno-psabi" } */
+/* { dg-options "-mvsx -O2 -mfloat128 -mlong-double-128 -mabi=ieeelongdouble -Wno-psabi" } */
 
 /* Test whether we convert __builtin_<math>l to __builtin_<math>f128 if the
-   default long double type is IEEE 128-bit.  Also test that using the explicit
-   __builtin_<math>f128 function does not interfere with the __builtin_<math>l
-   function.  */
+   default long double type is IEEE 128-bit.  We leave off the \M in matching
+   the calls, so power10 will match using bl foo@notoc.  Also test that using
+   the explicit __builtin_<math>f128 function does not interfere with the
+   __builtin_<math>l function.  */
 
 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} } } */
+/* { dg-final { scan-assembler-not {\mbl sinl}         } } */
-- 
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] 6+ messages in thread

* Ping [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
  2020-11-19 23:58 [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
@ 2020-12-04  4:31 ` Michael Meissner
  2020-12-10 15:27 ` Ping x2: " Michael Meissner
  2020-12-10 21:20 ` Segher Boessenkool
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Meissner @ 2020-12-04  4:31 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, Segher Boessenkool,
	David Edelsohn, Bill Schmidt, Peter Bergner

I haven't received a response for this patch:

| Date: Thu, 19 Nov 2020 18:58:14 -0500
| Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
| Message-ID: <20201119235814.GA322@ibm-toto.the-meissners.org>
| https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559659.html

-- 
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] 6+ messages in thread

* Ping x2: [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
  2020-11-19 23:58 [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
  2020-12-04  4:31 ` Ping " Michael Meissner
@ 2020-12-10 15:27 ` Michael Meissner
  2020-12-10 21:20 ` Segher Boessenkool
  2 siblings, 0 replies; 6+ messages in thread
From: Michael Meissner @ 2020-12-10 15:27 UTC (permalink / raw)
  To: Michael Meissner, Segher Boessenkool
  Cc: gcc-patches, David Edelsohn, Bill Schmidt, Peter Bergner

This patch is one of the critical patches to enable building GCC with the long
double type set to IEEE 128-bit.

I haven't received a response for this patch:

| Date: Thu, 19 Nov 2020 18:58:14 -0500
| Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
| Message-ID: <20201119235814.GA322@ibm-toto.the-meissners.org>
| https://gcc.gnu.org/pipermail/gcc-patches/2020-November/559659.html

-- 
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] 6+ messages in thread

* Re: [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
  2020-11-19 23:58 [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
  2020-12-04  4:31 ` Ping " Michael Meissner
  2020-12-10 15:27 ` Ping x2: " Michael Meissner
@ 2020-12-10 21:20 ` Segher Boessenkool
  2020-12-11 22:07   ` Michael Meissner
  2 siblings, 1 reply; 6+ messages in thread
From: Segher Boessenkool @ 2020-12-10 21:20 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, David Edelsohn, Bill Schmidt,
	Peter Bergner

Hi!

On Thu, Nov 19, 2020 at 06:58:14PM -0500, Michael Meissner wrote:
> 	* 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.

Please write what it does, not "add support".  Say what names it maps
to, importantly.  You don't need to list all, but what you wrote is
100% contentless.

> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index a5188553593..35e9c844e17 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -27065,57 +27065,128 @@ 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 still don't understand why you want to support some hypothetical and
untested configuration.

> +  /* { dg-final { scan-assembler {\mbl __ynieee128} } }  */

This kind of thing does not portably work (the function names can have
various prefixes added).


I cannot understand this code, and it does seem far from obviously
correct.  But, okay for trunk if you handle all fallout (and I mean all,
not just "all you consider important").


Segher

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

* Re: [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
  2020-12-10 21:20 ` Segher Boessenkool
@ 2020-12-11 22:07   ` Michael Meissner
  2020-12-11 23:03     ` Segher Boessenkool
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Meissner @ 2020-12-11 22:07 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Michael Meissner, gcc-patches, David Edelsohn, Bill Schmidt,
	Peter Bergner

On Thu, Dec 10, 2020 at 03:20:01PM -0600, Segher Boessenkool wrote:
> Hi!
> 
> On Thu, Nov 19, 2020 at 06:58:14PM -0500, Michael Meissner wrote:
> > 	* 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.
> 
> Please write what it does, not "add support".  Say what names it maps
> to, importantly.  You don't need to list all, but what you wrote is
> 100% contentless.

Ok.

> > diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> > index a5188553593..35e9c844e17 100644
> > --- a/gcc/config/rs6000/rs6000.c
> > +++ b/gcc/config/rs6000/rs6000.c
> > @@ -27065,57 +27065,128 @@ 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 still don't understand why you want to support some hypothetical and
> untested configuration.

I'm not sure what you mean by hypothetical and untested configuration.  If you
build a default configuration on a big endian system (i.e. do not use
--with-cpu specifying at least power7), the __float128 type is not enabled by
default, because you need access to the VSX vector registers.

> > +  /* { dg-final { scan-assembler {\mbl __ynieee128} } }  */
> 
> This kind of thing does not portably work (the function names can have
> various prefixes added).

Why would it have prefixes?  Can you suggest a better way of doing the test?
There are lots of different long names that need to get mapped if long doubles
are IEEE 128-bit.  This test just tries to test every function to make sure it
got mapped appropriately.

We can't do a link test without requiring that GLIBC is 2.32 or newer, since
the older GLIBCs don't have all of the symbols.  And the link test would only
work on little endian ELFV2 systems, since big endian GLIBC 2.32 does not
export any of the float128 stuff.

> I cannot understand this code, and it does seem far from obviously
> correct.  But, okay for trunk if you handle all fallout (and I mean all,
> not just "all you consider important").

Note, the code is only invokved for systems where IEEE 128-bit floating point
is supported.  So it will never get called for a lot of the random embedded
systems or the big endian systems.

There is another way I could do the code that is simpler, but over time it will
need maintainence as new built-in functions are added.

Right now, in going over the system built-ins, it tries to do the mapping based
on the names:

    1)	If the function has a long double argument or returns long double, and
	it ends in 'l', the name is mapped to "__" followed by <name minus 'l'>
	and then "ieee128".  I.e. "sinl" becomes "__sinieee128".

    2)	However, some names do not follow that formula and I have a switch
	statement for the outliers.

    3)	If the function name ends in "printf", the name is transformed to "__"
	followed by <name> followed by "ieee128".  I.e. "sprintf" becomes
	"__sprintfieee128".

    4)	If the function names ends in "scanf", the name is transformed to
	"__isoc99_" followed by <name> followed by "ieee128".  I.e. "vscanf"
	becomes "__isoc99_vscanfieee128".

I could change it to just having a switch statement of all known built-in
functions.  I would need to add some code that if checking was enabled, it
would look for built-in functions that use long double that are not mapped, and
issue a warning to update the table of maps.  This might be cleaner to look at,
but every so often, we would need to add a new symbol.

Would you prefer me to do that second implementation?

-- 
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] 6+ messages in thread

* Re: [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions
  2020-12-11 22:07   ` Michael Meissner
@ 2020-12-11 23:03     ` Segher Boessenkool
  0 siblings, 0 replies; 6+ messages in thread
From: Segher Boessenkool @ 2020-12-11 23:03 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, David Edelsohn, Bill Schmidt,
	Peter Bergner

On Fri, Dec 11, 2020 at 05:07:28PM -0500, Michael Meissner wrote:
> On Thu, Dec 10, 2020 at 03:20:01PM -0600, Segher Boessenkool wrote:
> > >     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 still don't understand why you want to support some hypothetical and
> > untested configuration.
> 
> I'm not sure what you mean by hypothetical and untested configuration.

Do you know any 32-bit config that uses IEEE QP float?

You should be able to use it (and on *all* systems even, that just
requires soft float for it, and it would make testing HUGELY easier, but
you prefer having ten times are much frustrating work later over having
a little bit of work now.  But that aside.), but it isn't the default on
any 32-bit config.  So it is hypothetical, and because of that, it
obviously cannot be tested.

> If you
> build a default configuration on a big endian system (i.e. do not use
> --with-cpu specifying at least power7), the __float128 type is not enabled by
> default, because you need access to the VSX vector registers.

It *cannot* be enabled on most older systems.  This is a big problem.
If we *did* have soft float QP float, we could even enable it as the
default long double type on many systems.  This is *much* less
problematic than switching the long double default on some complex
subset of configurations.

> > > +  /* { dg-final { scan-assembler {\mbl __ynieee128} } }  */
> > 
> > This kind of thing does not portably work (the function names can have
> > various prefixes added).
> 
> Why would it have prefixes?  Can you suggest a better way of doing the test?

Many testcases do it already.  Like, builtins-1.c has
{\mbl \.?_?__divdi3\M}.  It depends on what ABI you have.

> There are lots of different long names that need to get mapped if long doubles
> are IEEE 128-bit.  This test just tries to test every function to make sure it
> got mapped appropriately.

It isn't portable enough.  I know you think that only powerpc64le-linux
has, and can ever have, and will ever have, QP float.  But that is
wrong.  And I don't want more work than necessary because you just
randomly restrict things.

You know this, I have said it tens of times already.

> We can't do a link test without requiring that GLIBC is 2.32 or newer, since
> the older GLIBCs don't have all of the symbols.

You should not require glibc for this at all.  All compiler support
routines belong in libgcc.  That is what libgcc *is*.

Not wanting to do that work gives crazy restrictions already, and will
be even more work in the future.

> And the link test would only
> work on little endian ELFV2 systems, since big endian GLIBC 2.32 does not
> export any of the float128 stuff.

Yes, more technical debt.  (I hate that term, but it is appropriate
here).

> > I cannot understand this code, and it does seem far from obviously
> > correct.  But, okay for trunk if you handle all fallout (and I mean all,
> > not just "all you consider important").
> 
> Note, the code is only invokved for systems where IEEE 128-bit floating point
> is supported.  So it will never get called for a lot of the random embedded
> systems or the big endian systems.

Did I say that?

I meant what I *said*, not whatever you imagine I meant.


Segher

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

end of thread, other threads:[~2020-12-11 23:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-19 23:58 [PATCH] PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
2020-12-04  4:31 ` Ping " Michael Meissner
2020-12-10 15:27 ` Ping x2: " Michael Meissner
2020-12-10 21:20 ` Segher Boessenkool
2020-12-11 22:07   ` Michael Meissner
2020-12-11 23:03     ` Segher Boessenkool

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