diff mbox series

PowerPC: Map IEEE 128-bit long double built-ins.

Message ID 20210114165919.GA1094@ibm-toto.the-meissners.org
State New
Headers show
Series PowerPC: Map IEEE 128-bit long double built-ins. | expand

Commit Message

Michael Meissner Jan. 14, 2021, 4:59 p.m. UTC
From 78435dee177447080434cdc08fc76b1029c7f576 Mon Sep 17 00:00:00 2001
From: Michael Meissner <meissner@linux.ibm.com>
Date: Wed, 13 Jan 2021 21:47:03 -0500
Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.

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.

I have tested this patch by doing builds, bootstraps, and make check with 3
builds on a power9 little endian server:

    *	Build one used the default long double being IBM 128-bit;
    *	Build two set the long double default to IEEE 128-bit; (and)
    *	Build three set the long double default to 64-bit.

The compilers built fine providing I recompiled gmp, mpc, and mpfr with the
appropriate long double options.  There were a few differences in the test
suite runs that will be addressed in later patches, but over all it works
well.  This patch is required to be able to build a toolchain where the default
long double is IEEE 128-bit.  Can I check this patch into the master branch for
GCC 11?

gcc/
2021-01-14  Michael Meissner  <meissner@linux.ibm.com>

	* config/rs6000/rs6000.c (ieee128_builtin_name): New function.
	(built_in_uses_long_double): New function.
	(identifier_ends_in_suffix): 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/
2021-01-14  Michael Meissner  <meissner@linux.ibm.com>

	* gcc.target/powerpc/float128-longdouble-math.c: New test.
	* gcc.target/powerpc/float128-longdouble-stdio.c: New test.
	* gcc.target/powerpc/float128-math.c: Adjust test for new name
	being generated.  Add support for running test on power10.  Add
	support for running if long double defaults to 64-bits.
---
 gcc/config/rs6000/rs6000.c                    | 239 ++++++++--
 .../powerpc/float128-longdouble-math.c        | 442 ++++++++++++++++++
 .../powerpc/float128-longdouble-stdio.c       |  36 ++
 .../gcc.target/powerpc/float128-math.c        |  16 +-
 4 files changed, 694 insertions(+), 39 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c

Comments

Segher Boessenkool Jan. 15, 2021, 9:43 p.m. UTC | #1
Hi!

On Thu, Jan 14, 2021 at 11:59:19AM -0500, Michael Meissner wrote:
> >From 78435dee177447080434cdc08fc76b1029c7f576 Mon Sep 17 00:00:00 2001
> From: Michael Meissner <meissner@linux.ibm.com>
> Date: Wed, 13 Jan 2021 21:47:03 -0500
> Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.
> 
> This patch replaces patches previously submitted:

What did you change after I approved it?


Segher
Michael Meissner Jan. 19, 2021, 5:24 p.m. UTC | #2
On Fri, Jan 15, 2021 at 03:43:13PM -0600, Segher Boessenkool wrote:
> Hi!
> 
> On Thu, Jan 14, 2021 at 11:59:19AM -0500, Michael Meissner wrote:
> > >From 78435dee177447080434cdc08fc76b1029c7f576 Mon Sep 17 00:00:00 2001
> > From: Michael Meissner <meissner@linux.ibm.com>
> > Date: Wed, 13 Jan 2021 21:47:03 -0500
> > Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.
> > 
> > This patch replaces patches previously submitted:
> 
> What did you change after I approved it?

You grumbled about the way I converted the names from the current name to the
IEEE 128-bit name as being unclear.

1) I moved the table of known mappings from within a function to a separate
function, and I populated the switch statement with all of the current names.

2) I moved the code that looks at a built-in function's arguments and returns
whether it uses long double to a separate function rather than being buried
within a larger function.

3) I changed the code for case we we didn't provide a name (i.e. new built-ins)
to hopefully be clearer on the conversion.
Michael Meissner Jan. 26, 2021, 11:39 p.m. UTC | #3
Ping https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563496.html

| Date: Thu, 14 Jan 2021 11:59:19 -0500
| Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.
| Message-ID: <20210114165919.GA1094@ibm-toto.the-meissners.org>

As I've said in the past, this is the most important patch of the IEEE 128-bit
patches.  What do I need to do to be able to commit this patch ASAP?  Or what
changes do I need to make?

I posted the patch on January 14th.  You asked what had changed in the patch,
and I replied on the 19th:

| You grumbled about the way I converted the names from the current name to the
| IEEE 128-bit name as being unclear.
|
| 1) I moved the table of known mappings from within a function to a separate
| function, and I populated the switch statement with all of the current names.
|
| 2) I moved the code that looks at a built-in function's arguments and returns
| whether it uses long double to a separate function rather than being buried
| within a larger function.
|
| 3) I changed the code for case we we didn't provide a name (i.e. new built-ins)
| to hopefully be clearer on the conversion.
will schmidt Jan. 27, 2021, 7:06 p.m. UTC | #4
On Thu, 2021-01-14 at 11:59 -0500, Michael Meissner via Gcc-patches wrote:
> From 78435dee177447080434cdc08fc76b1029c7f576 Mon Sep 17 00:00:00 2001
> From: Michael Meissner <meissner@linux.ibm.com>
> Date: Wed, 13 Jan 2021 21:47:03 -0500
> Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.
> 
> 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>


Subject and date should be sufficient _if_ having the old versions
of the patchs are necessary to review the latest version of the
patch.  Which ideally is not the case.


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

ok.

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

Does the fortran compiler currently use the wrong name? (pr?)

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

This appears to be  the rs6000_mangle_decl_assembler_name() function, which
also maps <name>l_r to <name>ieee128_r, and looks like some additional special
handling for printf and scanf.  


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


