[PATCHv4] powerpc64le: ifunc interesting *f128 routines in multiarch mode

Message ID 20200805185827.817999-1-murphyp@linux.vnet.ibm.com
State Superseded
Delegated to: Tulio Magno Quites Machado Filho
Headers
Series [PATCHv4] powerpc64le: ifunc interesting *f128 routines in multiarch mode |

Commit Message

Paul E. Murphy Aug. 5, 2020, 6:58 p.m. UTC
  V4:  Opt-in enablement instead of opt-out.  Take a fixed list
     of functions an ifunc them.  Makefile is refactored to
     append _F128_ENABLE_IFUNC and usage of _F128_DISABLE_IFUNC
     is removed or updated as needed.

     Likewise, don't nullify hidden_proto macro, only math_hidden_proto.
     This allows us to retain protos for functions which aren't
     built with this support, used internally, and by the ifunc'ed
     variants.

     Remove float128-ifunc.c and generate finite compat symbols
     as needed via float128-ifunc.h header and update Makefile
     commentary.

     Finally, only ifunc transcendental functions and those
     with trivial implementations when hardware support is
     present.

---8<---

Programatically generate simple wrappers for interesting libm *f128
objects.  Interesting functions are transcendental functions or
those with trivial compiler builtins.

A second set of implementation files are generated which simply
include the first implementation encountered along the search
path.  This usually works, excepting when a wrapper is overriden
and makefile search order slightly diverges from include order.

A set of additional headers are included which primarily rely
on asm redirects to rename, and less frequently macro renames
where an asm redirect is not possible.  These intercept several
common headers to install redirect and disable macros at specific
times.  This works surprisingly well.  Notably, some ugliness
occurs when header inclusion must be coerced at certain times
before turning off aliasing and plt bypass wrappers.

Finally, don't build this support if requested CPU is newer
than power8.
---
 .../powerpc64/le/fpu/multiarch/Makefile       | 204 +++++++++++++++++-
 .../le/fpu/multiarch/float128-ifunc-macros.h  |  57 +++++
 .../float128-ifunc-redirect-macros.h          |  52 +++++
 .../multiarch/float128-ifunc-redirects-mp.h   |  64 ++++++
 .../fpu/multiarch/float128-ifunc-redirects.h  |  42 ++++
 .../le/fpu/multiarch/float128-ifunc.h         | 164 ++++++++++++++
 .../le/fpu/multiarch/float128_private.h       |  99 +++++++++
 .../fpu/multiarch/math-type-macros-float128.h | 120 +++++++++++
 .../powerpc64/le/fpu/multiarch/math_private.h |  15 ++
 .../le/fpu/multiarch/s_fmaf128-power9.c       |  28 ---
 .../le/fpu/multiarch/s_fmaf128-ppc64.c        |  26 ---
 .../powerpc64/le/fpu/multiarch/s_fmaf128.c    |  36 ----
 .../le/fpu/multiarch/w_sqrtf128-power9.c      |  35 ---
 .../le/fpu/multiarch/w_sqrtf128-ppc64le.c     |  35 ---
 .../powerpc64/le/fpu/multiarch/w_sqrtf128.c   |  31 ---
 .../powerpc/powerpc64/le/power9/Makeconfig    |   3 +
 16 files changed, 814 insertions(+), 197 deletions(-)
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-macros.h
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirect-macros.h
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects-mp.h
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc.h
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/math-type-macros-float128.h
 create mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/math_private.h
 delete mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-power9.c
 delete mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-ppc64.c
 delete mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128.c
 delete mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-power9.c
 delete mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-ppc64le.c
 delete mode 100644 sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128.c
 create mode 100644 sysdeps/powerpc/powerpc64/le/power9/Makeconfig
  

Comments

Paul A. Clarke Sept. 9, 2020, 6:53 p.m. UTC | #1
On Wed, Aug 05, 2020 at 01:58:27PM -0500, Paul E. Murphy via Libc-alpha wrote:
> Programatically generate simple wrappers for interesting libm *f128
> objects.  Interesting functions are transcendental functions or
> those with trivial compiler builtins.

(Subjective): s/interesting/select/ ?

> A second set of implementation files are generated which simply
> include the first implementation encountered along the search
> path.  This usually works, excepting when a wrapper is overriden

nit: s/excepting/except/

> and makefile search order slightly diverges from include order.

Is that good, bad, or just ugly?

> A set of additional headers are included which primarily rely

nit: s/rely/relies/ (singular verb for "set")

> on asm redirects to rename, and less frequently macro renames
> where an asm redirect is not possible.  These intercept several
> common headers to install redirect and disable macros at specific

nit: s/redirect/redirections/ ?
or, is this "redirect macros" and "disable macros"?  If so, perhaps:
"These files intercept several common headers in order to disable
macros or perform redirections at specific times."

> times.  This works surprisingly well.  Notably, some ugliness
> occurs when header inclusion must be coerced at certain times
> before turning off aliasing and plt bypass wrappers.

s/Notably/However/
(I would expect "notably" to highlight what really works well,
and that's not what that sentence includes. ;-)

> 
> Finally, don't build this support if requested CPU is newer
> than power8.

Are there instructions for how do remove this orchestration
when POWER8 is no longer supported?

> ---
[snip]
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
> index 8747b02127..f8d7e7e442 100644
> --- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
> @@ -1,10 +1,202 @@
>  ifeq ($(subdir),math)
> -libm-sysdep_routines += s_fmaf128-ppc64 s_fmaf128-power9 \
> -			w_sqrtf128-power9 w_sqrtf128-ppc64le
>  
> -CFLAGS-s_fmaf128-ppc64.c += $(type-float128-CFLAGS) $(no-gnu-attribute-CFLAGS)
> -CFLAGS-s_fmaf128-power9.c += $(type-float128-CFLAGS) -mcpu=power9 $(no-gnu-attribute-CFLAGS)

I think these specific implementations have been replaced with
your new sweeping changes, correct?
Shall we note that you are replacing these existing multiarch implementations
in the commit message?

> +#
> +# Only enable ifunc _Float128 support if the baseline cpu support
> +# is older than power9.
> +ifneq (yes,$(libc-submachine-power9))
> +do_f128_multiarch = yes
> +endif
> +
> +#
> +# This is an ugly, but contained, mechanism to provide hardware optimized
> +# _Float128 and ldouble == ieee128 optimized routines for P9 and beyond
> +# hardware.  At a very high level, we rely on ASM renames, and rarely
> +# macro renames to build two sets of _Float128 ABI, one with _power8 (the
> +# baseline powerpc64le cpu) and power9 (the first powerpc64le cpu to introduce

nit: "_power8" has an underscore, and "power9" doesn't. Make consistent?

> +# hardware support for _Float128).
> +#
> +# At a high level, we compile 3 files for each object file.
> +#   1.  The baseline soft-float128, unsuffixed objects $(object).$(sfx).
> +#       This ABI is suffixed with _power8.

So, is it unsuffixed or suffixed?

> +#   2.  The hard-float128, power9, suffixed objects $(object)-power9.$(sfx)
> +#   3.  The IFUNC wrapper object to export ABI, $(object)-ifunc.$(sfx)

nit: If this said something like "containing [the?] exported ABI", it would be
consistent with the 2nd sentence, below.

> +#
> +# 2 & 3 are automatically generated by Makefile rule.  Placing the exported
> +# ABI into a separate file allows reuse of existing aliasing macros
> +# with minimal hassle.
> +#
> +# Extending support to new API involes updating:

Is this documentation for future use?  You might want to tag it with "HOWTO", like
"HOWTO add new APIs" or something like that?

> +#
> +#   * Internal float128 API: the float128_private.h interposer.
> +#   * math_private.h API: float128-ifunc-redirects-mp.h
> +#   * templated math API: the math-type-macros-float128.h interposer.

This seem backwards to me, as I'd expect "file:description", but it could just
be me.

> +#
> +# The above is supported by several carefully crafted header files as

nit: s/is/are/ IMHO
(I read "carefully crafted" as "fragile", FYI ;-)

> +# described below:
> +#

nit, subjective: The indentation below seems like you attempted to line up
the continuation of the 2nd line after the include file name on the first
line, then arbitrarily stuck with that forever after. It's pretty deep,
which makes for somewhat short lines. You could back it out quite a bit,
and/or format something like:
  * file:
    text
...which nicely makes the file names stand out.

> +#   * float128-ifunc.h provides support for generating the IFUNC objects
> +#                      in part 3 above.  It also enables case-by-case
> +#                      overriding as some objects do not expose a uniform
> +#                      ABI.
> +#   * float128-ifunc-macros.h disables all first-order aliasing macros
> +#                      used in libm/_Float128, but not the backing

What is "libm/_Float128"? Is there a more precise way to say that?

> +#                      implementations provided by libc-symbols.h as some
> +#                      objects generate strong aliases which make this
> +#                      work easier.
> +#   * float128-ifunc-redirect-macros.h provides macros to support ASM
> +#                      redirect of _Float128 ABI.
> +#   * float128-ifunc-redirects.h provides ASM redirects for functions
> +#                      which are nominally redirected in the private
> +#                      copy of math.h.

Given the other suffixes, should this file be called
float128-ifunc-redirects-asm.h?

> +#   * float128-ifunc-redirects-mp.h provides ASM redirects which are used
> +#                      by math_private.h (the -mp suffix) and the interposer
> +#                      float128_private.h discussed late.
> +#
> +# The headers above should only be included via the interposed headers
> +# discussed below.  Several commonly used headers are interposed to rename all

Does "should only be included via the interposed headers" really mean
"should not be included directly, except by the interposing headers below"?

> +# via ASM redirects.  This requires careful orchestration of header inclusion
> +# to ensure headers are redirected to exclusively _power8 or _power9 suffixed
> +# ABI.  This also has the desirable side-effect of bypassing the PLT locally
> +# and generating compile time errors if a function is missed or changed.
> +#
> +#   * float128_private.h is currently used to rename the ldouble == ieee128
> +#                      object files today.  This takes it a step further and
> +#                      redirects symbols to _power9 or _power8 variants of the
> +#                      functions.  This supports nearly all files in
> +#                      sysdeps/ieee754/float128, but not all _Float128 objects.
> +#                      However, there are three distinct build configurations
> +#                      used to compile _Float128 support.  Two other headers
> +#                      below complete the ABI redirection.
> +#   * math-type-macros-float128.h supports renames for the common object files
> +#                      which are built from templates in math/.
> +#   * math_private.h provides rename support for the common files built in math/
> +#                      which are neither template generated nor ldbl-128
> +#                      specific.  It should be noted that float128_private.h and
> +#                      math_private.h overlap in their declarations, and are
> +#                      used orthogonally.
> +#
> +#
> +# Secondly, this enforces a slightly different mechanism for machine specific

To what does the "Secondly" refer as primarily?
nit: hyphenate "machine-specific".
Global: Is "machine" a well-defined term?

> +# overrides.  That is, all optimizations for all targets must all be reachable

I think that 3rd "all" is unnecessary.  :-)

> +# from the same file as the above relies on rebuilding the same file with

comma in "from the same file, as the above..." ?

> +# different compiler settings.  Most arch specific overrides should be trivial

nit: hyphenate "arch-specific".
Should "machine-specific" above instead be "arch-specific" ?

> +# implementations (e.g sqrt or fma), thus it should present no obstacle.
> +# Likewise, this also enforces them to use the same language (C or ASM today).

Might want to replace "them" with a noun for clarity. "... forces all
implementations ..."?

