public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work030)] PowerPC: Map IEEE 128-bit long double built-in functions.
@ 2020-12-18  1:26 Michael Meissner
  0 siblings, 0 replies; 3+ messages in thread
From: Michael Meissner @ 2020-12-18  1:26 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9daf614e16b8bcd616bca5c50df8026c87fe3b66

commit 9daf614e16b8bcd616bca5c50df8026c87fe3b66
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Thu Dec 17 20:26:19 2020 -0500

    PowerPC: Map IEEE 128-bit long double built-in functions.
    
    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>
    
    November 19th, 2020:
    Message-ID: <20201119235814.GA322@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.
    
    If 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.
    
    gcc/
    2020-12-17  Michael Meissner  <meissner@linux.ibm.com>
    
            * config/rs6000/rs6000.c (ieee128_builtin_name): New function.
            (built_in_uses_long_double): New function.
            (rs6000_mangle_decl_assembler_name): Update support for mapping built-in
            function names for long double built-in functions if long double is
            IEEE 128-bit to catch all of the built-in functions that take or
            return long double arguments.
    
    gcc/testsuite/
    2020-12-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.

Diff:
---
 gcc/config/rs6000/rs6000.c                         | 234 +++++++++--
 .../gcc.target/powerpc/float128-longdouble-math.c  | 442 +++++++++++++++++++++
 .../gcc.target/powerpc/float128-longdouble-stdio.c |  36 ++
 gcc/testsuite/gcc.target/powerpc/float128-math.c   |  16 +-
 4 files changed, 683 insertions(+), 45 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 72f5d4250b5..b77abb10b24 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -27095,6 +27095,165 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
 #endif
 
 \f