> 
> I have tested this patch by doing builds, bootstraps, and make check with 3
> builds on a power9 little endian server:
> 
>     *	Build one used the default long double being IBM 128-bit;
>     *	Build two set the long double default to IEEE 128-bit; (and)
>     *	Build three set the long double default to 64-bit.
> 

ok

> The compilers built fine providing I recompiled gmp, mpc, and mpfr with the
> appropriate long double options.

Presumably the build is otherwise broken... 
Does that mean more than invoking download_preqrequisites as part of the
build?   If there are specific options required during configure/build of
those packages, they should be called out.

> There were a few differences in the test
> suite runs that will be addressed in later patches, but over all it works
> well.

Presumably minimal. :-)


>       This patch is required to be able to build a toolchain where the default
> long double is IEEE 128-bit. 

Ok.   Could lead the patch description with this,.  I imagine this is
just one of several patches that are still required towrards that goal.



>  Can I check this patch into the master branch for
> GCC 11?





> 
> gcc/
> 2021-01-14  Michael Meissner  <meissner@linux.ibm.com>
> 
> 	* config/rs6000/rs6000.c (ieee128_builtin_name): New function.
> 	(built_in_uses_long_double): New function.
> 	(identifier_ends_in_suffix): 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/
> 2021-01-14  Michael Meissner  <meissner@linux.ibm.com>
> 
> 	* gcc.target/powerpc/float128-longdouble-math.c: New test.
> 	* gcc.target/powerpc/float128-longdouble-stdio.c: New test.
> 	* gcc.target/powerpc/float128-math.c: Adjust test for new name
> 	being generated.  Add support for running test on power10.  Add
> 	support for running if long double defaults to 64-bits.
> ---
>  gcc/config/rs6000/rs6000.c                    | 239 ++++++++--
>  .../powerpc/float128-longdouble-math.c        | 442 ++++++++++++++++++
>  .../powerpc/float128-longdouble-stdio.c       |  36 ++
>  .../gcc.target/powerpc/float128-math.c        |  16 +-
>  4 files changed, 694 insertions(+), 39 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> 
> diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
> index 6f48dd6566d..282703b9715 100644
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -27100,6 +27100,172 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
>  #endif
> 
>  
> +/* 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.  */


This doesn't have any checks for mode, this only returns the name used
for the IEEE built-in.   (so, you can drop the "If .. representation, "
and "instead of .." built-in" portions of that comment.)
Does the
default case occur naturally?  May be worth a debug-builtin printf/info
statement there.
(Actually I see there is a debug_builtin info blurb in
the caller of this function, so probably OK there.. )

> +
> +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";
> +    }
> +}
> +
> +/* 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;
> +}

ok


> +
> +/* Return true if an identifier ends in a specific suffix.  */
> +static bool
> +identifier_ends_in_suffix (tree id, const char *suffix)
> +{
> +  size_t suffix_len = strlen (suffix);
> +  size_t id_len = IDENTIFIER_LENGTH (id);
> +
> +  return (id_len > suffix_len
> +	  && strcmp (IDENTIFIER_POINTER (id), suffix) == 0);
> +}
> +


ok