> +#
> +ifeq ($(do_f128_multiarch),yes)
> +
> +gen-libm-f128-ifunc-calls = \
> +	e_acosf128 e_acoshf128 e_asinf128 e_atan2f128 e_atanhf128 e_coshf128 \
> +	e_expf128 e_fmodf128 e_hypotf128 e_j0f128 e_j1f128 e_jnf128 \
> +	e_lgammaf128_r e_logf128 e_log10f128 e_powf128 e_remainderf128 \
> +	e_sinhf128 e_sqrtf128 e_gammaf128_r e_ilogbf128 k_tanf128 s_asinhf128 \
> +	s_atanf128 s_cbrtf128 s_ceilf128 s_cosf128 s_erff128 s_expm1f128 \
> +	s_fabsf128 s_floorf128 s_log1pf128 s_logbf128 \
> +	s_rintf128 s_scalblnf128 s_sinf128 s_tanf128 \
> +	s_tanhf128 s_truncf128 s_remquof128 e_log2f128 \
> +	s_roundf128 s_nearbyintf128 s_sincosf128 s_fmaf128 s_lrintf128 \
> +	s_llrintf128 s_lroundf128 s_llroundf128 e_exp10f128 \
> +	m_modff128 m_scalbnf128 m_frexpf128 m_ldexpf128 x2y2m1f128 \
> +	gamma_productf128 lgamma_negf128 lgamma_productf128 s_roundevenf128 \
> +	cargf128 conjf128 cimagf128 crealf128 cabsf128 e_scalbf128 s_cacosf128 \
> +	s_cacoshf128 s_ccosf128 s_ccoshf128 s_casinf128 s_csinf128 \
> +	s_casinhf128 k_casinhf128 s_csinhf128 k_casinhf128 s_csinhf128 \
> +	s_catanhf128 s_catanf128 s_ctanf128 s_ctanhf128 s_cexpf128 s_clogf128 \
> +	s_cprojf128 s_csqrtf128 s_cpowf128 s_clog10f128 s_fdimf128 \
> +	s_fmaxf128 s_fminf128 w_ilogbf128 w_llogbf128 \
> +	w_log1pf128 w_scalblnf128 w_acosf128 \
> +	w_acoshf128 w_asinf128 w_atan2f128 w_atanhf128 w_coshf128 w_exp10f128 \
> +	w_exp2f128 w_fmodf128 w_hypotf128 w_j0f128 w_j1f128 w_jnf128 \
> +	w_logf128 w_log10f128 w_log2f128 w_powf128 w_remainderf128 \
> +	w_scalbf128 w_sinhf128 w_sqrtf128 w_tgammaf128 w_lgammaf128 \
> +	w_lgammaf128_r w_expf128 e_exp2f128 \
> +	k_sinf128 k_cosf128 k_sincosf128 e_rem_pio2f128
> +
> +
> +f128-march-routines-p9 = $(addsuffix -power9,$(gen-libm-f128-ifunc-calls))

nit, subjective, global: s/routines/functions/, but this is certainly no big deal
is it used for both "function" and "file"?

> +f128-march-routines-ifunc = $(addsuffix -ifunc,$(gen-libm-f128-ifunc-calls))
> +f128-march-routines = $(f128-march-routines-p9) $(f128-march-routines-ifunc)
> +f128-march-cpus = power9
> +
> +libm-routines += $(f128-march-routines)
> +generated += $(f128-march-routines)
> +
> +CFLAGS-float128-ifunc.c += $(type-float128-CFLAGS) $(no-gnu-attribute-CFLAGS)
> +
> +# Copy special CFLAGS for some functions
> +CFLAGS-m_modff128-power9.c += -fsignaling-nans
> +
> +# Generate wrapper objects for each machine,
> +# and a separate ifunc wrapper.  Likewise substitute
> +# m_%.c files should include s_%.c to match common libm rules
> +# for files built in both libm and libc.

This sentence is confusing to me. "Likewise substitute ... files
should include"... comma after "Likewise"?  Is "substitute" a
verb or an adjective?  Suggest rewording.