+/* If long double uses the IEEE 128-bit representation, return the name used
+   within GLIBC for the IEEE 128-bit long double built-in, instead of the
+   default IBM 128-bit long double built-in.  Or return NULL if the built-in
+   function does not use long double.  */
+
+static const char *
+ieee128_builtin_name (built_in_function fn)
+{
+  switch (fn)
+    {
+    default:			return NULL;
+    case BUILT_IN_ACOSHL:	return "__acoshieee128";
+    case BUILT_IN_ACOSL:	return "__acosieee128";
+    case BUILT_IN_ASINHL:	return "__asinhieee128";
+    case BUILT_IN_ASINL:	return "__asinieee128";
+    case BUILT_IN_ATAN2L:	return "__atan2ieee128";
+    case BUILT_IN_ATANHL:	return "__atanhieee128";
+    case BUILT_IN_ATANL:	return "__atanieee128";
+    case BUILT_IN_CABSL:	return "__cabsieee128";
+    case BUILT_IN_CACOSHL:	return "__cacoshieee128";
+    case BUILT_IN_CACOSL:	return "__cacosieee128";
+    case BUILT_IN_CARGL:	return "__cargieee128";
+    case BUILT_IN_CASINHL:	return "__casinhieee128";
+    case BUILT_IN_CASINL:	return "__casinieee128";
+    case BUILT_IN_CATANHL:	return "__catanhieee128";
+    case BUILT_IN_CATANL:	return "__catanieee128";
+    case BUILT_IN_CBRTL:	return "__cbrtieee128";
+    case BUILT_IN_CCOSHL:	return "__ccoshieee128";
+    case BUILT_IN_CCOSL:	return "__ccosieee128";
+    case BUILT_IN_CEILL:	return "__ceilieee128";
+    case BUILT_IN_CEXPL:	return "__cexpieee128";
+    case BUILT_IN_CEXPIL:	return "__cexpiieee128";
+    case BUILT_IN_CIMAGL:	return "__cimagieee128";
+    case BUILT_IN_CLOG10L:	return "__clog10ieee128";
+    case BUILT_IN_CLOGL:	return "__clogieee128";
+    case BUILT_IN_CONJL:	return "__conjieee128";
+    case BUILT_IN_COPYSIGNL:	return "__copysignieee128";
+    case BUILT_IN_COSHL:	return "__coshieee128";
+    case BUILT_IN_COSL:		return "__cosieee128";
+    case BUILT_IN_CPOWL:	return "__cpowieee128";
+    case BUILT_IN_CPROJL:	return "__cprojieee128";
+    case BUILT_IN_CREALL:	return "__crealieee128";
+    case BUILT_IN_CSINHL:	return "__csinhieee128";
+    case BUILT_IN_CSINL:	return "__csinieee128";
+    case BUILT_IN_CSQRTL:	return "__csqrtieee128";
+    case BUILT_IN_CTANHL:	return "__ctanhieee128";
+    case BUILT_IN_CTANL:	return "__ctanieee128";
+    case BUILT_IN_DREML:	return "__remainderieee128";
+    case BUILT_IN_ERFCL:	return "__erfcieee128";
+    case BUILT_IN_ERFL:		return "__erfieee128";
+    case BUILT_IN_EXP10L:	return "__exp10ieee128";
+    case BUILT_IN_EXP2L:	return "__exp2ieee128";
+    case BUILT_IN_EXPL:		return "__expieee128";
+    case BUILT_IN_EXPM1L:	return "__expm1ieee128";
+    case BUILT_IN_FABSL:	return "__fabsieee128";
+    case BUILT_IN_FDIML:	return "__fdimieee128";
+    case BUILT_IN_FINITEL:	return "__finiteieee128";
+    case BUILT_IN_FLOORL:	return "__floorieee128";
+    case BUILT_IN_FMAL:		return "__fmaieee128";
+    case BUILT_IN_FMAXL:	return "__fmaxieee128";
+    case BUILT_IN_FMINL:	return "__fminieee128";
+    case BUILT_IN_FMODL:	return "__fmodieee128";
+    case BUILT_IN_FPRINTF:	return "__fprintfieee128";
+    case BUILT_IN_FREXPL:	return "__frexpieee128";
+    case BUILT_IN_FSCANF:	return "__isoc99_fscanfieee128";
+    case BUILT_IN_GAMMAL:	return "__lgammaieee128";
+    case BUILT_IN_GAMMAL_R:	return "__lgammaieee128_r";
+    case BUILT_IN_HYPOTL:	return "__hypotieee128";
+    case BUILT_IN_ILOGBL:	return "__ilogbieee128";
+    case BUILT_IN_IROUNDL:	return "__iroundieee128";
+    case BUILT_IN_ISINFL:	return "__isinfieee128";
+    case BUILT_IN_ISNANL:	return "__isnanieee128";
+    case BUILT_IN_J0L:		return "__j0ieee128";
+    case BUILT_IN_J1L:		return "__j1ieee128";
+    case BUILT_IN_JNL:		return "__jnieee128";
+    case BUILT_IN_LDEXPL:	return "__ldexpieee128";
+    case BUILT_IN_LGAMMAL:	return "__lgammaieee128";
+    case BUILT_IN_LGAMMAL_R:	return "__lgammaieee128_r";
+    case BUILT_IN_LLRINTL:	return "__llrintieee128";
+    case BUILT_IN_LLROUNDL:	return "__llroundieee128";
+    case BUILT_IN_LOG10L:	return "__log10ieee128";
+    case BUILT_IN_LOG1PL:	return "__log1pieee128";
+    case BUILT_IN_LOG2L:	return "__log2ieee128";
+    case BUILT_IN_LOGBL:	return "__logbieee128";
+    case BUILT_IN_LOGL:		return "__logieee128";
+    case BUILT_IN_LRINTL:	return "__lrintieee128";
+    case BUILT_IN_LROUNDL:	return "__lroundieee128";
+    case BUILT_IN_MODFL:	return "__modfieee128";
+    case BUILT_IN_NEARBYINTL:	return "__nearbyintieee128";
+    case BUILT_IN_NEXTAFTERL:	return "__nextafterieee128";
+    case BUILT_IN_NEXTTOWARD:	return "__nexttoward_to_ieee128";
+    case BUILT_IN_NEXTTOWARDF:	return "__nexttowardf_to_ieee128";
+    case BUILT_IN_NEXTTOWARDL:	return "__nexttowardieee128";
+    case BUILT_IN_POW10L:	return "__exp10ieee128";
+    case BUILT_IN_POWIL:	return "__powiieee128";
+    case BUILT_IN_POWL:		return "__powieee128";
+    case BUILT_IN_PRINTF:	return "__printfieee128";
+    case BUILT_IN_REMAINDERL:	return "__remainderieee128";
+    case BUILT_IN_REMQUOL:	return "__remquoieee128";
+    case BUILT_IN_RINTL:	return "__rintieee128";
+    case BUILT_IN_ROUNDEVENL:	return "__roundevenieee128";
+    case BUILT_IN_ROUNDL:	return "__roundieee128";
+    case BUILT_IN_SCALBL:	return "__scalbieee128";
+    case BUILT_IN_SCALBLNL:	return "__scalblnieee128";
+    case BUILT_IN_SCALBNL:	return "__scalbnieee128";
+    case BUILT_IN_SCANF:	return "__isoc99_scanfieee128";
+    case BUILT_IN_SIGNBITL:	return "__signbitieee128";
+    case BUILT_IN_SIGNIFICANDL:	return "__significandieee128";
+    case BUILT_IN_SINCOSL:	return "__sincosieee128";
+    case BUILT_IN_SINHL:	return "__sinhieee128";
+    case BUILT_IN_SINL:		return "__sinieee128";
+    case BUILT_IN_SNPRINTF:	return "__snprintfieee128";
+    case BUILT_IN_SPRINTF:	return "__sprintfieee128";
+    case BUILT_IN_SQRTL:	return "__sqrtieee128";
+    case BUILT_IN_SSCANF:	return "__isoc99_sscanfieee128";
+    case BUILT_IN_TANHL:	return "__tanhieee128";
+    case BUILT_IN_TANL:		return "__tanieee128";
+    case BUILT_IN_TGAMMAL:	return "__tgammaieee128";
+    case BUILT_IN_TRUNCL:	return "__truncieee128";
+    case BUILT_IN_VFPRINTF:	return "__vfprintfieee128";
+    case BUILT_IN_VFSCANF:	return "__isoc99_vfscanfieee128";
+    case BUILT_IN_VPRINTF:	return "__vprintfieee128";
+    case BUILT_IN_VSCANF:	return "__isoc99_vscanfieee128";
+    case BUILT_IN_VSNPRINTF:	return "__vsnprintfieee128";
+    case BUILT_IN_VSPRINTF:	return "__vsprintfieee128";
+    case BUILT_IN_VSSCANF:	return "__isoc99_vsscanfieee128";
+    case BUILT_IN_Y0L:		return "__y0ieee128";
+    case BUILT_IN_Y1L:		return "__y1ieee128";
+    case BUILT_IN_YNL:		return "__ynieee128";
+    }
+}
+
+#if ENABLE_ASSERT_CHECKING
+/* Return true if a built-in function returns or passes a long double type.  */
+static bool
+built_in_uses_long_double (tree decl)
+{
+  tree type = TREE_TYPE (decl);
+  machine_mode ret_mode = TYPE_MODE (type);
+
+  /* See if the function returns a long double type.  */
+  if (ret_mode == TFmode || ret_mode == TCmode)
+    return true;
+
+  function_args_iterator args_iter;
+  tree arg;
+
+  /* See if the function passes a long double type.  */
+  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
+    {
+      machine_mode arg_mode = TYPE_MODE (arg);
+      if (arg_mode == TFmode || arg_mode == TCmode)
+	return true;
+    }
+
+  return false;
+}
+#endif
+
 /* On 64-bit Linux and Freebsd systems, possibly switch the long double library
    function names from <foo>l to <foo>f128 if the default long double type is
    IEEE 128-bit.  Typically, with the C and C++ languages, the standard math.h
@@ -27115,51 +27274,52 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
 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);
-
-      if (name[len - 1] == 'l')
+      const char *ieee_name = ieee128_builtin_name (DECL_FUNCTION_CODE (decl));
+      tree id_orig = id;
+
+      if (ieee_name)
+	id = get_identifier (ieee_name);
+
+      /* If we have checking enabled, see if any additional long double built-in
+	 functions were added.  We check for *printf functions, *scanf
+	 functions, and *l and *l_r functions that have explicit long double or
+	 Complex long double arguments or returns.  If the warning is printed,
+	 you need to update ieee128_builtin_name with the new built-in
+	 functions.  */
+#if ENABLE_ASSERT_CHECKING
+      else
 	{
-	  bool uses_ieee128_p = false;
-	  tree type = TREE_TYPE (decl);
-	  machine_mode ret_mode = TYPE_MODE (type);
+	  size_t len = IDENTIFIER_LENGTH (id);
+	  size_t printf_len = strlen ("printf");
+	  size_t scanf_len = strlen ("scanf");
+	  size_t l_r_len = strlen ("l_r");
 
-	  /* 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;
+	  if (len >= printf_len
+	      && strcmp (name + len - printf_len, "printf") == 0)
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
 
-	      /* See if the function passes a IEEE 128-bit floating point type
-		 or complex type.  */
-	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
-		{
-		  machine_mode arg_mode = TYPE_MODE (arg);
-		  if (arg_mode == TFmode || arg_mode == TCmode)
-		    {
-		      uses_ieee128_p = true;
-		      break;
-		    }
-		}
-	    }
+	  else if (len >= scanf_len
+		   && strcmp (name + len - scanf_len, "scanf") == 0)
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
 
