public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work018)] PowerPC: Map long double built-in functions if IEEE 128-bit long double.
@ 2020-09-18 18:06 Michael Meissner
  0 siblings, 0 replies; only message in thread
From: Michael Meissner @ 2020-09-18 18:06 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c8760e7d293cb53176053a10151861b5862c648e

commit c8760e7d293cb53176053a10151861b5862c648e
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Fri Sep 18 14:05:31 2020 -0400

    PowerPC: Map long double built-in functions if IEEE 128-bit long double.
    
    gcc/
    2020-09-18  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-09-18  Michael Meissner  <meissner@linux.ibm.com>
    
            * gcc.target/powerpc/float128-longdouble-math.c: New test.
            * gcc.target/powerpc/float128-longdouble-stdio.c: New test.

Diff:
---
 gcc/config/rs6000/rs6000.c                         | 153 ++++--
 .../gcc.target/powerpc/float128-longdouble-math.c  | 559 +++++++++++++++++++++
 .../gcc.target/powerpc/float128-longdouble-stdio.c |  37 ++
 3 files changed, 718 insertions(+), 31 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index b589f4566c2..0ff0f31d552 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -26909,56 +26909,147 @@ 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 = "remainderf128";
+	  break;
+
+	case BUILT_IN_GAMMAL:
+	  newname = "lgammaf128";
+	  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 = "exp10f128";
+	  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)
 	    {
-	      function_args_iterator args_iter;
-	      tree arg;
+	      char *name2 = (char *) alloca (len + 1 + printf_extra);
+	      strcpy (name2, "__");
+	      memcpy (name2 + 2, name, len);
+	      strcpy (name2 + 2 + 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 (len >= scanf_len
+		   && strcmp (name + len - scanf_len, "scanf") == 0)
+	    {
+	      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;
+	    }
+
+	  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.  */
+	      if (uses_ieee128_p)
+		{
+		  char *name2 = (char *) alloca (len + 4);
+		  memcpy (name2, name, len - 1);
+		  strcpy (name2 + len - 1, "f128");
+		  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..e7a79f5e4e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
@@ -0,0 +1,559 @@
+/* { 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 {\macoshf128\M} } }  */
+  *p++ = BUILTIN1 (acoshl, *q++);
+
+  /* { dg-final { scan-assembler {\macosf128\M} } }  */
+  *p++ = BUILTIN1 (acosl, *q++);
+
+  /* { dg-final { scan-assembler {\masinhf128\M} } }  */
+  *p++ = BUILTIN1 (asinhl, *q++);
+
+  /* { dg-final { scan-assembler {\masinf128\M} } }  */
+  *p++ = BUILTIN1 (asinl, *q++);
+
+  /* { dg-final { scan-assembler {\matanhf128\M} } }  */
+  *p++ = BUILTIN1 (atanhl, *q++);
+
+  /* { dg-final { scan-assembler {\matanf128\M} } }  */
+  *p++ = BUILTIN1 (atanl, *q++);
+
+  /* { dg-final { scan-assembler {\mcbrtf128\M} } }  */
+  *p++ = BUILTIN1 (cbrtl, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (ceill, *q++);
+
+  /* { dg-final { scan-assembler {\mcoshf128\M} } }  */
+  *p++ = BUILTIN1 (coshl, *q++);
+
+  /* { dg-final { scan-assembler {\mcosf128\M} } }  */
+  *p++ = BUILTIN1 (cosl, *q++);
+
+  /* { dg-final { scan-assembler {\merfcf128\M} } }  */
+  *p++ = BUILTIN1 (erfcl, *q++);
+
+  /* { dg-final { scan-assembler {\merff128\M} } }  */
+  *p++ = BUILTIN1 (erfl, *q++);
+
+  /* { dg-final { scan-assembler {\mexp10f128\M} } }  */
+  *p++ = BUILTIN1 (exp10l, *q++);
+
+  /* { dg-final { scan-assembler {\mexp2f128\M} } }  */
+  *p++ = BUILTIN1 (exp2l, *q++);
+
+  /* { dg-final { scan-assembler {\mexpf128\M} } }  */
+  *p++ = BUILTIN1 (expl, *q++);
+
+  /* { dg-final { scan-assembler {\mexpm1f128\M} } }  */
+  *p++ = BUILTIN1 (expm1l, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (fabsl, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (floorl, *q++);
+
+  /* { dg-final { scan-assembler {\mlgammaf128\M} } }  */
+  *p++ = BUILTIN1 (gammal, *q++);
+
+  /* { dg-final { scan-assembler {\mj0f128\M} } }  */
+  *p++ = BUILTIN1 (j0l, *q++);
+
+  /* { dg-final { scan-assembler {\mj1f128\M} } }  */
+  *p++ = BUILTIN1 (j1l, *q++);
+
+  /* lgammaf128 mentioned previously.  */
+  *p++ = BUILTIN1 (lgammal, *q++);
+
+  /* { dg-final { scan-assembler {\mlog10f128\M} } }  */
+  *p++ = BUILTIN1 (log10l, *q++);
+
+  /* { dg-final { scan-assembler {\mlog1pf128\M} } }  */
+  *p++ = BUILTIN1 (log1pl, *q++);
+
+  /* { dg-final { scan-assembler {\mlog2f128\M} } }  */
+  *p++ = BUILTIN1 (log2l, *q++);
+
+  /* { dg-final { scan-assembler {\mlogbf128\M} } }  */
+  *p++ = BUILTIN1 (logbl, *q++);
+
+  /* { dg-final { scan-assembler {\mlogf128\M} } }  */
+  *p++ = BUILTIN1 (logl, *q++);
+
+  /* { dg-final { scan-assembler {\mnearbyintf128\M} } }  */
+  *p++ = BUILTIN1 (nearbyintl, *q++);
+
+  /* { dg-final { scan-assembler {\mexp10f128\M} } }  */
+  *p++ = BUILTIN1 (pow10l, *q++);
+
+  /* { dg-final { scan-assembler {\mrintf128\M} } }  */
+  *p++ = BUILTIN1 (rintl, *q++);
+
+  /* { dg-final { scan-assembler {\mroundevenf128\M} } }  */
+  *p++ = BUILTIN1 (roundevenl, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (roundl, *q++);
+
+  /* { dg-final { scan-assembler {\m__significandieee128\M} } }  */
+  *p++ = BUILTIN1 (significandl, *q++);
+
+  /* { dg-final { scan-assembler {\msinhf128\M} } }  */
+  *p++ = BUILTIN1 (sinhl, *q++);
+
+  /* { dg-final { scan-assembler {\msinf128\M} } }  */
+  *p++ = BUILTIN1 (sinl, *q++);
+
+  /* { dg-final { scan-assembler {\msqrtf128\M} } }  */
+  *p++ = BUILTIN1 (sqrtl, *q++);
+
+  /* { dg-final { scan-assembler {\mtanhf128\M} } }  */
+  *p++ = BUILTIN1 (tanhl, *q++);
+
+  /* { dg-final { scan-assembler {\mtanf128\M} } }  */
+  *p++ = BUILTIN1 (tanl, *q++);
+
+  /* { dg-final { scan-assembler {\mtgammaf128\M} } }  */
+  *p++ = BUILTIN1 (tgammal, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (truncl, *q++);
+
+  /* { dg-final { scan-assembler {\my0f128\M} } }  */
+  *p++ = BUILTIN1 (y0l, *q++);
+
+  /* { dg-final { scan-assembler {\my1f128\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 {\matan2f128\M} } }  */
+  *p++ = BUILTIN2 (atan2l, *q++, *r++);
+
+  /* inline code.  */
+  *p++ = BUILTIN2 (copysignl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mremainderf128\M} } }  */
+  *p++ = BUILTIN2 (dreml, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mfdimf128\M} } }  */
+  *p++ = BUILTIN2 (fdiml, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mfmaxf128\M} } }  */
+  *p++ = BUILTIN2 (fmaxl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mfminf128\M} } }  */
+  *p++ = BUILTIN2 (fminl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mfmodf128\M} } }  */
+  *p++ = BUILTIN2 (fmodl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mhypotf128\M} } }  */
+  *p++ = BUILTIN2 (hypotl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mnextafterf128\M} } }  */
+  *p++ = BUILTIN2 (nextafterl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__nexttowardieee128\M} } }  */
+  *p++ = BUILTIN2 (nexttowardl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mpowf128\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.  */
+  *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 {\mcabsf128\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 {\mcacoshf128\M} } }  */
+  *p++ = BUILTIN1 (cacoshl, *q++);
+
+  /* { dg-final { scan-assembler {\mcacosf128\M} } }  */
+  *p++ = BUILTIN1 (cacosl, *q++);
+
+  /* { dg-final { scan-assembler {\mcasinhf128\M} } }  */
+  *p++ = BUILTIN1 (casinhl, *q++);
+
+  /* { dg-final { scan-assembler {\mcasinf128\M} } }  */
+  *p++ = BUILTIN1 (casinl, *q++);
+
+  /* { dg-final { scan-assembler {\mcatanhf128\M} } }  */
+  *p++ = BUILTIN1 (catanhl, *q++);
+
+  /* { dg-final { scan-assembler {\mcatanf128\M} } }  */
+  *p++ = BUILTIN1 (catanl, *q++);
+
+  /* { dg-final { scan-assembler {\mccoshf128\M} } }  */
+  *p++ = BUILTIN1 (ccoshl, *q++);
+
+  /* { dg-final { scan-assembler {\mccosf128\M} } }  */
+  *p++ = BUILTIN1 (ccosl, *q++);
+
+  /* { dg-final { scan-assembler {\mcexpf128\M} } }  */
+  *p++ = BUILTIN1 (cexpl, *q++);
+
+  /* { dg-final { scan-assembler {\mclogf128\M} } }  */
+  *p++ = BUILTIN1 (clogl, *q++);
+
+  /* { dg-final { scan-assembler {\mclog10f128\M} } }  */
+  *p++ = BUILTIN1 (clog10l, *q++);
+
+  /* inline code.  */
+  *p++ = BUILTIN1 (conjl, *q++);
+
+  /* { dg-final { scan-assembler {\mcprojf128\M} } }  */
+  *p++ = BUILTIN1 (cprojl, *q++);
+
+  /* { dg-final { scan-assembler {\mcsinhf128\M} } }  */
+  *p++ = BUILTIN1 (csinhl, *q++);
+
+  /* { dg-final { scan-assembler {\mcsinf128\M} } }  */
+  *p++ = BUILTIN1 (csinl, *q++);
+
+  /* { dg-final { scan-assembler {\mcsqrtf128\M} } }  */
+  *p++ = BUILTIN1 (csqrtl, *q++);
+
+  /* { dg-final { scan-assembler {\mctanhf128\M} } }  */
+  *p++ = BUILTIN1 (ctanhl, *q++);
+
+  /* { dg-final { scan-assembler {\mctanf128\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 {\mcpowf128\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 {\mfrexpf128\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 {\mldexpf128\M} } }  */
+  *p++ = BUILTIN2 (ldexpl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\m__powikf2\M} } }  */
+  *p++ = BUILTIN2 (powil, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mscalbnf128\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 {\mscalblnf128\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 {\mjnf128\M} } }  */
+  *p++ = BUILTIN2 (jnl, *q++, *r++);
+
+  /* { dg-final { scan-assembler {\mynf128\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 {\mmodff128\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 {\mremquof128\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 {\mceilf128\M} } }  */
+  *p++ = BUILTIN1 (iceill, *q++);
+
+  /* { dg-final { scan-assembler {\mfloorf128\M} } }  */
+  *p++ = BUILTIN1 (ifloorl, *q++);
+
+  /* { dg-final { scan-assembler {\milogbf128\M} } }  */
+  *p++ = BUILTIN1 (ilogbl, *q++);
+
+  /* { dg-final { scan-assembler {\mlrintf128\M} } }  */
+  *p++ = BUILTIN1 (irintl, *q++);
+
+  /* { dg-final { scan-assembler {\mlroundf128\M} } }  */
+  *p++ = BUILTIN1 (iroundl, *q++);
+
+  /* inline code.  */
+  *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;
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-09-18 18:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-18 18:06 [gcc(refs/users/meissner/heads/work018)] PowerPC: Map long double built-in functions if IEEE 128-bit long double 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).