> +
>  /* 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
> @@ -27120,51 +27286,62 @@ 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);
> +      const char *ieee_name = ieee128_builtin_name (DECL_FUNCTION_CODE (decl));
> +      tree id_orig = id;
> 
> -      if (name[len - 1] == 'l')
> +      if (ieee_name)
> +	id = get_identifier (ieee_name);
> +
> +      /* If we did not get an IEEE 128-bit built-in name, check to see if a new
> +	 math built-in function that is passed or returns long double arguments.
> +	 If it ends in 'l' or 'l_r', convert the name the GLIBC IEEE 128-bit
> +	 built-in name.  Also convert any printf/scanf functions that were not
> +	 handled.  */
> +      if (!ieee_name)
>  	{
> -	  bool uses_ieee128_p = false;
> -	  tree type = TREE_TYPE (decl);
> -	  machine_mode ret_mode = TYPE_MODE (type);
> +	  const char *name = IDENTIFIER_POINTER (id);
> +	  char *new_name = NULL;
> +	  size_t len = IDENTIFIER_LENGTH (id);
> 
> -	  /* 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
> +	  if (built_in_uses_long_double (decl))
>  	    {
> -	      function_args_iterator args_iter;
> -	      tree arg;
> +	      if (identifier_ends_in_suffix (id, "l"))
> +		{
> +		  int len_m1 = len - 1;		/* eliminate 'l'.  */
> +		  new_name = xasprintf ("__%.*sieee128", len_m1, name);
> +		}
> 
> -	      /* See if the function passes a IEEE 128-bit floating point type
> -		 or complex type.  */
> -	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
> +	      else if (identifier_ends_in_suffix (id, "l_r"))
>  		{
> -		  machine_mode arg_mode = TYPE_MODE (arg);
> -		  if (arg_mode == TFmode || arg_mode == TCmode)
> -		    {
> -		      uses_ieee128_p = true;
> -		      break;
> -		    }
> +		  int len_m3 = len - 3;		/* eliminate 'l_r'.  */
> +		  new_name = xasprintf ("__%.*sieee128_r", len_m3, name);
>  		}
>  	    }
> 
> -	  /* If we passed or returned an IEEE 128-bit floating point type,
> -	     change the name.  */
> -	  if (uses_ieee128_p)
> +	  /* Check that no new printf/scanf functions were added.  */
> +	  else if (identifier_ends_in_suffix (id, "printf"))
> +	    new_name = xasprintf ("__%sieee128", name);
> +
> +	  else if (identifier_ends_in_suffix (id, "scanf"))
> +	    new_name = xasprintf ("__isoc99_%sieee128", name);
> +
> +	  if (new_name)
>  	    {
> -	      char *name2 = (char *) alloca (len + 4);
> -	      memcpy (name2, name, len - 1);
> -	      strcpy (name2 + len - 1, "f128");
> -	      id = get_identifier (name2);
> +	      id = get_identifier (new_name);
> +	      free ((void *)new_name);
>  	    }
>  	}
> +
> +      if (id != id_orig && TARGET_DEBUG_BUILTIN)
> +	fprintf (stderr, "Map %s => %s%s\n",
> +		 IDENTIFIER_POINTER (id_orig),
> +		 IDENTIFIER_POINTER (id),
> +		 ieee_name != NULL ? "" : " (not in table)");
>      }
> 
>    return id;
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> new file mode 100644
> index 00000000000..07934bb7357
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> @@ -0,0 +1,442 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-options "-mdejagnu-cpu=power9 -O2 -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble" } */
> +
> +/* Test if switching long double to IEEE 128-bit maps all of the math built-in
> +   function names correctly.  We leave off the \M in matching the calls, so
> +   power10 will match using bl foo@notoc.  */
> +
> +#ifdef DO_FUNC
> +#define BUILTIN1(FUNC, ARG1)             FUNC (ARG1)
> +#define BUILTIN2(FUNC, ARG1, ARG2)       FUNC (ARG1, ARG2)
> +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) FUNC (ARG1, ARG2, ARG3)
> +
> +#else
> +#define BUILTIN1(FUNC, ARG1)             __builtin_ ## FUNC (ARG1)
> +#define BUILTIN2(FUNC, ARG1, ARG2)       __builtin_ ## FUNC (ARG1, ARG2)
> +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) __builtin_ ## FUNC (ARG1, ARG2, ARG3)
> +#endif
> +
> +/* Built-in functions that returns a long double and take one long double
> +   argument.  */
> +
> +void
> +return_ld_arg_ld (long double *p,
> +		  long double *q)
> +{
> +  /* { dg-final { scan-assembler {\mbl __acoshieee128} } }  */
> +  *p++ = BUILTIN1 (acoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __acosieee128} } }  */
> +  *p++ = BUILTIN1 (acosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __asinhieee128} } }  */
> +  *p++ = BUILTIN1 (asinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __asinieee128} } }  */
> +  *p++ = BUILTIN1 (asinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __atanhieee128} } }  */
> +  *p++ = BUILTIN1 (atanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __atanieee128} } }  */
> +  *p++ = BUILTIN1 (atanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __cbrtieee128} } }  */
> +  *p++ = BUILTIN1 (cbrtl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2} } }  */
> +  *p++ = BUILTIN1 (ceill, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __coshieee128} } }  */
> +  *p++ = BUILTIN1 (coshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __cosieee128} } }  */
> +  *p++ = BUILTIN1 (cosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __erfcieee128} } }  */
> +  *p++ = BUILTIN1 (erfcl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __erfieee128} } }  */
> +  *p++ = BUILTIN1 (erfl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __exp10ieee128} } }  */
> +  *p++ = BUILTIN1 (exp10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __exp2ieee128} } }  */
> +  *p++ = BUILTIN1 (exp2l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __expieee128} } }  */
> +  *p++ = BUILTIN1 (expl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __expm1ieee128} } }  */
> +  *p++ = BUILTIN1 (expm1l, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsabsqp} } }  */
> +  *p++ = BUILTIN1 (fabsl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3} } }  */
> +  *p++ = BUILTIN1 (floorl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __lgammaieee128} } }  */
> +  *p++ = BUILTIN1 (gammal, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __j0ieee128} } }  */
> +  *p++ = BUILTIN1 (j0l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __j1ieee128} } }  */
> +  *p++ = BUILTIN1 (j1l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __log10ieee128} } }  */
> +  *p++ = BUILTIN1 (log10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __log1pieee128} } }  */
> +  *p++ = BUILTIN1 (log1pl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __log2ieee128} } }  */
> +  *p++ = BUILTIN1 (log2l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __logbieee128} } }  */
> +  *p++ = BUILTIN1 (logbl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __logieee128} } }  */
> +  *p++ = BUILTIN1 (logl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __nearbyintieee128} } }  */
> +  *p++ = BUILTIN1 (nearbyintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __exp10ieee128} } }  */
> +  *p++ = BUILTIN1 (pow10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __rintieee128} } }  */
> +  *p++ = BUILTIN1 (rintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __roundevenieee128} } }  */
> +  *p++ = BUILTIN1 (roundevenl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,0} } }  */
> +  *p++ = BUILTIN1 (roundl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __significandieee128} } }  */
> +  *p++ = BUILTIN1 (significandl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __sinhieee128} } }  */
> +  *p++ = BUILTIN1 (sinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __sinieee128} } }  */
> +  *p++ = BUILTIN1 (sinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __sqrtieee128} } }  */
> +  *p++ = BUILTIN1 (sqrtl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __tanhieee128} } }  */
> +  *p++ = BUILTIN1 (tanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __tanieee128} } }  */
> +  *p++ = BUILTIN1 (tanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __tgammaieee128} } }  */
> +  *p++ = BUILTIN1 (tgammal, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1} } }  */
> +  *p++ = BUILTIN1 (truncl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __y0ieee128} } }  */
> +  *p++ = BUILTIN1 (y0l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __y1ieee128} } }  */
> +  *p   = BUILTIN1 (y1l, *q);
> +
> +}
> +
> +/* Built-in functions that returns a long double and take two long double
> +   arguments.  */
> +
> +void
> +return_ld_arg_ld_ld (long double *p,
> +		     long double *q,
> +		     long double *r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __atan2ieee128} } }  */
> +  *p++ = BUILTIN2 (atan2l, *q++, *r++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxscpsgnqp} } }  */
> +  *p++ = BUILTIN2 (copysignl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __remainderieee128} } }  */
> +  *p++ = BUILTIN2 (dreml, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __fdimieee128} } }  */
> +  *p++ = BUILTIN2 (fdiml, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __fmaxieee128} } }  */
> +  *p++ = BUILTIN2 (fmaxl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __fminieee128} } }  */
> +  *p++ = BUILTIN2 (fminl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __fmodieee128} } }  */
> +  *p++ = BUILTIN2 (fmodl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __hypotieee128} } }  */
> +  *p++ = BUILTIN2 (hypotl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __nextafterieee128} } }  */
> +  *p++ = BUILTIN2 (nextafterl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __nexttowardieee128} } }  */
> +  *p++ = BUILTIN2 (nexttowardl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __powieee128} } }  */
> +  *p++ = BUILTIN2 (powl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __scalbnieee128} } }  */
> +  *p   = BUILTIN2 (scalbl, *q, *r);
> +}
> +
> +/* Built-in function that returns a long double and take three long double
> +   arguments.  */
> +
> +void
> +return_ld_arg_ld_ld_ld (long double *p,
> +			long double *q,
> +			long double *r,
> +			long double *s)
> +{
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxsmaddqp} } }  */
> +  *p = BUILTIN3 (fmal, *q, *r, *s);
> +}
> +
> +/* Built-in functions that returns a long double and take one
> +   _Complex long double argument.  */
> +
> +void
> +return_ld_arg_cld (long double *p,
> +		   _Complex long double *q)
> +{
> +  /* { dg-final { scan-assembler {\mbl __cabsieee128} } }  */
> +  *p++ = BUILTIN1 (cabsl, *q++);
> +}
> +
> +/* Built-in functions that returns a _Complex long double and takes one
> +   _Complex long double argument.  */
> +
> +void
> +return_cld_arg_cld (_Complex long double *p,
> +		    _Complex long double *q)
> +{
> +  /* { dg-final { scan-assembler {\mbl __cacoshieee128} } }  */
> +  *p++ = BUILTIN1 (cacoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __cacosieee128} } }  */
> +  *p++ = BUILTIN1 (cacosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __casinhieee128} } }  */
> +  *p++ = BUILTIN1 (casinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __casinieee128} } }  */
> +  *p++ = BUILTIN1 (casinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __catanhieee128} } }  */
> +  *p++ = BUILTIN1 (catanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __catanieee128} } }  */
> +  *p++ = BUILTIN1 (catanl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __ccoshieee128} } }  */
> +  *p++ = BUILTIN1 (ccoshl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __ccosieee128} } }  */
> +  *p++ = BUILTIN1 (ccosl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __cexpieee128} } }  */
> +  *p++ = BUILTIN1 (cexpl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __clogieee128} } }  */
> +  *p++ = BUILTIN1 (clogl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __clog10ieee128} } }  */
> +  *p++ = BUILTIN1 (clog10l, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __cprojieee128} } }  */
> +  *p++ = BUILTIN1 (cprojl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __csinhieee128} } }  */
> +  *p++ = BUILTIN1 (csinhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __csinieee128} } }  */
> +  *p++ = BUILTIN1 (csinl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __csqrtieee128} } }  */
> +  *p++ = BUILTIN1 (csqrtl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __ctanhieee128} } }  */
> +  *p++ = BUILTIN1 (ctanhl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __ctanieee128} } }  */
> +  *p   = BUILTIN1 (ctanl, *q);
> +}
> +
> +/* Built-in functions that returns a _Complex long double and takes one
> +   long double argument.  */
> +
> +void
> +return_cld_arg_ld (_Complex long double *p,
> +		   long double *q)
> +{
> +  /* { dg-final { scan-assembler {\mbl __sincosieee128} } }  */
> +  *p = BUILTIN1 (cexpil, *q);
> +}
> +
> +/* Built-in function that returns a _Complex long double and takes two
> +   _Complex long double arguments.  */
> +
> +void
> +return_cld_arg_cld_cld (_Complex long double *p,
> +			_Complex long double *q,
> +			_Complex long double *r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __cpowieee128} } }  */
> +  *p = BUILTIN2 (cpowl, *q, *r);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   pointer to an int arguments.  */
> +
> +void
> +return_ld_arg_ld_pi (long double *p,
> +		     long double *q,
> +		     int **r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __frexpieee128} } }  */
> +  *p++ = BUILTIN2 (frexpl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __lgammaieee128_r} } }  */
> +  *p++ = BUILTIN2 (gammal_r, *q++, *r++);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and an
> +   int arguments.  */
> +
> +void
> +return_ld_arg_ld_i (long double *p,
> +		    long double *q,
> +		    int *r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __ldexpieee128} } }  */
> +  *p++ = BUILTIN2 (ldexpl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __powikf2} } }  */
> +  *p++ = BUILTIN2 (powil, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __scalbnieee128} } }  */
> +  *p   = BUILTIN2 (scalbnl, *q, *r);
> +}
> +
> +/* Built-in function that returns a long double and takes a long double and a
> +   long arguments.  */
> +
> +void
> +return_ld_arg_ld_l (long double *p,
> +		    long double *q,
> +		    long *r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __scalblnieee128} } }  */
> +  *p = BUILTIN2 (scalblnl, *q, *r);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   long long arguments.  */
> +
> +void
> +return_ld_arg_i_ld (long double *p,
> +		    int *q,
> +		    long double *r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __jnieee128} } }  */
> +  *p++ = BUILTIN2 (jnl, *q++, *r++);
> +
> +  /* { dg-final { scan-assembler {\mbl __ynieee128} } }  */
> +  *p   = BUILTIN2 (ynl, *q, *r);
> +}
> +
> +/* Built-in functions that returns a long double and takes a long double and a
> +   pointer to a long double arguments.  */
> +
> +void
> +return_ld_arg_ld_pld (long double *p,
> +		      long double *q,
> +		      long double **r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __modfieee128} } }  */
> +  *p = BUILTIN2 (modfl, *q, *r);
> +}
> +
> +/* Built-in function that returns a long double and takes two long double and a
> +   pointer to an int arguments.  */
> +
> +void
> +return_ld_arg_ld_ld_pi (long double *p,
> +			long double *q,
> +			long double *r,
> +			int **s)
> +{
> +  /* { dg-final { scan-assembler {\mbl __remquoieee128} } }  */
> +  *p = BUILTIN3 (remquol, *q, *r, *s);
> +}
> +
> +/* Built-in functions that return san int and takes one long double argument.  */
> +
> +void
> +return_i_arg_ld (int *p,
> +		 long double *q)
> +{
> +  /* { dg-final { scan-assembler {\mbl __ceilieee128} } }  */
> +  *p++ = BUILTIN1 (iceill, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __floorieee128} } }  */
> +  *p++ = BUILTIN1 (ifloorl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __ilogbieee128} } }  */
> +  *p++ = BUILTIN1 (ilogbl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __lrintieee128} } }  */
> +  *p++ = BUILTIN1 (irintl, *q++);
> +
> +  /* { dg-final { scan-assembler {\mbl __lroundieee128} } }  */
> +  *p++ = BUILTIN1 (iroundl, *q++);
> +
> +  /* inline code.  */
> +  /* { dg-final { scan-assembler {\mxscvqpswz} } }  */
> +  *p++ = BUILTIN1 (signbitl, *q++);
> +}
> +
> +/* Built-in function that returns a double and takes one double and one long
> +   double arguments.  */
> +
> +void
> +return_d_arg_d_ld (double *p,
> +		   double *q,
> +		   long double *r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __nexttoward_to_ieee128} } }  */
> +  *p = BUILTIN2 (nexttoward, *q, *r);
> +}
> +
> +/* Built-in function that returns a float and takes one float and one long
> +   double arguments.  */
> +
> +void
> +return_f_arg_f_ld (float *p,
> +		   float *q,
> +		   long double *r)
> +{
> +  /* { dg-final { scan-assembler {\mbl __nexttowardf_to_ieee128} } }  */
> +  *p = BUILTIN2 (nexttowardf, *q, *r);
> +}
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> new file mode 100644
> index 00000000000..39e59d949f9
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> @@ -0,0 +1,36 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-options "-mdejagnu-cpu=power9 -O2 -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble" } */
> +
> +/* Test if switching long double to IEEE 128-bit maps the printf and scanf
> +   function names correctly.  We leave off the \M in matching the calls, so
> +   power10 will match using bl foo@notoc.  */
> +
> +#include <stdlib.h>
> +
> +volatile long double x = 1.0L;
> +volatile long double y, z;
> +
> +int
> +main (void)
> +{
> +  char buffer[100];
> +
> +  /* { dg-final { scan-assembler {\mbl __sprintfieee128} } }  */
> +  __builtin_sprintf (buffer, "%Lg", x);
> +
> +  /* { dg-final { scan-assembler {\mbl __printfieee128} } }  */
> +  __builtin_printf ("x is %Lg [%s]\n", x, buffer);
> +
> +  /* { dg-final { scan-assembler {\mbl __isoc99_sscanfieee128} } }  */
> +  __builtin_sscanf (buffer, "%Lg", &y);
> +
> +  __builtin_printf ("Type 1.0: ");
> +
> +  /* { dg-final { scan-assembler {\mbl __isoc99_scanfieee128} } }  */
> +  __builtin_scanf ("%Lg", &z);
> +
> +  if (x != y || x != z)
> +    abort ();
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.target/powerpc/float128-math.c b/gcc/testsuite/gcc.target/powerpc/float128-math.c
> index 4ad3b5b8363..d1e22239718 100644
> --- a/gcc/testsuite/gcc.target/powerpc/float128-math.c
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-math.c
> @@ -1,20 +1,20 @@
> -/* { dg-do compile { target { powerpc*-*-linux* } } } */
>  /* { dg-require-effective-target ppc_float128_sw } */
>  /* { dg-require-effective-target vsx_hw } */
> -/* { dg-options "-mvsx -O2 -mfloat128 -mabi=ieeelongdouble -Wno-psabi" } */
> +/* { dg-options "-mvsx -O2 -mfloat128 -mlong-double-128 -mabi=ieeelongdouble -Wno-psabi" } */
> 
>  /* Test whether we convert __builtin_<math>l to __builtin_<math>f128 if the
> -   default long double type is IEEE 128-bit.  Also test that using the explicit
> -   __builtin_<math>f128 function does not interfere with the __builtin_<math>l
> -   function.  */
> +   default long double type is IEEE 128-bit.  We leave off the \M in matching
> +   the calls, so power10 will match using bl foo@notoc.  Also test that using
> +   the explicit __builtin_<math>f128 function does not interfere with the
> +   __builtin_<math>l function.  */
> 
>  extern __float128 sinf128 (__float128);
> 
> -void foo (__float128 *p, long double *q, long double *r)
> +void foo (__float128 *p, long double *q)
>  {
>    *p = sinf128 (*p);
>    *q = __builtin_sinl (*q);
>  }
> 
> -/* { dg-final { scan-assembler-times {\mbl sinf128\M} 2 } } */
> -/* { dg-final { scan-assembler-not   {\mbl sinl\M}      } } */
> +/* { dg-final { scan-assembler     {\mbl __sinieee128} } } */
> +/* { dg-final { scan-assembler-not {\mbl sinl}         } } */
> -- 
> 2.22.0
> 
>
Michael Meissner Jan. 27, 2021, 8:51 p.m. UTC | #5
On Wed, Jan 27, 2021 at 01:06:46PM -0600, will schmidt wrote:
> On Thu, 2021-01-14 at 11:59 -0500, Michael Meissner via Gcc-patches wrote:
> > From 78435dee177447080434cdc08fc76b1029c7f576 Mon Sep 17 00:00:00 2001
> > From: Michael Meissner <meissner@linux.ibm.com>
> > Date: Wed, 13 Jan 2021 21:47:03 -0500
> > Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.
> > 
> > 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>
> 
> 
> Subject and date should be sufficient _if_ having the old versions
> of the patchs are necessary to review the latest version of the
> patch.  Which ideally is not the case.
> 
> 
> > 
> > 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.
> 
> ok.
> 
> > 
> > In addition, changing the name in GCC allows the Fortran compiler to
> > automatically use the correct name.
> 
> Does the fortran compiler currently use the wrong name? (pr?)

Yes.  If the compiler is configured for IBM 128-bit long double, the Fortran
compiler calls 'sinl' for real*16.  If the compiler is configured for IEEE
128-bit long double, the compiler needs to call __sinieee128 instead of sinl.

Similarly if a C or C++ user calls __builtin_sinl directly without including
math.h, the wrong name would be used.

Hence what this code does is change the names of all of the built-in functions
that can use long double to be the names appropriate for IEEE 128-bit.

> > 
> > 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.
> 
> This appears to be  the rs6000_mangle_decl_assembler_name() function, which
> also maps <name>l_r to <name>ieee128_r, and looks like some additional special
> handling for printf and scanf.  

Yes, the rs6000_mangle_decl_assembler_name was not complete in the mapping.  In
particular, it did not handle *printf, *scanf, or *l_r calls.  There are also a
few names that need to have a different mapping.

> 
> > To map the printf functions, <name> is mapped to __<name>ieee128.
> > 
> > To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128.
> 
> 
> > 
> > I have tested this patch by doing builds, bootstraps, and make check with 3
> > builds on a power9 little endian server:
> > 
> >     *	Build one used the default long double being IBM 128-bit;
> >     *	Build two set the long double default to IEEE 128-bit; (and)
> >     *	Build three set the long double default to 64-bit.
> > 
> 
> ok
> 
> > The compilers built fine providing I recompiled gmp, mpc, and mpfr with the
> > appropriate long double options.
> 
> Presumably the build is otherwise broken... 
> Does that mean more than invoking download_preqrequisites as part of the
> build?   If there are specific options required during configure/build of
> those packages, they should be called out.
> 
> > There were a few differences in the test
> > suite runs that will be addressed in later patches, but over all it works
> > well.
> 
> Presumably minimal. :-)