-	  /* 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);
-	    }
+	  else if (name[len - 1] == 'l' && built_in_uses_long_double (decl))
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
+
+	  else if (len >= l_r_len
+		   && strcmp (name + len - l_r_len, "l_r") == 0
+		   && built_in_uses_long_double (decl))
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
 	}
+#endif
+
+      if (id != id_orig && TARGET_DEBUG_BUILTIN)
+	fprintf (stderr, "Map %s => %s\n", name, IDENTIFIER_POINTER (id));
     }
 
   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}         } } */


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

* [gcc(refs/users/meissner/heads/work030)] PowerPC: Map IEEE 128-bit long double built-in functions.
@ 2020-12-17 22:10 Michael Meissner
  0 siblings, 0 replies; 3+ messages in thread
From: Michael Meissner @ 2020-12-17 22:10 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7a92eb48752ef010d34f3c9eb1c9f8dc17a48307

commit 7a92eb48752ef010d34f3c9eb1c9f8dc17a48307
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Thu Dec 17 17:10:17 2020 -0500

    PowerPC: Map IEEE 128-bit long double built-in functions.
    
    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>
    
    November 19th, 2020:
    Message-ID: <20201119235814.GA322@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.
    
    If 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.
    
    gcc/
    2020-12-17  Michael Meissner  <meissner@linux.ibm.com>
    
            * config/rs6000/rs6000.c (ieee128_builtin_name): New function.
            (built_in_uses_long_double): New function.
            (rs6000_mangle_decl_assembler_name): Update support for mapping built-in
            function names for long double built-in functions if long double is
            IEEE 128-bit to catch all of the built-in functions that take or
            return long double arguments.
    
    gcc/testsuite/
    2020-12-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.