> +$(objpfx)gen-float128-ifuncs.stmp: Makefile
> +	$(make-target-directory)
> +	for gcall in $(gen-libm-f128-ifunc-calls); do    \
> +	  ifile="$${gcall}";                             \
> +	  if [ $${gcall##m_} != $${gcall} ]; then        \
> +	    ifile="s_$${gcall##m_}";                     \
> +	  fi;                                            \

what's this for? maybe a comment to explain?

> +	  for cpu in $(f128-march-cpus); do              \
> +	    file=$(objpfx)$${gcall}-$${cpu}.c;           \
> +	    {                                            \
> +	      echo "#include <$${ifile}.c>";             \
> +	    } > $${file};                                \
> +	  done;                                          \
> +	  name="$${gcall##?_}";                          \
> +	  pfx="$${gcall%%_*}";                           \
> +	  R="";                                          \
> +	  r="";                                          \
> +	  if [ $${gcall##m_} != $${gcall} ]; then        \
> +	    pfx="s";                                     \
> +	  fi;                                            \
> +	  if [ $${#pfx} != 1 ]; then                     \
> +	    pfx="";                                      \
> +	  else                                           \
> +	    pfx="_$${pfx}";                              \
> +	  fi;                                            \

what's this for? maybe a comment to explain?

> +	  if [ $${name%%_r} != $${name} ]; then          \
> +	    R="_R";                                      \
> +	    r="_r";                                      \
> +	    name="$${name%%_r}";                         \
> +	  fi;                                            \

what's this for? maybe a comment to explain?

> +	  name="$${name%%f128}";                         \
> +	  decl="DECL_ALIAS$${pfx}_$${name}$${r}";        \
> +	  compat="GEN_COMPAT$${pfx}_$${name}$${r}";      \
> +	  declc="DECL_ALIAS$${R}$${pfx}";                \
> +	  {                                              \
> +	    echo "#include <float128-ifunc.h>";          \
> +	    echo "#ifndef $${decl}";                     \
> +	    echo "# define $${decl}(f) $${declc} (f)";   \
> +	    echo "#endif";                               \
> +	    echo "#ifndef $${compat}";                   \
> +	    echo "# define $${compat}(f)";               \
> +	    echo "#endif";                               \
> +	    echo "$${decl} ($${name});";                 \
> +	    echo "$${compat} ($${name});";               \
> +	  } > $(objpfx)$${gcall}-ifunc.c;                \
> +	done;                                            \
> +	echo > $(@)
> +
> +$(foreach f,$(f128-march-routines),$(objpfx)$(f).c): $(objpfx)gen-float128-ifuncs.stmp
> +
> +enable-f128-ifunc-CFLAGS = -D_F128_ENABLE_IFUNC $(no-gnu-attributes-CFLAGS) $(type-float128-CFLAGS)
> +
> +# Enable IFUNC on baseline (power8) implementations

Do you need to call out "power8" explicitly here, or is just whatever
you happen to get without "-mcpu"?

> +include $(o-iterator)
> +define o-iterator-doit
> +$(foreach f,$(gen-libm-f128-ifunc-calls),$(objpfx)$(f)$(o)): sysdep-CFLAGS += -D_F128_ENABLE_IFUNC
> +endef
> +object-suffixes-left := $(all-object-suffixes)
> +include $(o-iterator)
> +
> +# Likewise, but for power9.
> +include $(o-iterator)
> +define o-iterator-doit
> +$(foreach f,$(f128-march-routines-p9),$(objpfx)$(f)$(o)): sysdep-CFLAGS += $$(enable-f128-ifunc-CFLAGS) -mcpu=power9
> +endef
> +object-suffixes-left := $(all-object-suffixes)
> +include $(o-iterator)
>  
> -CFLAGS-w_sqrtf128-ppc64le.c += $(type-float128-CFLAGS) $(no-gnu-attribute-CFLAGS)
> -CFLAGS-w_sqrtf128-power9.c += $(type-float128-CFLAGS) -mcpu=power9 $(no-gnu-attribute-CFLAGS)

NOTE2SELF: Need to come back to understand this.

> +endif # do_f128_multiarch
>  endif
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-macros.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-macros.h
> new file mode 100644
> index 0000000000..12e1eea510
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-macros.h
> @@ -0,0 +1,57 @@
> +/* _Float128 aliasing macro support for ifunc generation on PPC.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _FLOAT128_IFUNC_MACROS_PPC64LE
> +#define _FLOAT128_IFUNC_MACROS_PPC64LE 1
> +
> +/* Bring in the various alias providing headers, and disable

Hyphenate "alias-providing" (or use "headers providing aliases")

> +   those used for _Float128.  This prevents exporting any ABI

"those" is aliases or headers?  Suggest replacing "those" with the
concrete term.

> +   from _Float128 implementation objects, or confusing errors

"confusing" is a bit dangling here, as it could be "... prevents
confusing errors" or { "prevents exporting" or "confusing errors" }.
Maybe "... and prevents errors ..."

> +   when a renamed symbol fails to compile.  */
> +#include <libm-alias-float128.h>
> +#include <libm-alias-finite.h>
> +
> +#undef libm_alias_float128_r
> +#undef libm_alias_finite
> +#undef libm_alias_exclusive_ldouble
> +#undef libm_alias_float128_other_r_ldbl
> +#undef declare_mgen_finite_alias
> +#undef declare_mgen_alias
> +#undef declare_mgen_alias_r

Is this a robust list that won't require maintenance over time?
The cross-file dependencies are a bit of a concern.
I wonder if this disabling should be done inside the included
files, rather than here?  And triggered with a single define,
like __FLOAT128_ENABLE_ALIASING (or something much better than that ;-)

> +
> +#define libm_alias_finite(from, to)
> +#define libm_alias_float128_r(from, to, r)
> +#define libm_alias_exclusive_ldouble(from, to)
> +#define libm_alias_float128_other_r_ldbl(from, to, r)
> +#define declare_mgen_finite_alias(from, to)
> +#define declare_mgen_alias(from, to)
> +#define declare_mgen_alias_r(from, to)
> +
> +/*  Likewise, disable hidden symbol support.  This is not needed
> +    for the implementation objects as the redirects already give
> +    us this support.  This also means any non-_Float128 headers
> +    which provide hidden_def's should be included prior to this
> +    header (only fenv.h during initial support).  */

What does "during initial support" mean?

> +#undef libm_hidden_def
> +#define libm_hidden_def(func)
> +#undef libm_hidden_proto
> +#define libm_hidden_proto(f)
> +
> +#include <float128-ifunc-redirect-macros.h>
> +
> +#endif /* _FLOAT128_IFUNC_MACROS_PPC64LE */
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirect-macros.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirect-macros.h
> new file mode 100644
> index 0000000000..1dafd99327
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirect-macros.h
> @@ -0,0 +1,52 @@
> +/* _Float128 aliasing macro support for ifunc generation on PPC.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _FLOAT128_IFUNC_REDIRECT_MACROS_PPC64LE
> +#define _FLOAT128_IFUNC_REDIRECT_MACROS_PPC64LE 1
> +
> +/* Define the redirection macros used throughout most of the IFUNC headers.
> +
> +   F128_REDIR_PFX_R(function, destination_prefix, reentrant_suffix)
> +    Redirect function, optionally suffixed by reentrant_suffix, to a function
> +    named destination_prefix ## function ## cpu ## reentrant_suffix where cpu
> +    is either _power8 or _power9 as inferred by compiler options.

The "power8/9" comment is going to get stale quickly. Is it needed?

> +
> +   F128_SFX_APPEND(sym)
> +    Append the the multiarch cpu specific suffix to the sym. sym is not
> +    expanded.  This is sym ## cpu, where cpu is either power8 or power9
> +    inferred by compiler options.

You probably don't need the 2nd sentence.

> +
> +   F128_REDIR_R(func, reentrant_suffix)
> +    Redirect func to a function named function ## cpu ## reentrant_suffix
> +    where cpu is either _power8 or _power9 as inferred by compiler options.

You could end the description with the first line.

> +
> +   F128_REDIR(function)
> +    Redirect function, to a function named function ## cpu where cpu is
> +    either _power8 or _power9 as inferred by compiler options.

Same general comment.

> +*/
> +#ifndef _ARCH_PWR9
> +#define F128_REDIR_PFX_R(func, pfx, r) extern __typeof(func ## r) func ## r __asm( #pfx #func "_power8" #r );
> +#define F128_SFX_APPEND(x) x ## _power8
> +#else
> +#define F128_REDIR_PFX_R(func, pfx, r) extern __typeof(func ## r) func ## r __asm( #pfx #func "_power9" #r );
> +#define F128_SFX_APPEND(x) x ## _power9
> +#endif

Suggest reversing these in anticipation of _ARCH_PWR10 support, so you would then have:
#if _ARCH_PWR10
#elif _ARCH_PWR9
#else /* _ARCH_PWR8.  */
#endif

Also, do you need the "_power8" suffix?

Here and many other places: very long lines.

> +#define F128_REDIR_R(func, r) F128_REDIR_PFX_R (func, , r)
> +#define F128_REDIR(func) F128_REDIR_R (func, )
> +
> +#endif /*_FLOAT128_IFUNC_REDIRECT_MACROS_PPC64LE */
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects-mp.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects-mp.h
> new file mode 100644
> index 0000000000..3c8b6f1291
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects-mp.h
> @@ -0,0 +1,64 @@
> +/* _Float128 multiarch redirects shared with math_private.h
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _FLOAT128_IFUNC_REDIRECTS_MP_H
> +#define _FLOAT128_IFUNC_REDIRECTS_MP_H 1
> +
> +#include <float128-ifunc-redirect-macros.h>
> +
> +F128_REDIR (__ieee754_acosf128)
> +F128_REDIR (__ieee754_acoshf128)
> +F128_REDIR (__ieee754_asinf128)
> +F128_REDIR (__ieee754_atan2f128)
> +F128_REDIR (__ieee754_atanhf128)
> +F128_REDIR (__ieee754_coshf128)
> +F128_REDIR (__ieee754_expf128)
> +F128_REDIR (__ieee754_exp10f128)
> +F128_REDIR (__ieee754_exp2f128)
> +F128_REDIR (__ieee754_fmodf128)
> +F128_REDIR (__ieee754_gammaf128)
> +F128_REDIR_R (__ieee754_gammaf128, _r)
> +F128_REDIR (__ieee754_hypotf128)
> +F128_REDIR (__ieee754_j0f128)
> +F128_REDIR (__ieee754_j1f128)
> +F128_REDIR (__ieee754_jnf128)
> +F128_REDIR (__ieee754_lgammaf128)
> +F128_REDIR_R (__ieee754_lgammaf128, _r)
> +F128_REDIR (__ieee754_logf128)
> +F128_REDIR (__ieee754_log10f128)
> +F128_REDIR (__ieee754_log2f128)
> +F128_REDIR (__ieee754_powf128)
> +F128_REDIR (__ieee754_remainderf128)
> +F128_REDIR (__ieee754_sinhf128)
> +F128_REDIR (__ieee754_sqrtf128)
> +F128_REDIR (__ieee754_y0f128)
> +F128_REDIR (__ieee754_y1f128)
> +F128_REDIR (__ieee754_ynf128)
> +F128_REDIR (__ieee754_scalbf128)
> +F128_REDIR (__ieee754_ilogbf128)
> +F128_REDIR (__ieee754_rem_pio2f128)
> +F128_REDIR (__kernel_sinf128)
> +F128_REDIR (__kernel_cosf128)
> +F128_REDIR (__kernel_tanf128)
> +F128_REDIR (__kernel_sincosf128)
> +F128_REDIR (__kernel_rem_pio2f128)
> +F128_REDIR (__x2y2m1f128)
> +F128_REDIR (__gamma_productf128)
> +F128_REDIR (__lgamma_negf128)
> +
> +#endif /*_FLOAT128_IFUNC_REDIRECTS_MP_H */
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h
> new file mode 100644
> index 0000000000..61b98b05f1
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h
> @@ -0,0 +1,42 @@
> +/* _Float128 redirects for ppc64le multiarch env.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _FLOAT128_IFUNC_REDIRECTS
> +#define _FLOAT128_IFUNC_REDIRECTS 1
> +
> +#include <float128-ifunc-macros.h>
> +
> +F128_REDIR_PFX_R (sqrtf128, __,);
> +F128_REDIR_PFX_R (rintf128, __,);
> +F128_REDIR_PFX_R (ceilf128, __,);
> +F128_REDIR_PFX_R (floorf128, __,);
> +F128_REDIR_PFX_R (truncf128, __,);
> +F128_REDIR_PFX_R (roundf128, __,);
> +F128_REDIR_PFX_R (fabsf128, __,);
> +
> +extern __typeof (ldexpf128) F128_SFX_APPEND (__ldexpf128);
> +
> +#define __ldexpf128 F128_SFX_APPEND (__ldexpf128)

Why is this one special?

> +
> +/* Similarly, we disable math_hidden_proto which prevents

Similarly to what?

> +   a few common helper functions from bypassing the PLT.  
> +   Note, this header is only used for building libm objects.  */
> +hidden_proto (__fpclassifyf128)
> +hidden_proto (__issignalingf128)
> +
> +#endif /* _FLOAT128_IFUNC_REDIRECTS */
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc.h
> new file mode 100644
> index 0000000000..b001b73fea
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc.h
> @@ -0,0 +1,164 @@
> +/* _Float128 ifunc symboling macros.

"symboling" ?

> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _FLOAT128_IFUNC_H
> +#define _FLOAT128_IFUNC_H 1
> +
> +/* Disable hidden prototypes.  They rename ABI we ifunc which causes
> +   problems and show up as strange errors.  */

Reword the 2nd sentence.

> +#undef hidden_proto
> +#define hidden_proto(x)
> +#define NO_MATH_REDIRECT 1
> +
> +/* Avoid include/math.h, it can break ifunc, i.e it's inline fabsf128.  */

"Avoid" as in "Do not"?  Suggest saying that. Perhaps "Do not include
<math.h> here, which will break ...".
period after "i.e."
no apostrophe for "its", actually, remove "it's".
Should you explain why this "breaks" things?

> +#include <math/math.h>
> +#include <math_private.h>
> +#include <complex.h>
> +#include <first-versions.h>
> +#include <shlib-compat.h>
> +#include "init-arch.h"
> +
> +#include <libm-alias-float128.h>
> +#include <libm-alias-finite.h>
> +
> +/* _F128_IFUNC2(func, from, r)
> +      Generate an ifunc symbol func ## r from the symbols
> +	from ## {power8, power9} ## r
> +
> +      We use the PPC hwcap bit HAS_IEEE128 to select between the two with
> +      the assumption all P9 features are available on such targets.  */
> +#define _F128_IFUNC2(func, from, r) \
> +	libc_ifunc (func ## r, (hwcap2 & PPC_FEATURE2_HAS_IEEE128) \
> +                                ? from ## _power9 ## r : from ## _power8 ## r)

I'm starting to wonder about these suffixes versus more generic
and meaningful suffixes, since the distinction is whether the hardware
supports hardware 128-bit float, right?  Is "_noieee128" and no suffix
feasible? Or, something like that?

> +
> +/* _F128_IFUNC(func, r)
> +      Similar to above, except the exported symbol name trivially remaps from
> +      func ## {cpu} ## r to func ## r.  */
> +#define _F128_IFUNC(func, r) _F128_IFUNC2(func, func, r)
> +
> +/* MAKE_IMPL_IFUNC2(func, pfx1, pfx2, r)

Here and elsewhere, maybe s/MAKE/DECLARE/ ?

> +     Declare external symbols of type pfx1 ## func ## f128 ## r with the name
> +                                      pfx2 ## func ## f128 ## _{cpu} ## r
> +     which are exported as implementation specific symbols (i.e backing support
> +     for type classification macros).  */
> +#define MAKE_IMPL_IFUNC2(func, pfx1, pfx2, r) \
> +	extern __typeof (pfx1 ## func ## f128 ## r) pfx2 ## func ## f128_power8 ## r; \
> +	extern __typeof (pfx1 ## func ## f128 ## r) pfx2 ## func ## f128_power9 ## r; \

Here also, hoping there is a better choice of suffixes.

> +        _F128_IFUNC2 (__ ## func ## f128, pfx2 ## func ## f128, r);
> +
> +/* GEN_COMPAT_R_e(f)
> +     Generate a compatability symbol for finite alias of ieee function.  */
> +#define GEN_COMPAT_R_e(f, r) \
> +	libm_alias_finite (__ieee754_ ## f ## f128 ## r, __ ## f ## f128 ## r)
> +
> +#define GEN_COMPAT_e_acos(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_acosh(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_asin(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_sinh(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_atan2(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_atanh(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_cosh(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_exp10(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_exp2(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_exp(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_fmod(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_gamma_r(f) GEN_COMPAT_R_e(f,_r)
> +#define GEN_COMPAT_e_hypot(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_j0(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(y0,)
> +#define GEN_COMPAT_e_j1(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(y1,)
> +#define GEN_COMPAT_e_jn(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(yn,)
> +#define GEN_COMPAT_e_lgamma_r(f) GEN_COMPAT_R_e(f,_r)
> +#define GEN_COMPAT_e_log10(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_log2(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_log(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_pow(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_remainder(f) GEN_COMPAT_R_e(f,)
> +#define GEN_COMPAT_e_sqrt(f) GEN_COMPAT_R_e(f,)
> +
> +/* MAKE_IEEE_IFUNC_R(func, pfx, r)
> +    Declare an ieee ifunc symbol used internally by libm.  E.g __ieee754_sinf128  */
> +#define MAKE_IEEE_IFUNC_R(func, r) \
> +	extern __typeof (__ieee754_ ## func ## f128 ## r) __ieee754_ ## func ## f128_power8 ## r; \
> +	extern __typeof (__ieee754_ ## func ## f128 ## r) __ieee754_ ## func ## f128_power9 ## r; \
> +        _F128_IFUNC2 (__ieee754_ ## func ## f128, __ieee754_ ## func ## f128, r);
> +
> +/* MAKE_IFUNCP_WRAP_R(w, func, r)
> +      Export a function which the implementation wraps with prefix w to
> +      to func ## r. */

nit: 2 spaces after period.

> +#define MAKE_IFUNCP_WRAP_R(w, func, r) \
> +	extern __typeof (func ## f128 ## r) __ ## func ## f128 ## r; \
> +	MAKE_IMPL_IFUNC2 (func,__,__ ## w, r) \
> +	weak_alias (__ ## func ## f128 ## r, func ## f128 ## r); \
> +	libm_alias_float128_other_r (__ ## func, func, r);
> +
> +/* MAKE_IFUNCP_R(func, r)
> +    The default IFUNC generator for all libm _Float128 ABI except
> +    when specifically overwritten.  This is a convenience wrapper

"default" implies "except when ... overwritten", so you could remove that latter
phrase.

> +    around MAKE_IFUNCP_R where w is not used.  */

This *is* MAKE_IFUNCP_R.  I think you mean MAKE_IFUNCP_WRAP_R, but
I think you could delete this sentence, as it is pretty easy to see
in the implementation.

> +#define MAKE_IFUNCP_R(func,r) MAKE_IFUNCP_WRAP_R (,func,r)
> +
> +/* Generic aliasing functions.  */
> +#define DECL_ALIAS(f) MAKE_IFUNCP_R (f,)
> +#define DECL_ALIAS_s(f) MAKE_IFUNCP_R (f,)
> +#define DECL_ALIAS_w(f) MAKE_IFUNCP_R (f,)
> +#define DECL_ALIAS_e(f) MAKE_IEEE_IFUNC_R (f,)
> +#define DECL_ALIAS_k(f)
> +#define DECL_ALIAS_R_w(f) MAKE_IFUNCP_R (f, _r)
> +#define DECL_ALIAS_R_e(f) MAKE_IEEE_IFUNC_R (f,_r)
> +
> +/* No symbols are defined in these helper/wrapper objects. */

nit: 2 spaces after period.

> +#define DECL_ALIAS_lgamma_neg(x)
> +#define DECL_ALIAS_lgamma_product(x)
> +#define DECL_ALIAS_gamma_product(x)
> +#define DECL_ALIAS_x2y2m1(x)
> +#define DECL_ALIAS_s_log1p(x)
> +#define DECL_ALIAS_s_scalbln(x)
> +#define DECL_ALIAS_s_scalbn(x)
> +
> +/* Ensure the wrapper functions get exposed via IFUNC, not the
> +   wrappee (e.g __w_log1pf128_power8 instead of __log1pf128_power8. */

nit: 2 spaces after period.

> +#define DECL_ALIAS_w_log1p(x) MAKE_IFUNCP_WRAP_R(w_,x,)
> +#define DECL_ALIAS_w_scalbln(x) MAKE_IFUNCP_WRAP_R(w_,x,)
> +
> +/* Expose ldouble only redirected symbols.  */

That's difficult to parse.  Could this be reworded?

> +#define DECL_LDOUBLE_ALIAS(func, RTYPE, ARGS) \
> +	extern RTYPE func ARGS; \
> +	extern __typeof (func) func ## _power8; \
> +	extern __typeof (func) func ## _power9; \
> +	_F128_IFUNC ( func,)
> +
> +/* These are declared in their respective jX objects.  */
> +#define DECL_ALIAS_w_j0(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (y0,)
> +#define DECL_ALIAS_w_j1(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (y1,)
> +#define DECL_ALIAS_w_jn(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (yn,)
> +#define DECL_ALIAS_e_j0(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (y0,)
> +#define DECL_ALIAS_e_j1(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (y1,)
> +#define DECL_ALIAS_e_jn(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (yn,)
> +
> +#define DECL_ALIAS_s_erf(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (erfc,)
> +
> +/* scalbnf128 is an alias of ldexpf128.  */
> +#define DECL_ALIAS_s_ldexp(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_WRAP_R (wrap_, scalbn,)
> +
> +/* Handle the special case functions which exist only to support
> +   ldouble == ieee128.  */
> +#define DECL_ALIAS_w_scalb(x) \
> +	DECL_LDOUBLE_ALIAS (__scalbf128,_Float128, (_Float128, _Float128)) \
> +	libm_alias_float128_other_r_ldbl (__scalb, scalb,)
> +
> +#endif /* ifndef _FLOAT128_IFUNC_H  */
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h
> new file mode 100644
> index 0000000000..78f87daccf
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h
> @@ -0,0 +1,99 @@
> +/* _Float128 overrides for float128 in ppc64le multiarch env.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _FLOAT128_PRIVATE_PPC64LE
> +#define _FLOAT128_PRIVATE_PPC64LE 1
> +
> +#if IS_IN(libc) || !defined(_F128_ENABLE_IFUNC)
> +/* multiarch is not supported.  Do nothing and pass through. */

nit: 2 spaces after period.

> +#include_next <float128_private.h>
> +#else
> +
> +/* Include fenv.h now before turning off PLT bypass tricks.  At
> +   minimum fereaiseexcept is used today. */

Suggest generifying this, instead of calling out the example,
tell why this is needed.

> +#include <fenv.h>
> +
> +/* Likewise, the PLT bypass trick uses the same trick to rename
> +   as we do.  Only one asm-rename is allowed.  Only fenv.h
> +   functions require this today, so we include them above.  */

Oh, maybe this is the "why?", so combine this comment with the one
above "#include <fenv.h>", if I understand correctly.

> +#undef libm_hidden_proto
> +#define libm_hidden_proto(f)
> +
> +/* Always disable redirects.  We supply these uniquely later on. */

nit: 2 spaces after period.


> +#undef NO_MATH_REDIRECT
> +#define NO_MATH_REDIRECT
> +#include <math.h>
> +#undef NO_MATH_REDIRECT

Elsewhere, you have a comment like this:
/* Ensure local redirects are always disabled by including
   math.h in the following manner.  */
Do you want the same above this code, too?

> +
> +#include_next <float128_private.h>
> +
> +#include <float128-ifunc-macros.h>
> +
> +/* Declare these now, as they otherwise are not. */

Why are these two special?

nit: 2 spaces after period.

> +extern __typeof (cosf128) __ieee754_cosf128;
> +extern __typeof (asinhf128) __ieee754_asinhf128;
> +
> +F128_REDIR (__ieee754_asinhf128)
> +F128_REDIR (__ieee754_cosf128)
> +F128_REDIR (__asinhf128)
> +F128_REDIR (__atanf128)
> +F128_REDIR (__cbrtf128)
> +F128_REDIR (__ceilf128)
> +F128_REDIR (__cosf128)
> +F128_REDIR (__erfcf128)
> +F128_REDIR (__erff128)
> +F128_REDIR (__expf128)
> +F128_REDIR (__expm1f128)
> +F128_REDIR (__fabsf128)
> +F128_REDIR (__fdimf128)
> +F128_REDIR (__floorf128)
> +F128_REDIR (__fmaf128)
> +F128_REDIR (__fmaxf128)
> +F128_REDIR (__fminf128)
> +F128_REDIR (__frexpf128)
> +F128_REDIR (__ldexpf128)
> +F128_REDIR (__llrintf128)
> +F128_REDIR (__llroundf128)
> +F128_REDIR (__log1pf128)
> +F128_REDIR (__logbf128)
> +F128_REDIR (__logf128)
> +F128_REDIR (__lrintf128)
> +F128_REDIR (__lroundf128)
> +F128_REDIR (__modff128)
> +F128_REDIR (__nearbyintf128)
> +F128_REDIR (__remquof128)
> +F128_REDIR (__rintf128)
> +F128_REDIR (__roundevenf128)
> +F128_REDIR (__roundf128)
> +F128_REDIR (__scalblnf128)
> +F128_REDIR (__scalbnf128)
> +F128_REDIR (__sincosf128)
> +F128_REDIR (__sinf128)
> +F128_REDIR (__sqrtf128)
> +F128_REDIR (__tanhf128)
> +F128_REDIR (__tanf128)
> +F128_REDIR (__truncf128)
> +F128_REDIR (__lgamma_productf128)
> +F128_REDIR (__mpn_extract_float128)
> +
> +#include <float128-ifunc-redirects-mp.h>
> +#include <float128-ifunc-redirects.h>
> +
> +#endif /* !(IS_IN(libc) && defined(_F128_ENABLE_IFUNC) */
> +
> +#endif /* _FLOAT128_PRIVATE_PPC64LE */
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math-type-macros-float128.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math-type-macros-float128.h
> new file mode 100644
> index 0000000000..6185185bc3
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math-type-macros-float128.h
> @@ -0,0 +1,120 @@
> +/* _Float128 overrides for float128 in ppc64le multiarch env.
> +   Copyright (C) 2020 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#ifndef _MATH_TYPE_MACROS_FLOAT128_PPC64_MULTI
> +#define _MATH_TYPE_MACROS_FLOAT128_PPC64_MULTI 1
> +
> +#include_next <math-type-macros-float128.h>
> +
> +#if !IS_IN(libc) && defined(_F128_ENABLE_IFUNC)
> +
> +/* Include fenv.h now before turning off PLT bypass.  At
> +   minimum fereaiseexcept is used today. */

nit: 2 spaces after period.

Suggest generifying this, instead of calling out the example,
tell why this is needed.

> +#include <fenv.h>
> +
> +#include <float128-ifunc-macros.h>
> +
> +/* Ensure local redirects are always disabled by including
> +   math.h in the following manner.  */
> +#undef NO_MATH_REDIRECT
> +#define NO_MATH_REDIRECT
> +#include <math.h>
> +#undef NO_MATH_REDIRECT
> +
> +/* Include forward defitions to redirect complex functions

spelling: "definitions"

> +   below.  */
> +#include <complex.h>
> +
> +/* Declare redirects for an implementation function f which
> +   has a complex analogue.  f is assumed to be prefixed
> +   with '__' and is thus passed through to F128_REDIR.  */

Do you want to say that "f must be prefixed with '__'" ?
But, it seems you prefix f with '__' below?  Maybe I don't
understand the comment above?

> +#define F128_C_REDIR(f) F128_REDIR (__c ## f ## f128); \
> +			F128_REDIR (__ ## f ## f128); \
> +
> +/* Similar to F128_C_REDIR, declare the set of implementation
> +   redirects for the trigonometric family f for {a,}f{,h}
> +   and {a,}cf{,h} complex variants where f is sin/cos/tan.  */
> +#define F128_TRIG_REDIR(f) F128_C_REDIR (a ## f); \
> +			   F128_C_REDIR (a ## f ## h); \
> +			   F128_C_REDIR (f); \
> +			   F128_C_REDIR (f ## h);
> +
> +F128_TRIG_REDIR (cos)
> +F128_TRIG_REDIR (sin)
> +F128_TRIG_REDIR (tan)
> +
> +F128_C_REDIR (log);
> +F128_C_REDIR (log10);
> +F128_C_REDIR (exp);
> +F128_C_REDIR (sqrt);
> +F128_C_REDIR (pow);
> +
> +F128_REDIR (__atan2f128)
> +F128_REDIR (__kernel_casinhf128);
> +F128_REDIR (__rintf128);
> +F128_REDIR (__floorf128);
> +F128_REDIR (__fabsf128);
> +F128_REDIR (__hypotf128);
> +F128_REDIR (__scalbnf128);
> +F128_REDIR (__scalblnf128);
> +F128_REDIR (__sincosf128);
> +F128_REDIR (__log1pf128);
> +F128_REDIR (__ilogbf128);
> +F128_REDIR (__ldexpf128);
> +F128_REDIR (__cargf128);
> +F128_REDIR (__cimagf128);
> +F128_REDIR (__crealf128);
> +F128_REDIR (__conjf128);
> +F128_REDIR (__cprojf128);
> +F128_REDIR (__cabsf128);
> +F128_REDIR (__fdimf128);
> +F128_REDIR (__fminf128);
> +F128_REDIR (__fmaxf128);
> +F128_REDIR (__fmodf128);
> +F128_REDIR (__llogbf128);
> +F128_REDIR (__log2f128);
> +F128_REDIR (__exp10f128);
> +F128_REDIR (__exp2f128);
> +F128_REDIR (__j0f128);
> +F128_REDIR (__j1f128);
> +F128_REDIR (__jnf128);
> +F128_REDIR (__y0f128);
> +F128_REDIR (__y1f128);
> +F128_REDIR (__ynf128);
> +F128_REDIR (__lgammaf128);
> +F128_REDIR_R (__lgammaf128, _r);
> +F128_REDIR (__tgammaf128);
> +F128_REDIR (__remainderf128);
> +
> +/* Assist implementations which declare additional symbols
> +   which require forward declarations to redirect.  */

That's a mouthful. Maybe:
Declare symbols for implementations that require forward declarations
to redirect.
?

> +extern _Float128 __wrap_scalbnf128 (_Float128, int);
> +extern _Float128 __w_scalblnf128 (_Float128, long int);
> +extern _Float128 __w_log1pf128 (_Float128);
> +extern _Float128 __scalbf128 (_Float128, _Float128);
> +F128_REDIR (__scalbf128);
> +F128_REDIR (__wrap_scalbnf128);
> +F128_REDIR (__w_scalblnf128);
> +F128_REDIR (__w_log1pf128);
> +
> +/* Include the redirects shared with math_private.h users.  */
> +#include <float128-ifunc-redirects.h>
> +
> +#endif /* !IS_IN(libc) && defined(_F128_ENABLE_IFUNC) */
> +
> +#endif /*_MATH_TYPE_MACROS_FLOAT128_PPC64_MULTI */
> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math_private.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math_private.h
> new file mode 100644
> index 0000000000..bde3fc4a06
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math_private.h
> @@ -0,0 +1,15 @@
> +#ifndef MATH_PRIVATE_PPC64LE_MA
> +#define MATH_PRIVATE_PPC64LE_MA 1
> +
> +#include_next <math_private.h>
> +
> +#if defined (_F128_ENABLE_IFUNC)
> +
> +/* math_private.h redeclares many float128_private.h renamed functions, but
> +   we can't inclue float128_private.h as this header is used beyond

spelling: "include"

> +   private float128 files.  */

This comment says what you aren't doing. Maybe add or replace with what you
*are* doing.

> +#include <float128-ifunc-redirects-mp.h>
> +
> +#endif
> +
> +#endif /* MATH_PRIVATE_PPC64LE_MA */

[snip]

PC
  
Tulio Magno Quites Machado Filho Oct. 8, 2020, 3:16 p.m. UTC | #2
"Paul E. Murphy via Libc-alpha" <libc-alpha@sourceware.org> writes:

> Programatically generate simple wrappers for interesting libm *f128
> objects.  Interesting functions are transcendental functions or
> those with trivial compiler builtins.
>
> A second set of implementation files are generated which simply
> include the first implementation encountered along the search
> path.  This usually works, excepting when a wrapper is overriden
> and makefile search order slightly diverges from include order.
>
> A set of additional headers are included which primarily rely
> on asm redirects to rename, and less frequently macro renames
> where an asm redirect is not possible.  These intercept several
> common headers to install redirect and disable macros at specific
> times.  This works surprisingly well.  Notably, some ugliness
> occurs when header inclusion must be coerced at certain times
> before turning off aliasing and plt bypass wrappers.
>
> Finally, don't build this support if requested CPU is newer
> than power8.

I have just minor comments.
Otherwise, LGTM.

Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>

Paul Clarke also pointed out a couple of changes to this patch that needs
to be done.

> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
> index 8747b02127..f8d7e7e442 100644
> --- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
> +# 2 & 3 are automatically generated by Makefile rule.  Placing the exported
> +# ABI into a separate file allows reuse of existing aliasing macros
> +# with minimal hassle.
> +#
> +# Extending support to new API involes updating:

s/involes/involves/

> diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h
> new file mode 100644
> index 0000000000..61b98b05f1
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h
> ...
> +extern __typeof (ldexpf128) F128_SFX_APPEND (__ldexpf128);
> +
> +#define __ldexpf128 F128_SFX_APPEND (__ldexpf128)
> +
> +/* Similarly, we disable math_hidden_proto which prevents
> +   a few common helper functions from bypassing the PLT.  

Trailing whitespace.

> +++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h
> +#if IS_IN(libc) || !defined(_F128_ENABLE_IFUNC)
> +/* multiarch is not supported.  Do nothing and pass through. */
> +#include_next <float128_private.h>
> +#else
...
> +F128_REDIR (__mpn_extract_float128)

This function is not part of libm, just libc.
Does it really need to be listed here?
  

Patch

diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
index 8747b02127..f8d7e7e442 100644
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
@@ -1,10 +1,202 @@ 
 ifeq ($(subdir),math)
-libm-sysdep_routines += s_fmaf128-ppc64 s_fmaf128-power9 \
-			w_sqrtf128-power9 w_sqrtf128-ppc64le
 
-CFLAGS-s_fmaf128-ppc64.c += $(type-float128-CFLAGS) $(no-gnu-attribute-CFLAGS)
-CFLAGS-s_fmaf128-power9.c += $(type-float128-CFLAGS) -mcpu=power9 $(no-gnu-attribute-CFLAGS)
+#
+# Only enable ifunc _Float128 support if the baseline cpu support
+# is older than power9.
+ifneq (yes,$(libc-submachine-power9))
+do_f128_multiarch = yes
+endif
+
+#
+# This is an ugly, but contained, mechanism to provide hardware optimized
+# _Float128 and ldouble == ieee128 optimized routines for P9 and beyond
+# hardware.  At a very high level, we rely on ASM renames, and rarely
+# macro renames to build two sets of _Float128 ABI, one with _power8 (the
+# baseline powerpc64le cpu) and power9 (the first powerpc64le cpu to introduce
+# hardware support for _Float128).
+#
+# At a high level, we compile 3 files for each object file.
+#   1.  The baseline soft-float128, unsuffixed objects $(object).$(sfx).
+#       This ABI is suffixed with _power8.
+#   2.  The hard-float128, power9, suffixed objects $(object)-power9.$(sfx)
+#   3.  The IFUNC wrapper object to export ABI, $(object)-ifunc.$(sfx)
+#
+# 2 & 3 are automatically generated by Makefile rule.  Placing the exported
+# ABI into a separate file allows reuse of existing aliasing macros
+# with minimal hassle.
+#
+# Extending support to new API involes updating:
+#
+#   * Internal float128 API: the float128_private.h interposer.
+#   * math_private.h API: float128-ifunc-redirects-mp.h
+#   * templated math API: the math-type-macros-float128.h interposer.
+#
+# The above is supported by several carefully crafted header files as
+# described below:
+#
+#   * float128-ifunc.h provides support for generating the IFUNC objects
+#                      in part 3 above.  It also enables case-by-case
+#                      overriding as some objects do not expose a uniform
+#                      ABI.
+#   * float128-ifunc-macros.h disables all first-order aliasing macros
+#                      used in libm/_Float128, but not the backing
+#                      implementations provided by libc-symbols.h as some
+#                      objects generate strong aliases which make this
+#                      work easier.
+#   * float128-ifunc-redirect-macros.h provides macros to support ASM
+#                      redirect of _Float128 ABI.
+#   * float128-ifunc-redirects.h provides ASM redirects for functions
+#                      which are nominally redirected in the private
+#                      copy of math.h.
+#   * float128-ifunc-redirects-mp.h provides ASM redirects which are used
+#                      by math_private.h (the -mp suffix) and the interposer
+#                      float128_private.h discussed late.
+#
+# The headers above should only be included via the interposed headers
+# discussed below.  Several commonly used headers are interposed to rename all
+# via ASM redirects.  This requires careful orchestration of header inclusion
+# to ensure headers are redirected to exclusively _power8 or _power9 suffixed
+# ABI.  This also has the desirable side-effect of bypassing the PLT locally
+# and generating compile time errors if a function is missed or changed.
+#
+#   * float128_private.h is currently used to rename the ldouble == ieee128
+#                      object files today.  This takes it a step further and
+#                      redirects symbols to _power9 or _power8 variants of the
+#                      functions.  This supports nearly all files in
+#                      sysdeps/ieee754/float128, but not all _Float128 objects.
+#                      However, there are three distinct build configurations
+#                      used to compile _Float128 support.  Two other headers
+#                      below complete the ABI redirection.
+#   * math-type-macros-float128.h supports renames for the common object files
+#                      which are built from templates in math/.
+#   * math_private.h provides rename support for the common files built in math/
+#                      which are neither template generated nor ldbl-128
+#                      specific.  It should be noted that float128_private.h and
+#                      math_private.h overlap in their declarations, and are
+#                      used orthogonally.
+#
+#
+# Secondly, this enforces a slightly different mechanism for machine specific
+# overrides.  That is, all optimizations for all targets must all be reachable
+# from the same file as the above relies on rebuilding the same file with
+# different compiler settings.  Most arch specific overrides should be trivial
+# implementations (e.g sqrt or fma), thus it should present no obstacle.
+# Likewise, this also enforces them to use the same language (C or ASM today).
+#
+ifeq ($(do_f128_multiarch),yes)
+
+gen-libm-f128-ifunc-calls = \
+	e_acosf128 e_acoshf128 e_asinf128 e_atan2f128 e_atanhf128 e_coshf128 \
+	e_expf128 e_fmodf128 e_hypotf128 e_j0f128 e_j1f128 e_jnf128 \
+	e_lgammaf128_r e_logf128 e_log10f128 e_powf128 e_remainderf128 \
+	e_sinhf128 e_sqrtf128 e_gammaf128_r e_ilogbf128 k_tanf128 s_asinhf128 \
+	s_atanf128 s_cbrtf128 s_ceilf128 s_cosf128 s_erff128 s_expm1f128 \
+	s_fabsf128 s_floorf128 s_log1pf128 s_logbf128 \
+	s_rintf128 s_scalblnf128 s_sinf128 s_tanf128 \
+	s_tanhf128 s_truncf128 s_remquof128 e_log2f128 \
+	s_roundf128 s_nearbyintf128 s_sincosf128 s_fmaf128 s_lrintf128 \
+	s_llrintf128 s_lroundf128 s_llroundf128 e_exp10f128 \
+	m_modff128 m_scalbnf128 m_frexpf128 m_ldexpf128 x2y2m1f128 \
+	gamma_productf128 lgamma_negf128 lgamma_productf128 s_roundevenf128 \
+	cargf128 conjf128 cimagf128 crealf128 cabsf128 e_scalbf128 s_cacosf128 \
+	s_cacoshf128 s_ccosf128 s_ccoshf128 s_casinf128 s_csinf128 \
+	s_casinhf128 k_casinhf128 s_csinhf128 k_casinhf128 s_csinhf128 \
+	s_catanhf128 s_catanf128 s_ctanf128 s_ctanhf128 s_cexpf128 s_clogf128 \
+	s_cprojf128 s_csqrtf128 s_cpowf128 s_clog10f128 s_fdimf128 \
+	s_fmaxf128 s_fminf128 w_ilogbf128 w_llogbf128 \
+	w_log1pf128 w_scalblnf128 w_acosf128 \
+	w_acoshf128 w_asinf128 w_atan2f128 w_atanhf128 w_coshf128 w_exp10f128 \
+	w_exp2f128 w_fmodf128 w_hypotf128 w_j0f128 w_j1f128 w_jnf128 \
+	w_logf128 w_log10f128 w_log2f128 w_powf128 w_remainderf128 \
+	w_scalbf128 w_sinhf128 w_sqrtf128 w_tgammaf128 w_lgammaf128 \
+	w_lgammaf128_r w_expf128 e_exp2f128 \
+	k_sinf128 k_cosf128 k_sincosf128 e_rem_pio2f128
+
+
+f128-march-routines-p9 = $(addsuffix -power9,$(gen-libm-f128-ifunc-calls))
+f128-march-routines-ifunc = $(addsuffix -ifunc,$(gen-libm-f128-ifunc-calls))
+f128-march-routines = $(f128-march-routines-p9) $(f128-march-routines-ifunc)
+f128-march-cpus = power9
+
+libm-routines += $(f128-march-routines)
+generated += $(f128-march-routines)
+
+CFLAGS-float128-ifunc.c += $(type-float128-CFLAGS) $(no-gnu-attribute-CFLAGS)
+
+# Copy special CFLAGS for some functions
+CFLAGS-m_modff128-power9.c += -fsignaling-nans
+
+# Generate wrapper objects for each machine,
+# and a separate ifunc wrapper.  Likewise substitute
+# m_%.c files should include s_%.c to match common libm rules
+# for files built in both libm and libc.
+$(objpfx)gen-float128-ifuncs.stmp: Makefile
+	$(make-target-directory)
+	for gcall in $(gen-libm-f128-ifunc-calls); do    \
+	  ifile="$${gcall}";                             \
+	  if [ $${gcall##m_} != $${gcall} ]; then        \
+	    ifile="s_$${gcall##m_}";                     \
+	  fi;                                            \
+	  for cpu in $(f128-march-cpus); do              \
+	    file=$(objpfx)$${gcall}-$${cpu}.c;           \
+	    {                                            \
+	      echo "#include <$${ifile}.c>";             \
+	    } > $${file};                                \
+	  done;                                          \
+	  name="$${gcall##?_}";                          \
+	  pfx="$${gcall%%_*}";                           \
+	  R="";                                          \
+	  r="";                                          \
+	  if [ $${gcall##m_} != $${gcall} ]; then        \
+	    pfx="s";                                     \
+	  fi;                                            \
+	  if [ $${#pfx} != 1 ]; then                     \
+	    pfx="";                                      \
+	  else                                           \
+	    pfx="_$${pfx}";                              \
+	  fi;                                            \
+	  if [ $${name%%_r} != $${name} ]; then          \
+	    R="_R";                                      \
+	    r="_r";                                      \
+	    name="$${name%%_r}";                         \
+	  fi;                                            \
+	  name="$${name%%f128}";                         \
+	  decl="DECL_ALIAS$${pfx}_$${name}$${r}";        \
+	  compat="GEN_COMPAT$${pfx}_$${name}$${r}";      \
+	  declc="DECL_ALIAS$${R}$${pfx}";                \
+	  {                                              \
+	    echo "#include <float128-ifunc.h>";          \
+	    echo "#ifndef $${decl}";                     \
+	    echo "# define $${decl}(f) $${declc} (f)";   \
+	    echo "#endif";                               \
+	    echo "#ifndef $${compat}";                   \
+	    echo "# define $${compat}(f)";               \
+	    echo "#endif";                               \
+	    echo "$${decl} ($${name});";                 \
+	    echo "$${compat} ($${name});";               \
+	  } > $(objpfx)$${gcall}-ifunc.c;                \
+	done;                                            \
+	echo > $(@)
+
+$(foreach f,$(f128-march-routines),$(objpfx)$(f).c): $(objpfx)gen-float128-ifuncs.stmp
+
+enable-f128-ifunc-CFLAGS = -D_F128_ENABLE_IFUNC $(no-gnu-attributes-CFLAGS) $(type-float128-CFLAGS)
+
+# Enable IFUNC on baseline (power8) implementations
+include $(o-iterator)
+define o-iterator-doit
+$(foreach f,$(gen-libm-f128-ifunc-calls),$(objpfx)$(f)$(o)): sysdep-CFLAGS += -D_F128_ENABLE_IFUNC
+endef
+object-suffixes-left := $(all-object-suffixes)
+include $(o-iterator)
+
+# Likewise, but for power9.
+include $(o-iterator)
+define o-iterator-doit
+$(foreach f,$(f128-march-routines-p9),$(objpfx)$(f)$(o)): sysdep-CFLAGS += $$(enable-f128-ifunc-CFLAGS) -mcpu=power9
+endef
+object-suffixes-left := $(all-object-suffixes)
+include $(o-iterator)
 
-CFLAGS-w_sqrtf128-ppc64le.c += $(type-float128-CFLAGS) $(no-gnu-attribute-CFLAGS)
-CFLAGS-w_sqrtf128-power9.c += $(type-float128-CFLAGS) -mcpu=power9 $(no-gnu-attribute-CFLAGS)
+endif # do_f128_multiarch
 endif
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-macros.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-macros.h
new file mode 100644
index 0000000000..12e1eea510
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-macros.h
@@ -0,0 +1,57 @@ 
+/* _Float128 aliasing macro support for ifunc generation on PPC.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _FLOAT128_IFUNC_MACROS_PPC64LE
+#define _FLOAT128_IFUNC_MACROS_PPC64LE 1
+
+/* Bring in the various alias providing headers, and disable
+   those used for _Float128.  This prevents exporting any ABI
+   from _Float128 implementation objects, or confusing errors
+   when a renamed symbol fails to compile.  */
+#include <libm-alias-float128.h>
+#include <libm-alias-finite.h>
+
+#undef libm_alias_float128_r
+#undef libm_alias_finite
+#undef libm_alias_exclusive_ldouble
+#undef libm_alias_float128_other_r_ldbl
+#undef declare_mgen_finite_alias
+#undef declare_mgen_alias
+#undef declare_mgen_alias_r
+
+#define libm_alias_finite(from, to)
+#define libm_alias_float128_r(from, to, r)
+#define libm_alias_exclusive_ldouble(from, to)
+#define libm_alias_float128_other_r_ldbl(from, to, r)
+#define declare_mgen_finite_alias(from, to)
+#define declare_mgen_alias(from, to)
+#define declare_mgen_alias_r(from, to)
+
+/*  Likewise, disable hidden symbol support.  This is not needed
+    for the implementation objects as the redirects already give
+    us this support.  This also means any non-_Float128 headers
+    which provide hidden_def's should be included prior to this
+    header (only fenv.h during initial support).  */
+#undef libm_hidden_def
+#define libm_hidden_def(func)
+#undef libm_hidden_proto
+#define libm_hidden_proto(f)
+
+#include <float128-ifunc-redirect-macros.h>
+
+#endif /* _FLOAT128_IFUNC_MACROS_PPC64LE */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirect-macros.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirect-macros.h
new file mode 100644
index 0000000000..1dafd99327
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirect-macros.h
@@ -0,0 +1,52 @@ 
+/* _Float128 aliasing macro support for ifunc generation on PPC.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _FLOAT128_IFUNC_REDIRECT_MACROS_PPC64LE
+#define _FLOAT128_IFUNC_REDIRECT_MACROS_PPC64LE 1
+
+/* Define the redirection macros used throughout most of the IFUNC headers.
+
+   F128_REDIR_PFX_R(function, destination_prefix, reentrant_suffix)
+    Redirect function, optionally suffixed by reentrant_suffix, to a function
+    named destination_prefix ## function ## cpu ## reentrant_suffix where cpu
+    is either _power8 or _power9 as inferred by compiler options.
+
+   F128_SFX_APPEND(sym)
+    Append the the multiarch cpu specific suffix to the sym. sym is not
+    expanded.  This is sym ## cpu, where cpu is either power8 or power9
+    inferred by compiler options.
+
+   F128_REDIR_R(func, reentrant_suffix)
+    Redirect func to a function named function ## cpu ## reentrant_suffix
+    where cpu is either _power8 or _power9 as inferred by compiler options.
+
+   F128_REDIR(function)
+    Redirect function, to a function named function ## cpu where cpu is
+    either _power8 or _power9 as inferred by compiler options.
+*/
+#ifndef _ARCH_PWR9
+#define F128_REDIR_PFX_R(func, pfx, r) extern __typeof(func ## r) func ## r __asm( #pfx #func "_power8" #r );
+#define F128_SFX_APPEND(x) x ## _power8
+#else
+#define F128_REDIR_PFX_R(func, pfx, r) extern __typeof(func ## r) func ## r __asm( #pfx #func "_power9" #r );
+#define F128_SFX_APPEND(x) x ## _power9
+#endif
+#define F128_REDIR_R(func, r) F128_REDIR_PFX_R (func, , r)
+#define F128_REDIR(func) F128_REDIR_R (func, )
+
+#endif /*_FLOAT128_IFUNC_REDIRECT_MACROS_PPC64LE */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects-mp.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects-mp.h
new file mode 100644
index 0000000000..3c8b6f1291
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects-mp.h
@@ -0,0 +1,64 @@ 
+/* _Float128 multiarch redirects shared with math_private.h
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _FLOAT128_IFUNC_REDIRECTS_MP_H
+#define _FLOAT128_IFUNC_REDIRECTS_MP_H 1
+
+#include <float128-ifunc-redirect-macros.h>
+
+F128_REDIR (__ieee754_acosf128)
+F128_REDIR (__ieee754_acoshf128)
+F128_REDIR (__ieee754_asinf128)
+F128_REDIR (__ieee754_atan2f128)
+F128_REDIR (__ieee754_atanhf128)
+F128_REDIR (__ieee754_coshf128)
+F128_REDIR (__ieee754_expf128)
+F128_REDIR (__ieee754_exp10f128)
+F128_REDIR (__ieee754_exp2f128)
+F128_REDIR (__ieee754_fmodf128)
+F128_REDIR (__ieee754_gammaf128)
+F128_REDIR_R (__ieee754_gammaf128, _r)
+F128_REDIR (__ieee754_hypotf128)
+F128_REDIR (__ieee754_j0f128)
+F128_REDIR (__ieee754_j1f128)
+F128_REDIR (__ieee754_jnf128)
+F128_REDIR (__ieee754_lgammaf128)
+F128_REDIR_R (__ieee754_lgammaf128, _r)
+F128_REDIR (__ieee754_logf128)
+F128_REDIR (__ieee754_log10f128)
+F128_REDIR (__ieee754_log2f128)
+F128_REDIR (__ieee754_powf128)
+F128_REDIR (__ieee754_remainderf128)
+F128_REDIR (__ieee754_sinhf128)
+F128_REDIR (__ieee754_sqrtf128)
+F128_REDIR (__ieee754_y0f128)
+F128_REDIR (__ieee754_y1f128)
+F128_REDIR (__ieee754_ynf128)
+F128_REDIR (__ieee754_scalbf128)
+F128_REDIR (__ieee754_ilogbf128)
+F128_REDIR (__ieee754_rem_pio2f128)
+F128_REDIR (__kernel_sinf128)
+F128_REDIR (__kernel_cosf128)
+F128_REDIR (__kernel_tanf128)
+F128_REDIR (__kernel_sincosf128)
+F128_REDIR (__kernel_rem_pio2f128)
+F128_REDIR (__x2y2m1f128)
+F128_REDIR (__gamma_productf128)
+F128_REDIR (__lgamma_negf128)
+
+#endif /*_FLOAT128_IFUNC_REDIRECTS_MP_H */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h
new file mode 100644
index 0000000000..61b98b05f1
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc-redirects.h
@@ -0,0 +1,42 @@ 
+/* _Float128 redirects for ppc64le multiarch env.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _FLOAT128_IFUNC_REDIRECTS
+#define _FLOAT128_IFUNC_REDIRECTS 1
+
+#include <float128-ifunc-macros.h>
+
+F128_REDIR_PFX_R (sqrtf128, __,);
+F128_REDIR_PFX_R (rintf128, __,);
+F128_REDIR_PFX_R (ceilf128, __,);
+F128_REDIR_PFX_R (floorf128, __,);
+F128_REDIR_PFX_R (truncf128, __,);
+F128_REDIR_PFX_R (roundf128, __,);
+F128_REDIR_PFX_R (fabsf128, __,);
+
+extern __typeof (ldexpf128) F128_SFX_APPEND (__ldexpf128);
+
+#define __ldexpf128 F128_SFX_APPEND (__ldexpf128)
+
+/* Similarly, we disable math_hidden_proto which prevents
+   a few common helper functions from bypassing the PLT.  
+   Note, this header is only used for building libm objects.  */
+hidden_proto (__fpclassifyf128)
+hidden_proto (__issignalingf128)
+
+#endif /* _FLOAT128_IFUNC_REDIRECTS */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc.h
new file mode 100644
index 0000000000..b001b73fea
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128-ifunc.h
@@ -0,0 +1,164 @@ 
+/* _Float128 ifunc symboling macros.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _FLOAT128_IFUNC_H
+#define _FLOAT128_IFUNC_H 1
+
+/* Disable hidden prototypes.  They rename ABI we ifunc which causes
+   problems and show up as strange errors.  */
+#undef hidden_proto
+#define hidden_proto(x)
+#define NO_MATH_REDIRECT 1
+
+/* Avoid include/math.h, it can break ifunc, i.e it's inline fabsf128.  */
+#include <math/math.h>
+#include <math_private.h>
+#include <complex.h>
+#include <first-versions.h>
+#include <shlib-compat.h>
+#include "init-arch.h"
+
+#include <libm-alias-float128.h>
+#include <libm-alias-finite.h>
+
+/* _F128_IFUNC2(func, from, r)
+      Generate an ifunc symbol func ## r from the symbols
+	from ## {power8, power9} ## r
+
+      We use the PPC hwcap bit HAS_IEEE128 to select between the two with
+      the assumption all P9 features are available on such targets.  */
+#define _F128_IFUNC2(func, from, r) \
+	libc_ifunc (func ## r, (hwcap2 & PPC_FEATURE2_HAS_IEEE128) \
+                                ? from ## _power9 ## r : from ## _power8 ## r)
+
+/* _F128_IFUNC(func, r)
+      Similar to above, except the exported symbol name trivially remaps from
+      func ## {cpu} ## r to func ## r.  */
+#define _F128_IFUNC(func, r) _F128_IFUNC2(func, func, r)
+
+/* MAKE_IMPL_IFUNC2(func, pfx1, pfx2, r)
+     Declare external symbols of type pfx1 ## func ## f128 ## r with the name
+                                      pfx2 ## func ## f128 ## _{cpu} ## r
+     which are exported as implementation specific symbols (i.e backing support
+     for type classification macros).  */
+#define MAKE_IMPL_IFUNC2(func, pfx1, pfx2, r) \
+	extern __typeof (pfx1 ## func ## f128 ## r) pfx2 ## func ## f128_power8 ## r; \
+	extern __typeof (pfx1 ## func ## f128 ## r) pfx2 ## func ## f128_power9 ## r; \
+        _F128_IFUNC2 (__ ## func ## f128, pfx2 ## func ## f128, r);
+
+/* GEN_COMPAT_R_e(f)
+     Generate a compatability symbol for finite alias of ieee function.  */
+#define GEN_COMPAT_R_e(f, r) \
+	libm_alias_finite (__ieee754_ ## f ## f128 ## r, __ ## f ## f128 ## r)
+
+#define GEN_COMPAT_e_acos(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_acosh(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_asin(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_sinh(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_atan2(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_atanh(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_cosh(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_exp10(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_exp2(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_exp(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_fmod(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_gamma_r(f) GEN_COMPAT_R_e(f,_r)
+#define GEN_COMPAT_e_hypot(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_j0(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(y0,)
+#define GEN_COMPAT_e_j1(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(y1,)
+#define GEN_COMPAT_e_jn(f) GEN_COMPAT_R_e(f,) GEN_COMPAT_R_e(yn,)
+#define GEN_COMPAT_e_lgamma_r(f) GEN_COMPAT_R_e(f,_r)
+#define GEN_COMPAT_e_log10(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_log2(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_log(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_pow(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_remainder(f) GEN_COMPAT_R_e(f,)
+#define GEN_COMPAT_e_sqrt(f) GEN_COMPAT_R_e(f,)
+
+/* MAKE_IEEE_IFUNC_R(func, pfx, r)
+    Declare an ieee ifunc symbol used internally by libm.  E.g __ieee754_sinf128  */
+#define MAKE_IEEE_IFUNC_R(func, r) \
+	extern __typeof (__ieee754_ ## func ## f128 ## r) __ieee754_ ## func ## f128_power8 ## r; \
+	extern __typeof (__ieee754_ ## func ## f128 ## r) __ieee754_ ## func ## f128_power9 ## r; \
+        _F128_IFUNC2 (__ieee754_ ## func ## f128, __ieee754_ ## func ## f128, r);
+
+/* MAKE_IFUNCP_WRAP_R(w, func, r)
+      Export a function which the implementation wraps with prefix w to
+      to func ## r. */
+#define MAKE_IFUNCP_WRAP_R(w, func, r) \
+	extern __typeof (func ## f128 ## r) __ ## func ## f128 ## r; \
+	MAKE_IMPL_IFUNC2 (func,__,__ ## w, r) \
+	weak_alias (__ ## func ## f128 ## r, func ## f128 ## r); \
+	libm_alias_float128_other_r (__ ## func, func, r);
+
+/* MAKE_IFUNCP_R(func, r)
+    The default IFUNC generator for all libm _Float128 ABI except
+    when specifically overwritten.  This is a convenience wrapper
+    around MAKE_IFUNCP_R where w is not used.  */
+#define MAKE_IFUNCP_R(func,r) MAKE_IFUNCP_WRAP_R (,func,r)
+
+/* Generic aliasing functions.  */
+#define DECL_ALIAS(f) MAKE_IFUNCP_R (f,)
+#define DECL_ALIAS_s(f) MAKE_IFUNCP_R (f,)
+#define DECL_ALIAS_w(f) MAKE_IFUNCP_R (f,)
+#define DECL_ALIAS_e(f) MAKE_IEEE_IFUNC_R (f,)
+#define DECL_ALIAS_k(f)
+#define DECL_ALIAS_R_w(f) MAKE_IFUNCP_R (f, _r)
+#define DECL_ALIAS_R_e(f) MAKE_IEEE_IFUNC_R (f,_r)
+
+/* No symbols are defined in these helper/wrapper objects. */
+#define DECL_ALIAS_lgamma_neg(x)
+#define DECL_ALIAS_lgamma_product(x)
+#define DECL_ALIAS_gamma_product(x)
+#define DECL_ALIAS_x2y2m1(x)
+#define DECL_ALIAS_s_log1p(x)
+#define DECL_ALIAS_s_scalbln(x)
+#define DECL_ALIAS_s_scalbn(x)
+
+/* Ensure the wrapper functions get exposed via IFUNC, not the
+   wrappee (e.g __w_log1pf128_power8 instead of __log1pf128_power8. */
+#define DECL_ALIAS_w_log1p(x) MAKE_IFUNCP_WRAP_R(w_,x,)
+#define DECL_ALIAS_w_scalbln(x) MAKE_IFUNCP_WRAP_R(w_,x,)
+
+/* Expose ldouble only redirected symbols.  */
+#define DECL_LDOUBLE_ALIAS(func, RTYPE, ARGS) \
+	extern RTYPE func ARGS; \
+	extern __typeof (func) func ## _power8; \
+	extern __typeof (func) func ## _power9; \
+	_F128_IFUNC ( func,)
+
+/* These are declared in their respective jX objects.  */
+#define DECL_ALIAS_w_j0(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (y0,)
+#define DECL_ALIAS_w_j1(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (y1,)
+#define DECL_ALIAS_w_jn(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (yn,)
+#define DECL_ALIAS_e_j0(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (y0,)
+#define DECL_ALIAS_e_j1(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (y1,)
+#define DECL_ALIAS_e_jn(f) MAKE_IEEE_IFUNC_R (f,) MAKE_IEEE_IFUNC_R (yn,)
+
+#define DECL_ALIAS_s_erf(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_R (erfc,)
+
+/* scalbnf128 is an alias of ldexpf128.  */
+#define DECL_ALIAS_s_ldexp(f) MAKE_IFUNCP_R (f,) MAKE_IFUNCP_WRAP_R (wrap_, scalbn,)
+
+/* Handle the special case functions which exist only to support
+   ldouble == ieee128.  */
+#define DECL_ALIAS_w_scalb(x) \
+	DECL_LDOUBLE_ALIAS (__scalbf128,_Float128, (_Float128, _Float128)) \
+	libm_alias_float128_other_r_ldbl (__scalb, scalb,)
+
+#endif /* ifndef _FLOAT128_IFUNC_H  */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h
new file mode 100644
index 0000000000..78f87daccf
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/float128_private.h
@@ -0,0 +1,99 @@ 
+/* _Float128 overrides for float128 in ppc64le multiarch env.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _FLOAT128_PRIVATE_PPC64LE
+#define _FLOAT128_PRIVATE_PPC64LE 1
+
+#if IS_IN(libc) || !defined(_F128_ENABLE_IFUNC)
+/* multiarch is not supported.  Do nothing and pass through. */
+#include_next <float128_private.h>
+#else
+
+/* Include fenv.h now before turning off PLT bypass tricks.  At
+   minimum fereaiseexcept is used today. */
+#include <fenv.h>
+
+/* Likewise, the PLT bypass trick uses the same trick to rename
+   as we do.  Only one asm-rename is allowed.  Only fenv.h
+   functions require this today, so we include them above.  */
+#undef libm_hidden_proto
+#define libm_hidden_proto(f)
+
+/* Always disable redirects.  We supply these uniquely later on. */
+#undef NO_MATH_REDIRECT
+#define NO_MATH_REDIRECT
+#include <math.h>
+#undef NO_MATH_REDIRECT
+
+#include_next <float128_private.h>
+
+#include <float128-ifunc-macros.h>
+
+/* Declare these now, as they otherwise are not. */
+extern __typeof (cosf128) __ieee754_cosf128;
+extern __typeof (asinhf128) __ieee754_asinhf128;
+
+F128_REDIR (__ieee754_asinhf128)
+F128_REDIR (__ieee754_cosf128)
+F128_REDIR (__asinhf128)
+F128_REDIR (__atanf128)
+F128_REDIR (__cbrtf128)
+F128_REDIR (__ceilf128)
+F128_REDIR (__cosf128)
+F128_REDIR (__erfcf128)
+F128_REDIR (__erff128)
+F128_REDIR (__expf128)
+F128_REDIR (__expm1f128)
+F128_REDIR (__fabsf128)
+F128_REDIR (__fdimf128)
+F128_REDIR (__floorf128)
+F128_REDIR (__fmaf128)
+F128_REDIR (__fmaxf128)
+F128_REDIR (__fminf128)
+F128_REDIR (__frexpf128)
+F128_REDIR (__ldexpf128)
+F128_REDIR (__llrintf128)
+F128_REDIR (__llroundf128)
+F128_REDIR (__log1pf128)
+F128_REDIR (__logbf128)
+F128_REDIR (__logf128)
+F128_REDIR (__lrintf128)
+F128_REDIR (__lroundf128)
+F128_REDIR (__modff128)
+F128_REDIR (__nearbyintf128)
+F128_REDIR (__remquof128)
+F128_REDIR (__rintf128)
+F128_REDIR (__roundevenf128)
+F128_REDIR (__roundf128)
+F128_REDIR (__scalblnf128)
+F128_REDIR (__scalbnf128)
+F128_REDIR (__sincosf128)
+F128_REDIR (__sinf128)
+F128_REDIR (__sqrtf128)
+F128_REDIR (__tanhf128)
+F128_REDIR (__tanf128)
+F128_REDIR (__truncf128)
+F128_REDIR (__lgamma_productf128)
+F128_REDIR (__mpn_extract_float128)
+
+#include <float128-ifunc-redirects-mp.h>
+#include <float128-ifunc-redirects.h>
+
+#endif /* !(IS_IN(libc) && defined(_F128_ENABLE_IFUNC) */
+
+#endif /* _FLOAT128_PRIVATE_PPC64LE */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math-type-macros-float128.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math-type-macros-float128.h
new file mode 100644
index 0000000000..6185185bc3
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math-type-macros-float128.h
@@ -0,0 +1,120 @@ 
+/* _Float128 overrides for float128 in ppc64le multiarch env.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _MATH_TYPE_MACROS_FLOAT128_PPC64_MULTI
+#define _MATH_TYPE_MACROS_FLOAT128_PPC64_MULTI 1
+
+#include_next <math-type-macros-float128.h>
+
+#if !IS_IN(libc) && defined(_F128_ENABLE_IFUNC)
+
+/* Include fenv.h now before turning off PLT bypass.  At
+   minimum fereaiseexcept is used today. */
+#include <fenv.h>
+
+#include <float128-ifunc-macros.h>
+
+/* Ensure local redirects are always disabled by including
+   math.h in the following manner.  */
+#undef NO_MATH_REDIRECT
+#define NO_MATH_REDIRECT
+#include <math.h>
+#undef NO_MATH_REDIRECT
+
+/* Include forward defitions to redirect complex functions
+   below.  */
+#include <complex.h>
+
+/* Declare redirects for an implementation function f which
+   has a complex analogue.  f is assumed to be prefixed
+   with '__' and is thus passed through to F128_REDIR.  */
+#define F128_C_REDIR(f) F128_REDIR (__c ## f ## f128); \
+			F128_REDIR (__ ## f ## f128); \
+
+/* Similar to F128_C_REDIR, declare the set of implementation
+   redirects for the trigonometric family f for {a,}f{,h}
+   and {a,}cf{,h} complex variants where f is sin/cos/tan.  */
+#define F128_TRIG_REDIR(f) F128_C_REDIR (a ## f); \
+			   F128_C_REDIR (a ## f ## h); \
+			   F128_C_REDIR (f); \
+			   F128_C_REDIR (f ## h);
+
+F128_TRIG_REDIR (cos)
+F128_TRIG_REDIR (sin)
+F128_TRIG_REDIR (tan)
+
+F128_C_REDIR (log);
+F128_C_REDIR (log10);
+F128_C_REDIR (exp);
+F128_C_REDIR (sqrt);
+F128_C_REDIR (pow);
+
+F128_REDIR (__atan2f128)
+F128_REDIR (__kernel_casinhf128);
+F128_REDIR (__rintf128);
+F128_REDIR (__floorf128);
+F128_REDIR (__fabsf128);
+F128_REDIR (__hypotf128);
+F128_REDIR (__scalbnf128);
+F128_REDIR (__scalblnf128);
+F128_REDIR (__sincosf128);
+F128_REDIR (__log1pf128);
+F128_REDIR (__ilogbf128);
+F128_REDIR (__ldexpf128);
+F128_REDIR (__cargf128);
+F128_REDIR (__cimagf128);
+F128_REDIR (__crealf128);
+F128_REDIR (__conjf128);
+F128_REDIR (__cprojf128);
+F128_REDIR (__cabsf128);
+F128_REDIR (__fdimf128);
+F128_REDIR (__fminf128);
+F128_REDIR (__fmaxf128);
+F128_REDIR (__fmodf128);
+F128_REDIR (__llogbf128);
+F128_REDIR (__log2f128);
+F128_REDIR (__exp10f128);
+F128_REDIR (__exp2f128);
+F128_REDIR (__j0f128);
+F128_REDIR (__j1f128);
+F128_REDIR (__jnf128);
+F128_REDIR (__y0f128);
+F128_REDIR (__y1f128);
+F128_REDIR (__ynf128);
+F128_REDIR (__lgammaf128);
+F128_REDIR_R (__lgammaf128, _r);
+F128_REDIR (__tgammaf128);
+F128_REDIR (__remainderf128);
+
+/* Assist implementations which declare additional symbols
+   which require forward declarations to redirect.  */
+extern _Float128 __wrap_scalbnf128 (_Float128, int);
+extern _Float128 __w_scalblnf128 (_Float128, long int);
+extern _Float128 __w_log1pf128 (_Float128);
+extern _Float128 __scalbf128 (_Float128, _Float128);
+F128_REDIR (__scalbf128);
+F128_REDIR (__wrap_scalbnf128);
+F128_REDIR (__w_scalblnf128);
+F128_REDIR (__w_log1pf128);
+
+/* Include the redirects shared with math_private.h users.  */
+#include <float128-ifunc-redirects.h>
+
+#endif /* !IS_IN(libc) && defined(_F128_ENABLE_IFUNC) */
+
+#endif /*_MATH_TYPE_MACROS_FLOAT128_PPC64_MULTI */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math_private.h b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math_private.h
new file mode 100644
index 0000000000..bde3fc4a06
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/math_private.h
@@ -0,0 +1,15 @@ 
+#ifndef MATH_PRIVATE_PPC64LE_MA
+#define MATH_PRIVATE_PPC64LE_MA 1
+
+#include_next <math_private.h>
+
+#if defined (_F128_ENABLE_IFUNC)
+
+/* math_private.h redeclares many float128_private.h renamed functions, but
+   we can't inclue float128_private.h as this header is used beyond
+   private float128 files.  */
+#include <float128-ifunc-redirects-mp.h>
+
+#endif
+
+#endif /* MATH_PRIVATE_PPC64LE_MA */
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-power9.c b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-power9.c
deleted file mode 100644
index 49aeb3a8f4..0000000000
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-power9.c
+++ /dev/null
@@ -1,28 +0,0 @@ 
-/* __fmaf128() PowerPC64LE POWER9 version.
-   Copyright (C) 2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <libm-alias-float128.h>
-
-#undef libm_alias_float128
-#define libm_alias_float128(a, b)
-#undef strong_alias
-#define strong_alias(a, b)
-
-#define __fmaf128 __fmaf128_power9
-
-#include <sysdeps/ieee754/float128/s_fmaf128.c>
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-ppc64.c b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-ppc64.c
deleted file mode 100644
index ab0c4d03a8..0000000000
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128-ppc64.c
+++ /dev/null
@@ -1,26 +0,0 @@ 
-/* __fmaf128() PowerPC64LE version.
-   Copyright (C) 2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#undef weak_alias
-#define weak_alias(a, b)
-#undef strong_alias
-#define strong_alias(a, b)
-
-#define __fmaf128 __fmaf128_ppc64
-
-#include <sysdeps/ieee754/float128/s_fmaf128.c>
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128.c b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128.c
deleted file mode 100644
index 3a370950f9..0000000000
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/s_fmaf128.c
+++ /dev/null
@@ -1,36 +0,0 @@ 
-/* Multiple versions of fmaf128.
-   Copyright (C) 2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <libm-alias-float128.h>
-
-#define fmaf128 __redirect_fmaf128
-#include <math.h>
-#undef fmaf128
-
-#include <math_ldbl_opt.h>
-#include "init-arch.h"
-
-extern __typeof (__redirect_fmaf128) __fmaf128_ppc64 attribute_hidden;
-extern __typeof (__redirect_fmaf128) __fmaf128_power9 attribute_hidden;
-
-libc_ifunc_redirected (__redirect_fmaf128, __fmaf128,
-		       (hwcap2 & PPC_FEATURE2_HAS_IEEE128)
-		       ? __fmaf128_power9
-		       : __fmaf128_ppc64);
-
-libm_alias_float128 (__fma, fma)
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-power9.c b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-power9.c
deleted file mode 100644
index e7414f4a59..0000000000
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-power9.c
+++ /dev/null
@@ -1,35 +0,0 @@ 
-/* POWER9 sqrt for _Float128
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   In addition to the permissions in the GNU Lesser General Public
-   License, the Free Software Foundation gives you unlimited
-   permission to link the compiled version of this file into
-   combinations with other programs, and to distribute those
-   combinations without any restriction coming from the use of this
-   file.  (The Lesser General Public License restrictions do apply in
-   other respects; for example, they cover modification of the file,
-   and distribution when not linked into a combine executable.)
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <math-type-macros-float128.h>
-
-#define __sqrtf128 __sqrtf128_power9
-
-#undef declare_mgen_alias
-#define declare_mgen_alias(a, b)
-
-#include <w_sqrt_template.c>
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-ppc64le.c b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-ppc64le.c
deleted file mode 100644
index e03ecb193f..0000000000
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128-ppc64le.c
+++ /dev/null
@@ -1,35 +0,0 @@ 
-/* PPC64LE sqrt for _Float128
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   In addition to the permissions in the GNU Lesser General Public
-   License, the Free Software Foundation gives you unlimited
-   permission to link the compiled version of this file into
-   combinations with other programs, and to distribute those
-   combinations without any restriction coming from the use of this
-   file.  (The Lesser General Public License restrictions do apply in
-   other respects; for example, they cover modification of the file,
-   and distribution when not linked into a combine executable.)
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <math-type-macros-float128.h>
-
-#define __sqrtf128 __sqrtf128_ppc64le
-
-#undef declare_mgen_alias
-#define declare_mgen_alias(a, b)
-
-#include <w_sqrt_template.c>
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128.c b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128.c
deleted file mode 100644
index e2db0a2864..0000000000
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/w_sqrtf128.c
+++ /dev/null
@@ -1,31 +0,0 @@ 
-/* Multiple versions of __sqrtf128.
-   Copyright (C) 2018-2020 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <https://www.gnu.org/licenses/>.  */
-
-#define NO_MATH_REDIRECT
-#include <math.h>
-#include "init-arch.h"
-#include <math-type-macros-float128.h>
-
-extern __typeof (__sqrtf128) __sqrtf128_ppc64le attribute_hidden;
-extern __typeof (__sqrtf128) __sqrtf128_power9 attribute_hidden;
-
-libc_ifunc (__sqrtf128,
-	    (hwcap2 & PPC_FEATURE2_ARCH_3_00)
-	    ? __sqrtf128_power9
-	    : __sqrtf128_ppc64le);
-declare_mgen_alias (__sqrt, sqrt)
diff --git a/sysdeps/powerpc/powerpc64/le/power9/Makeconfig b/sysdeps/powerpc/powerpc64/le/power9/Makeconfig
new file mode 100644
index 0000000000..a9190c7b15
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/le/power9/Makeconfig
@@ -0,0 +1,3 @@ 
+# Hint to multiarch (if used) we support power9
+# on powerpc64le.
+libc-submachine-power9 = yes