It depends on what you mean by minimal.

    * There are 5 C tests that fail (2 Decimal/IEEE, 3 NaN related)
    * 2 C tests that need some changes to be able to run
    * There are 2 C++ tests that fail (Decimal/IEEE, same as the C tests)
    * There are 31 C++ modules tests that fail (PR 98645)
    * There are 3 Fortran tests that used to fail that now pass

I have patches for the Decimal/IEEE tests

> 
> >       This patch is required to be able to build a toolchain where the default
> > long double is IEEE 128-bit. 
> 
> Ok.   Could lead the patch description with this,.  I imagine this is
> just one of several patches that are still required towrards that goal.

In terms of 'need', this patch and the Decimal patch next are the two patches
that absolutely need to be installed.  The others fix some things and tests,
but are not required.
Segher Boessenkool Jan. 28, 2021, 1:30 a.m. UTC | #6
On Tue, Jan 19, 2021 at 12:24:51PM -0500, Michael Meissner wrote:
> On Fri, Jan 15, 2021 at 03:43:13PM -0600, Segher Boessenkool wrote:
> > Hi!
> > 
> > On Thu, Jan 14, 2021 at 11:59:19AM -0500, Michael Meissner wrote:
> > > >From 78435dee177447080434cdc08fc76b1029c7f576 Mon Sep 17 00:00:00 2001
> > > From: Michael Meissner <meissner@linux.ibm.com>
> > > Date: Wed, 13 Jan 2021 21:47:03 -0500
> > > Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.
> > > 
> > > This patch replaces patches previously submitted:
> > 
> > What did you change after I approved it?
> 
> You grumbled about the way I converted the names from the current name to the
> IEEE 128-bit name as being unclear.
> 
> 1) I moved the table of known mappings from within a function to a separate
> function, and I populated the switch statement with all of the current names.
> 
> 2) I moved the code that looks at a built-in function's arguments and returns
> whether it uses long double to a separate function rather than being buried
> within a larger function.
> 
> 3) I changed the code for case we we didn't provide a name (i.e. new built-ins)
> to hopefully be clearer on the conversion.