Diff:
---
 gcc/config/rs6000/rs6000.c                         | 231 +++++++++--
 .../gcc.target/powerpc/float128-longdouble-math.c  | 442 +++++++++++++++++++++
 .../gcc.target/powerpc/float128-longdouble-stdio.c |  36 ++
 gcc/testsuite/gcc.target/powerpc/float128-math.c   |  16 +-
 4 files changed, 680 insertions(+), 45 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 72f5d4250b5..9a368c341d1 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -27095,6 +27095,162 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
 #endif
 
 \f
+/* If long double uses the IEEE 128-bit representation, return the name used
+   within GLIBC for the IEEE 128-bit long double built-in, instead of the
+   default IBM 128-bit long double built-in.  Or return NULL if the built-in
+   function does not use long double.  */
+
+static const char *
+ieee128_builtin_name (built_in_function fn)
+{
+  switch (fn)
+    {
+    default:			return NULL;
+    case BUILT_IN_ACOSHL:	return "__acoshieee128";
+    case BUILT_IN_ACOSL:	return "__acosieee128";
+    case BUILT_IN_ASINHL:	return "__asinhieee128";
+    case BUILT_IN_ASINL:	return "__asinieee128";
+    case BUILT_IN_ATAN2L:	return "__atan2ieee128";
+    case BUILT_IN_ATANHL:	return "__atanhieee128";
+    case BUILT_IN_ATANL:	return "__atanieee128";
+    case BUILT_IN_CABSL:	return "__cabsieee128";
+    case BUILT_IN_CACOSHL:	return "__cacoshieee128";
+    case BUILT_IN_CACOSL:	return "__cacosieee128";
+    case BUILT_IN_CARGL:	return "__cargieee128";
+    case BUILT_IN_CASINHL:	return "__casinhieee128";
+    case BUILT_IN_CASINL:	return "__casinieee128";
+    case BUILT_IN_CATANHL:	return "__catanhieee128";
+    case BUILT_IN_CATANL:	return "__catanieee128";
+    case BUILT_IN_CBRTL:	return "__cbrtieee128";
+    case BUILT_IN_CCOSHL:	return "__ccoshieee128";
+    case BUILT_IN_CCOSL:	return "__ccosieee128";
+    case BUILT_IN_CEILL:	return "__ceilieee128";
+    case BUILT_IN_CEXPL:	return "__cexpieee128";
+    case BUILT_IN_CIMAGL:	return "__cimagieee128";
+    case BUILT_IN_CLOG10L:	return "__clog10ieee128";
+    case BUILT_IN_CLOGL:	return "__clogieee128";
+    case BUILT_IN_CONJL:	return "__conjieee128";
+    case BUILT_IN_COPYSIGNL:	return "__copysignieee128";
+    case BUILT_IN_COSHL:	return "__coshieee128";
+    case BUILT_IN_COSL:		return "__cosieee128";
+    case BUILT_IN_CPOWL:	return "__cpowieee128";
+    case BUILT_IN_CPROJL:	return "__cprojieee128";
+    case BUILT_IN_CREALL:	return "__crealieee128";
+    case BUILT_IN_CSINHL:	return "__csinhieee128";
+    case BUILT_IN_CSINL:	return "__csinieee128";
+    case BUILT_IN_CSQRTL:	return "__csqrtieee128";
+    case BUILT_IN_CTANHL:	return "__ctanhieee128";
+    case BUILT_IN_CTANL:	return "__ctanieee128";
+    case BUILT_IN_DREML:	return "__remainderieee128";
+    case BUILT_IN_ERFCL:	return "__erfcieee128";
+    case BUILT_IN_ERFL:		return "__erfieee128";
+    case BUILT_IN_EXP10L:	return "__exp10ieee128";
+    case BUILT_IN_EXP2L:	return "__exp2ieee128";
+    case BUILT_IN_EXPL:		return "__expieee128";
+    case BUILT_IN_EXPM1L:	return "__expm1ieee128";
+    case BUILT_IN_FABSL:	return "__fabsieee128";
+    case BUILT_IN_FDIML:	return "__fdimieee128";
+    case BUILT_IN_FINITEL:	return "__finiteieee128";
+    case BUILT_IN_FLOORL:	return "__floorieee128";
+    case BUILT_IN_FMAL:		return "__fmaieee128";
+    case BUILT_IN_FMAXL:	return "__fmaxieee128";
+    case BUILT_IN_FMINL:	return "__fminieee128";
+    case BUILT_IN_FMODL:	return "__fmodieee128";
+    case BUILT_IN_FPRINTF:	return "__fprintfieee128";
+    case BUILT_IN_FREXPL:	return "__frexpieee128";
+    case BUILT_IN_FSCANF:	return "__isoc99_fscanfieee128";
+    case BUILT_IN_GAMMAL:	return "__lgammaieee128";
+    case BUILT_IN_GAMMAL_R:	return "__lgammaieee128_r";
+    case BUILT_IN_HYPOTL:	return "__hypotieee128";
+    case BUILT_IN_ILOGBL:	return "__ilogbieee128";
+    case BUILT_IN_ISINFL:	return "__isinfieee128";
+    case BUILT_IN_ISNANL:	return "__isnanieee128";
+    case BUILT_IN_J0L:		return "__j0ieee128";
+    case BUILT_IN_J1L:		return "__j1ieee128";
+    case BUILT_IN_JNL:		return "__jnieee128";
+    case BUILT_IN_LDEXPL:	return "__ldexpieee128";
+    case BUILT_IN_LGAMMAL:	return "__lgammaieee128";
+    case BUILT_IN_LGAMMAL_R:	return "__lgammaieee128_r";
+    case BUILT_IN_LLRINTL:	return "__llrintieee128";
+    case BUILT_IN_LLROUNDL:	return "__llroundieee128";
+    case BUILT_IN_LOG10L:	return "__log10ieee128";
+    case BUILT_IN_LOG1PL:	return "__log1pieee128";
+    case BUILT_IN_LOG2L:	return "__log2ieee128";
+    case BUILT_IN_LOGBL:	return "__logbieee128";
+    case BUILT_IN_LOGL:		return "__logieee128";
+    case BUILT_IN_LRINTL:	return "__lrintieee128";
+    case BUILT_IN_LROUNDL:	return "__lroundieee128";
+    case BUILT_IN_MODFL:	return "__modfieee128";
+    case BUILT_IN_NEARBYINTL:	return "__nearbyintieee128";
+    case BUILT_IN_NEXTAFTERL:	return "__nextafterieee128";
+    case BUILT_IN_NEXTTOWARD:	return "__nexttoward_to_ieee128";
+    case BUILT_IN_NEXTTOWARDF:	return "__nexttowardf_to_ieee128";
+    case BUILT_IN_NEXTTOWARDL:	return "__nexttowardieee128";
+    case BUILT_IN_POW10L:	return "__exp10ieee128";
+    case BUILT_IN_POWL:		return "__powieee128";
+    case BUILT_IN_PRINTF:	return "__printfieee128";
+    case BUILT_IN_REMAINDERL:	return "__remainderieee128";
+    case BUILT_IN_REMQUOL:	return "__remquoieee128";
+    case BUILT_IN_RINTL:	return "__rintieee128";
+    case BUILT_IN_ROUNDEVENL:	return "__roundevenieee128";
+    case BUILT_IN_ROUNDL:	return "__roundieee128";
+    case BUILT_IN_SCALBL:	return "__scalbieee128";
+    case BUILT_IN_SCALBLNL:	return "__scalblnieee128";
+    case BUILT_IN_SCALBNL:	return "__scalbnieee128";
+    case BUILT_IN_SCANF:	return "__isoc99_scanfieee128";
+    case BUILT_IN_SIGNBITL:	return "__signbitieee128";
+    case BUILT_IN_SIGNIFICANDL:	return "__significandieee128";
+    case BUILT_IN_SINCOSL:	return "__sincosieee128";
+    case BUILT_IN_SINHL:	return "__sinhieee128";
+    case BUILT_IN_SINL:		return "__sinieee128";
+    case BUILT_IN_SNPRINTF:	return "__snprintfieee128";
+    case BUILT_IN_SPRINTF:	return "__sprintfieee128";
+    case BUILT_IN_SQRTL:	return "__sqrtieee128";
+    case BUILT_IN_SSCANF:	return "__isoc99_sscanfieee128";
+    case BUILT_IN_TANHL:	return "__tanhieee128";
+    case BUILT_IN_TANL:		return "__tanieee128";
+    case BUILT_IN_TGAMMAL:	return "__tgammaieee128";
+    case BUILT_IN_TRUNCL:	return "__truncieee128";
+    case BUILT_IN_VFPRINTF:	return "__vfprintfieee128";
+    case BUILT_IN_VFSCANF:	return "__isoc99_vfscanfieee128";
+    case BUILT_IN_VPRINTF:	return "__vprintfieee128";
+    case BUILT_IN_VSCANF:	return "__isoc99_vscanfieee128";
+    case BUILT_IN_VSNPRINTF:	return "__vsnprintfieee128";
+    case BUILT_IN_VSPRINTF:	return "__vsprintfieee128";
+    case BUILT_IN_VSSCANF:	return "__isoc99_vsscanfieee128";
+    case BUILT_IN_Y0L:		return "__y0ieee128";
+    case BUILT_IN_Y1L:		return "__y1ieee128";
+    case BUILT_IN_YNL:		return "__ynieee128";
+    }
+}
+
+#if ENABLE_ASSERT_CHECKING
+/* Return true if a built-in function returns or passes a long double type.  */
+static bool
+built_in_uses_long_double (tree decl)
+{
+  tree type = TREE_TYPE (decl);
+  machine_mode ret_mode = TYPE_MODE (type);
+
+  /* See if the function returns a long double type.  */
+  if (ret_mode == TFmode || ret_mode == TCmode)
+    return true;
+
+  function_args_iterator args_iter;
+  tree arg;
+
+  /* See if the function passes a long double type.  */
+  FOREACH_FUNCTION_ARGS (type, arg, args_iter)
+    {
+      machine_mode arg_mode = TYPE_MODE (arg);
+      if (arg_mode == TFmode || arg_mode == TCmode)
+	return true;
+    }
+
+  return false;
+}
+#endif
+
 /* On 64-bit Linux and Freebsd systems, possibly switch the long double library
    function names from <foo>l to <foo>f128 if the default long double type is
    IEEE 128-bit.  Typically, with the C and C++ languages, the standard math.h
@@ -27115,51 +27271,52 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
 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);
-
-      if (name[len - 1] == 'l')
+      const char *ieee_name = ieee128_builtin_name (DECL_FUNCTION_CODE (decl));
+      tree id_orig = id;
+
+      if (ieee_name)
+	id = get_identifier (ieee_name);
+
+      /* If we have checking enabled, see if any additional long double built-in
+	 functions were added.  We check for *printf functions, *scanf
+	 functions, and *l/*l_r functions that have explicit long double or
+	 Complex long double arguments or returns.  If the warning is printed,
+	 you need to update ieee128_builtin_name with the new built-in
+	 functions.  */
+#if ENABLE_ASSERT_CHECKING
+      else
 	{
-	  bool uses_ieee128_p = false;
-	  tree type = TREE_TYPE (decl);
-	  machine_mode ret_mode = TYPE_MODE (type);
+	  size_t len = IDENTIFIER_LENGTH (id);
+	  size_t printf_len = strlen ("printf");
+	  size_t scanf_len = strlen ("scanf");
+	  size_t l_r_len = strlen ("l_r");
 
-	  /* 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;
+	  if (len >= printf_len
+	      && strcmp (name + len - printf_len, "printf") == 0)
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
 
-	      /* See if the function passes a IEEE 128-bit floating point type
-		 or complex type.  */
-	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
-		{
-		  machine_mode arg_mode = TYPE_MODE (arg);
-		  if (arg_mode == TFmode || arg_mode == TCmode)
-		    {
-		      uses_ieee128_p = true;
-		      break;
-		    }
-		}
-	    }
+	  else if (len >= scanf_len
+		   && strcmp (name + len - scanf_len, "scanf") == 0)
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
 