Don't Do That.

Commit what was approved (unless it actually does not work, then explain
that clearly).  You can sent incremental patches after that.


I am not going to review this whole patch once again.


If you change things in a series, the 0/N message is a good free-form
place to explain that (and start sith a summary, and a summary of what
is different from the previous version, for example).  Some people
keep a changelog of what changed in all version (newest on top of
course).

If there is only one patch, or you need to commemnt something on just
one patch, you can do that after the "---" line.  Everything before that
line then is the exact commit message you will use (or anyone else can
do it as well, with a simple "git am").


The goal of a patch submission is for it to be reviewed.  Your
submission should be optimised for that, not for anything else.


So please send an incremental patch if you want more changes, or if the
previous version was actually very much broken, explain what?


Segher
Segher Boessenkool Jan. 28, 2021, 1:34 a.m. UTC | #7
On Tue, Jan 26, 2021 at 06:39:22PM -0500, Michael Meissner wrote:
> Ping https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563496.html
> 
> | Date: Thu, 14 Jan 2021 11:59:19 -0500
> | Subject: [PATCH] PowerPC: Map IEEE 128-bit long double built-ins.
> | Message-ID: <20210114165919.GA1094@ibm-toto.the-meissners.org>
> 
> As I've said in the past, this is the most important patch of the IEEE 128-bit
> patches.  What do I need to do to be able to commit this patch ASAP?  Or what
> changes do I need to make?

https://patchwork.ozlabs.org/project/gcc/patch/20201119235814.GA322@ibm-toto.the-meissners.org/

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

(And that is for *that* patch, not including later changes.  Send those
separately, don't make me do much more work than needed).


Segher
Segher Boessenkool Jan. 28, 2021, 1:43 a.m. UTC | #8
On Wed, Jan 27, 2021 at 01:06:46PM -0600, will schmidt wrote:
> On Thu, 2021-01-14 at 11:59 -0500, Michael Meissner via Gcc-patches wrote:
> > November 19th, 2020:
> > Message-ID: <20201119235814.GA322@ibm-toto.the-meissners.org>
> 
> Subject and date should be sufficient

Only if people pick good subjects, and do not send ten patches with a
similar subject line on the same day.  I asked for the message id,
that works pretty much everywhere.

> _if_ having the old versions
> of the patchs are necessary to review the latest version of the
> patch.  Which ideally is not the case.

Stronger that that: I need to know what changed!  So please just explain
what changed, in just a short sentence or two, or more if that is needed
(but not if it is not needed).


Segher
Michael Meissner Jan. 28, 2021, 3:01 a.m. UTC | #9
On Wed, Jan 27, 2021 at 07:43:56PM -0600, Segher Boessenkool wrote:
> On Wed, Jan 27, 2021 at 01:06:46PM -0600, will schmidt wrote:
> > On Thu, 2021-01-14 at 11:59 -0500, Michael Meissner via Gcc-patches wrote:
> > > November 19th, 2020:
> > > Message-ID: <20201119235814.GA322@ibm-toto.the-meissners.org>
> > 
> > Subject and date should be sufficient
> 
> Only if people pick good subjects, and do not send ten patches with a
> similar subject line on the same day.  I asked for the message id,
> that works pretty much everywhere.
> 
> > _if_ having the old versions
> > of the patchs are necessary to review the latest version of the
> > patch.  Which ideally is not the case.
> 
> Stronger that that: I need to know what changed!  So please just explain
> what changed, in just a short sentence or two, or more if that is needed
> (but not if it is not needed).

In the past you complained that the patch would abort if the user did not link
against GLIBC 2.32 (because there is an #ifdef in the code to do the abort if
gcc was configured against an older GLIBC).

In addition, it used some pre-processor magic so that I didn't have to modify
the dfp-bit.{c,h} functions to add new functions.  In particular, the new
functions pretended they where the TF functions, and used #define to change the
names.

The new code modifies dfp-bit.{c,h} to have support for the KF functions as
separate #ifdef's.  It eliminates the preprocessor trickery, since I did modify
the dfp-bit.{c,h} support.

In order to deal with older GLIBC's, I used a different function for the KF
library (__sprintfkf instead of sprintf, and __strtokf instead of strold).
This function uses weak references to see if we had the GLIBC symbols
(__sprintfieee128 and __strtoieee128 that are in GLIBC 2.32).  If those
functions exist, we call those functions directly.

If those functions do not exist, I converted the _Float128 type to or from
__ibm128, and I did the normal long double conversions.  Given that IEEE
128-bit has a much larger exponent range than IBM 128-bit, it means there are
some numbers that can't be converted.  But at least the majority of the values
are converted.

Note all of the other binary/decimal conversions use the GLIBC functions
(either sprintf or strto<x>).  The GLIBC people have the expertise to do the
conversion, wheras I do not.  But until GLIBC 2.32, there was not enough of the
support in GLIBC to handle IEEE 128-bit conversions.
Michael Meissner Jan. 28, 2021, 3:04 a.m. UTC | #10
Whoops, I thought I was replying to the second patch about Decimal and IEEE
128-bit conversion, not about built-in support.

On Wed, Jan 27, 2021 at 10:01:38PM -0500, Michael Meissner wrote:
> On Wed, Jan 27, 2021 at 07:43:56PM -0600, Segher Boessenkool wrote:
> > On Wed, Jan 27, 2021 at 01:06:46PM -0600, will schmidt wrote:
> > > On Thu, 2021-01-14 at 11:59 -0500, Michael Meissner via Gcc-patches wrote:
> > > > November 19th, 2020:
> > > > Message-ID: <20201119235814.GA322@ibm-toto.the-meissners.org>
> > > 
> > > Subject and date should be sufficient
> > 
> > Only if people pick good subjects, and do not send ten patches with a
> > similar subject line on the same day.  I asked for the message id,
> > that works pretty much everywhere.
> > 
> > > _if_ having the old versions
> > > of the patchs are necessary to review the latest version of the
> > > patch.  Which ideally is not the case.
> > 
> > Stronger that that: I need to know what changed!  So please just explain
> > what changed, in just a short sentence or two, or more if that is needed
> > (but not if it is not needed).
> 
> In the past you complained that the patch would abort if the user did not link
> against GLIBC 2.32 (because there is an #ifdef in the code to do the abort if
> gcc was configured against an older GLIBC).
> 
> In addition, it used some pre-processor magic so that I didn't have to modify
> the dfp-bit.{c,h} functions to add new functions.  In particular, the new
> functions pretended they where the TF functions, and used #define to change the
> names.
> 
> The new code modifies dfp-bit.{c,h} to have support for the KF functions as
> separate #ifdef's.  It eliminates the preprocessor trickery, since I did modify
> the dfp-bit.{c,h} support.
> 
> In order to deal with older GLIBC's, I used a different function for the KF
> library (__sprintfkf instead of sprintf, and __strtokf instead of strold).
> This function uses weak references to see if we had the GLIBC symbols
> (__sprintfieee128 and __strtoieee128 that are in GLIBC 2.32).  If those
> functions exist, we call those functions directly.
> 
> If those functions do not exist, I converted the _Float128 type to or from
> __ibm128, and I did the normal long double conversions.  Given that IEEE
> 128-bit has a much larger exponent range than IBM 128-bit, it means there are
> some numbers that can't be converted.  But at least the majority of the values
> are converted.
> 
> Note all of the other binary/decimal conversions use the GLIBC functions
> (either sprintf or strto<x>).  The GLIBC people have the expertise to do the
> conversion, wheras I do not.  But until GLIBC 2.32, there was not enough of the
> support in GLIBC to handle IEEE 128-bit conversions.
will schmidt Jan. 28, 2021, 3:31 a.m. UTC | #11
On Wed, 2021-01-27 at 19:43 -0600, Segher Boessenkool wrote:
> On Wed, Jan 27, 2021 at 01:06:46PM -0600, will schmidt wrote:
> > On Thu, 2021-01-14 at 11:59 -0500, Michael Meissner via Gcc-patches 
> > wrote:
> > > November 19th, 2020:
> > > Message-ID: <20201119235814.GA322@ibm-toto.the-meissners.org>
> > 
> > Subject and date should be sufficient
> 
> Only if people pick good subjects, and do not send ten patches with a
> similar subject line on the same day.  I asked for the message id,
> that works pretty much everywhere.

Good points..  I wasn't aware you had specifically asked for the
message ids.  Thanks for clarifying the situation. :-)