-	  /* 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);
-	    }
+	  else if (name[len - 1] == 'l' && built_in_uses_long_double (decl))
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
+
+	  else if (len >= l_r_len
+		   && strcmp (name + len - l_r_len, "l_r") == 0
+		   && built_in_uses_long_double (decl))
+	    warning (0, "No IEEE 128-bit %qs built-in function", name);
 	}
+#endif
+
+      if (id != id_orig && TARGET_DEBUG_BUILTIN)
+	fprintf (stderr, "Map %s => %s\n", name, IDENTIFIER_POINTER (id));
     }
 
   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}         } } */


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

* [gcc(refs/users/meissner/heads/work030)] PowerPC: Map IEEE 128-bit long double built-in functions.
@ 2020-12-17  5:45 Michael Meissner
  0 siblings, 0 replies; 3+ messages in thread
From: Michael Meissner @ 2020-12-17  5:45 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:40d5c9767d2a6877f214da66b0885e9e6a5afc8d

commit 40d5c9767d2a6877f214da66b0885e9e6a5afc8d
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Thu Dec 17 00:43:54 2020 -0500

    PowerPC: Map IEEE 128-bit long double built-in functions.
    
    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.
    
    gcc/
    2020-12-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-12-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.

Diff:
---
 gcc/config/rs6000/rs6000.c                         | 135 +++++--
 .../gcc.target/powerpc/float128-longdouble-math.c  | 442 +++++++++++++++++++++
 .../gcc.target/powerpc/float128-longdouble-stdio.c |  36 ++
 gcc/testsuite/gcc.target/powerpc/float128-math.c   |  16 +-
 4 files changed, 589 insertions(+), 40 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 9d172b1de89..e8e52121721 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -27104,57 +27104,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}         } } */


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

end of thread, other threads:[~2020-12-18  1:26 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-18  1:26 [gcc(refs/users/meissner/heads/work030)] PowerPC: Map IEEE 128-bit long double built-in functions Michael Meissner
  -- strict thread matches above, loose matches on Subject: below --
2020-12-17 22:10 Michael Meissner
2020-12-17  5:45 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).