> 
> > _if_ having the old versions
> > of the patchs are necessary to review the latest version of the
> > patch.  Which ideally is not the case.
> 
> Stronger that that: I need to know what changed!  So please just
> explain
> what changed, in just a short sentence or two, or more if that is
> needed
> (but not if it is not needed).
> 
> 
> Segher
diff mbox series

Patch

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 6f48dd6566d..282703b9715 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -27100,6 +27100,172 @@  rs6000_globalize_decl_name (FILE * stream, tree decl)
 #endif
 
 
+/* 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";
+    }
+}
+
+/* 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;
+}
+
+/* Return true if an identifier ends in a specific suffix.  */
+static bool
+identifier_ends_in_suffix (tree id, const char *suffix)
+{
+  size_t suffix_len = strlen (suffix);
+  size_t id_len = IDENTIFIER_LENGTH (id);
+
+  return (id_len > suffix_len
+	  && strcmp (IDENTIFIER_POINTER (id), suffix) == 0);
+}
+
+
 /* 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
@@ -27120,51 +27286,62 @@  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);
+      const char *ieee_name = ieee128_builtin_name (DECL_FUNCTION_CODE (decl));
+      tree id_orig = id;
 
-      if (name[len - 1] == 'l')
+      if (ieee_name)
+	id = get_identifier (ieee_name);
+
+      /* If we did not get an IEEE 128-bit built-in name, check to see if a new
+	 math built-in function that is passed or returns long double arguments.
+	 If it ends in 'l' or 'l_r', convert the name the GLIBC IEEE 128-bit
+	 built-in name.  Also convert any printf/scanf functions that were not
+	 handled.  */
+      if (!ieee_name)
 	{
-	  bool uses_ieee128_p = false;
-	  tree type = TREE_TYPE (decl);
-	  machine_mode ret_mode = TYPE_MODE (type);
+	  const char *name = IDENTIFIER_POINTER (id);
+	  char *new_name = NULL;
+	  size_t len = IDENTIFIER_LENGTH (id);
 
-	  /* 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
+	  if (built_in_uses_long_double (decl))
 	    {
-	      function_args_iterator args_iter;
-	      tree arg;
+	      if (identifier_ends_in_suffix (id, "l"))
+		{
+		  int len_m1 = len - 1;		/* eliminate 'l'.  */
+		  new_name = xasprintf ("__%.*sieee128", len_m1, name);
+		}
 
-	      /* See if the function passes a IEEE 128-bit floating point type
-		 or complex type.  */
-	      FOREACH_FUNCTION_ARGS (type, arg, args_iter)
+	      else if (identifier_ends_in_suffix (id, "l_r"))
 		{
-		  machine_mode arg_mode = TYPE_MODE (arg);
-		  if (arg_mode == TFmode || arg_mode == TCmode)
-		    {
-		      uses_ieee128_p = true;
-		      break;
-		    }
+		  int len_m3 = len - 3;		/* eliminate 'l_r'.  */
+		  new_name = xasprintf ("__%.*sieee128_r", len_m3, name);
 		}
 	    }
 
-	  /* If we passed or returned an IEEE 128-bit floating point type,
-	     change the name.  */
-	  if (uses_ieee128_p)
+	  /* Check that no new printf/scanf functions were added.  */
+	  else if (identifier_ends_in_suffix (id, "printf"))
+	    new_name = xasprintf ("__%sieee128", name);
+
+	  else if (identifier_ends_in_suffix (id, "scanf"))
+	    new_name = xasprintf ("__isoc99_%sieee128", name);
+
+	  if (new_name)
 	    {
-	      char *name2 = (char *) alloca (len + 4);
-	      memcpy (name2, name, len - 1);
-	      strcpy (name2 + len - 1, "f128");
-	      id = get_identifier (name2);
+	      id = get_identifier (new_name);
+	      free ((void *)new_name);
 	    }
 	}
+
+      if (id != id_orig && TARGET_DEBUG_BUILTIN)
+	fprintf (stderr, "Map %s => %s%s\n",
+		 IDENTIFIER_POINTER (id_orig),
+		 IDENTIFIER_POINTER (id),
+		 ieee_name != NULL ? "" : " (not in table)");
     }
 
   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}         } } */