[4/8,RFC] Have libatomic working as first draft

Message ID 20240919131204.3865854-5-mmalcomson@nvidia.com
State New
Headers
Series Introduce floating point fetch_add builtins |

Commit Message

Matthew Malcomson Sept. 19, 2024, 1:12 p.m. UTC
  From: Matthew Malcomson <mmalcomson@nvidia.com>

As it stands there are still a few things to look at whether they could
be improved:
1) Need to find the exact version of automake to use.  I'm using
   automake 1.15.1 from https://ftp.gnu.org/gnu/automake/ but the
   header is claiming I'm using automake 1.15.
2) The internal naming is all a little "not right" up for floating
   point.  E.g. the SIZE() macro is no longer adding a SIZE integer
   suffix to something but instead adding a suffix representing a type.
   Not sure whether the churn to fix this is worth it -- will ask
   upstream.
3) Have not implemented the word-size compare and swap loop fallback.
   This because the implementation uses a mask and the mask is not
   always the same for any given architecture.  Hence the existing
   approach in code would not work for all floating point types.
   - I would appreciate some feedback about whether this is OK to not
     implement.  Seems reasonable to me.
4) In the existing test for the availability of an atomic fetch
   operation there are two things that I do not know why they are needed
   and hence didn't add them to the check for atomic floating point
   fetch_{add,sub}.
   I just wanted to highlight this in case I missed something.
   1) I only put the `x` register into a register with an `asm` call.
      To be honest I don't know why anything need be put into a
      register, but I didn't put the floating point value into a
      register because I didn't know of a standard GCC floating point
      register constraint that worked across all architectures.
      - Is there any need for this `asm` line (I copied from existing
        libatomic configure code without understanding).
      - Is there any need for the constant addition to be applied?
   2) I used a cast of a 1.0 floating point literal as the "addition"
      for all floating point types in the configury check.
      - Is there something subtle I'm missing about this?
        (I *think* it's fine, but felt like this seemed to be a place
        where I could trip up without knowing).

Description of things done in this commit:

We implement the new floating point builtins around fetch_add.  This is
mostly a configure/makefile change.  The main overview of the changes is
that we create a new list of suffixes (_fpf, _fp, _fpl, _fp16b, _fp16,
_fp32, _fp64, _fp128, _fp32x, _fp64x) and re-compile fadd_n.c and
fsub_n.c for these suffixes.
The existing machinery for checking whether a given atomic builtin is
implemented is extended to check for these same suffixes on the atomic
builtins.  The existing machinery for generating atomic fetch_<op>
implementations using a given suffix and general patterns is also
re-used (n.b. with the exception that the implementation based on
a compare and exchange of a word is not implemented because the
pre-processor does not know the size of the floating point types).

The AArch64 backend is updated slightly.  It didn't build because it
assumed there was some IFUNC for all operations implemented (and didn't
have any IFUNC for the new floating point operations).

The new functions are advertised as LIBATOMIC_1.3 in the linker map for
the dynamic library.

Signed-off-by: Matthew Malcomson <mmalcomson@nvidia.com>
---
 libatomic/Makefile.am                        |    6 +-
 libatomic/Makefile.in                        |   12 +-
 libatomic/acinclude.m4                       |   49 +
 libatomic/auto-config.h.in                   |   84 +-
 libatomic/config/linux/aarch64/host-config.h |    2 +
 libatomic/configure                          | 1153 +++++++++++++++++-
 libatomic/configure.ac                       |    4 +
 libatomic/fadd_n.c                           |   23 +
 libatomic/fop_n.c                            |    5 +-
 libatomic/fsub_n.c                           |   23 +
 libatomic/libatomic.map                      |   44 +
 libatomic/libatomic_i.h                      |   58 +
 libatomic/testsuite/Makefile.in              |    1 +
 13 files changed, 1392 insertions(+), 72 deletions(-)
  

Patch

diff --git a/libatomic/Makefile.am b/libatomic/Makefile.am
index efadd9dcd48..ec24f1da86b 100644
--- a/libatomic/Makefile.am
+++ b/libatomic/Makefile.am
@@ -110,6 +110,7 @@  IFUNC_OPT	= $(word $(PAT_S),$(IFUNC_OPTIONS))
 M_SIZE		= -DN=$(PAT_N)
 M_IFUNC		= $(if $(PAT_S),$(IFUNC_DEF) $(IFUNC_OPT))
 M_FILE		= $(PAT_BASE)_n.c
+M_FLOATING      = $(if $(findstring $(PAT_N),$(FPSUFFIXES)),-DFLOATING)
 
 # The lack of explicit dependency on the source file means that VPATH cannot
 # work properly.  Instead, perform this operation by hand.  First, collect a
@@ -120,10 +121,13 @@  all_c_files	:= $(foreach dir,$(search_path),$(wildcard $(dir)/*.c))
 M_SRC		= $(firstword $(filter %/$(M_FILE), $(all_c_files)))
 
 %_.lo: Makefile
-	$(LTCOMPILE) $(M_DEPS) $(M_SIZE) $(M_IFUNC) -c -o $@ $(M_SRC)
+	$(LTCOMPILE) $(M_DEPS) $(M_SIZE) $(M_FLOATING) $(M_IFUNC) -c -o $@ $(M_SRC)
 
 ## Include all of the sizes in the "normal" set of compilation flags.
 libatomic_la_LIBADD = $(foreach s,$(SIZES),$(addsuffix _$(s)_.lo,$(SIZEOBJS)))
+# Include the special floating point "sizes" as a set of compilation flags.
+FPOBJS = fadd fsub
+libatomic_la_LIBADD += $(foreach suf,$(FPSUFFIXES),$(addsuffix _$(suf)_.lo,$(FPOBJS)))
 
 ## On a target-specific basis, include alternates to be selected by IFUNC.
 if HAVE_IFUNC
diff --git a/libatomic/Makefile.in b/libatomic/Makefile.in
index 9798e7c09e9..c70ebf9cc8b 100644
--- a/libatomic/Makefile.in
+++ b/libatomic/Makefile.in
@@ -289,6 +289,7 @@  ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FPSUFFIXES = @FPSUFFIXES@
 GREP = @GREP@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@
@@ -441,6 +442,7 @@  IFUNC_OPT = $(word $(PAT_S),$(IFUNC_OPTIONS))
 M_SIZE = -DN=$(PAT_N)
 M_IFUNC = $(if $(PAT_S),$(IFUNC_DEF) $(IFUNC_OPT))
 M_FILE = $(PAT_BASE)_n.c
+M_FLOATING = $(if $(findstring $(PAT_N),$(FPSUFFIXES)),-DFLOATING)
 
 # The lack of explicit dependency on the source file means that VPATH cannot
 # work properly.  Instead, perform this operation by hand.  First, collect a
@@ -450,8 +452,12 @@  all_c_files := $(foreach dir,$(search_path),$(wildcard $(dir)/*.c))
 # Then sort through them to find the one we want, and select the first.
 M_SRC = $(firstword $(filter %/$(M_FILE), $(all_c_files)))
 libatomic_la_LIBADD = $(foreach s,$(SIZES),$(addsuffix \
-	_$(s)_.lo,$(SIZEOBJS))) $(am__append_1) $(am__append_2) \
-	$(am__append_3) $(am__append_4)
+	_$(s)_.lo,$(SIZEOBJS))) $(foreach \
+	suf,$(FPSUFFIXES),$(addsuffix _$(suf)_.lo,$(FPOBJS))) \
+	$(am__append_1) $(am__append_2) $(am__append_3) \
+	$(am__append_4)
+# Include the special floating point "sizes" as a set of compilation flags.
+FPOBJS = fadd fsub
 @ARCH_AARCH64_LINUX_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=armv8-a+lse
 @ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=armv7-a+fp -DHAVE_KERNEL64
 @ARCH_I386_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=i586
@@ -894,7 +900,7 @@  vpath % $(strip $(search_path))
 -include $(wildcard $(DEPDIR)/*.Ppo)
 
 %_.lo: Makefile
-	$(LTCOMPILE) $(M_DEPS) $(M_SIZE) $(M_IFUNC) -c -o $@ $(M_SRC)
+	$(LTCOMPILE) $(M_DEPS) $(M_SIZE) $(M_FLOATING) $(M_IFUNC) -c -o $@ $(M_SRC)
 
 # Amend the automake generated all-multi rule to guarantee that all-multi
 # is not run in parallel with the %_.lo rules which generate $(DEPDIR)/*.Ppo
diff --git a/libatomic/acinclude.m4 b/libatomic/acinclude.m4
index f35ab5b60a5..59445f68b85 100644
--- a/libatomic/acinclude.m4
+++ b/libatomic/acinclude.m4
@@ -17,6 +17,23 @@  AC_DEFUN([LIBAT_FORALL_MODES],
   $1(TI,16)]
 )
 dnl
+dnl Iterate over all the floating types that we want to check.
+dnl Arguments to the function given are the floting point type and the suffix
+dnl used to identify this floating point type.
+dnl
+AC_DEFUN([LIBAT_FOR_FLOATING_TYPES],
+  [$1(float,fpf)
+  $1(double,fp)
+  $1(long double,fpl)
+  $1(bfloat16,fpf16b)
+  $1(_Float16,fpf16)
+  $1(_Float32,fpf32)
+  $1(_Float64,fpf64)
+  $1(_Float128,fpf128)
+  $1(_Float32x,fpf32x)
+  $1(_Float64x,fpf64x)]
+)
+dnl
 dnl Check for builtin types by mode.
 dnl
 dnl A less interesting of size checking than autoconf normally provides.
@@ -33,6 +50,20 @@  AC_DEFUN([LIBAT_HAVE_INT_MODE],[
     SIZES="$SIZES $2"
   fi
 ])
+dnl
+dnl Check if built in floating point types are defined for this target.
+dnl
+AC_DEFUN([LIBAT_HAVE_FLOATING_TYPE],[
+  AC_CACHE_CHECK([for type $1],[libat_cv_have_type_$2],
+    [AC_COMPILE_IFELSE([AC_LANG_SOURCE([$1 x;])],
+      [libat_cv_have_type_$2=yes],[libat_cv_have_type_$2=no])])
+  LIBAT_DEFINE_YESNO([HAVE_$2], [$libat_cv_have_type_$2],
+      [Have support for floating type $1.])
+  if test x$libat_cv_have_type_$2 = xyes; then
+    FPSUFFIXES="$FPSUFFIXES $2"
+  fi
+])
+
 dnl
 dnl Check for atomic builtins.
 dnl See:
@@ -154,6 +185,24 @@  AC_DEFUN([LIBAT_HAVE_ATOMIC_FETCH_ADD],[
   AH_BOTTOM([#define MAYBE_HAVE_ATOMIC_FETCH_ADD_$2 HAVE_ATOMIC_FETCH_ADD_$2])
 ])
 
+dnl
+dnl Test if we have __atomic_fetch_add for floating point type $1, with suffix $2
+dnl
+AC_DEFUN([LIBAT_HAVE_ATOMIC_FETCH_ADDSUB_FP],[
+  LIBAT_TEST_ATOMIC_BUILTIN([for __atomic_fetch_{add,sub} for floating type $1],
+    [libat_cv_have_at_faddsub_$2], [
+      $1 *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, ($1)(1.0), 0);
+      __atomic_add_fetch (x, ($1)(1.0), 0);
+      __atomic_fetch_sub (x, ($1)(1.0), 0);
+      __atomic_sub_fetch (x, ($1)(1.0), 0);
+    ])
+LIBAT_DEFINE_YESNO([HAVE_ATOMIC_FETCH_ADDSUB_$2], [$libat_cv_have_at_faddsub_$2],
+        [Have __atomic_fetch_{add,sub} for floating point type $1.])
+  AH_BOTTOM([#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_$2 HAVE_ATOMIC_FETCH_ADDSUB_$2])
+])
+
 dnl
 dnl Test if we have __atomic_fetch_op for all op for mode $1, size $2
 dnl
diff --git a/libatomic/auto-config.h.in b/libatomic/auto-config.h.in
index ab3424a759e..fe56b31f4b6 100644
--- a/libatomic/auto-config.h.in
+++ b/libatomic/auto-config.h.in
@@ -33,6 +33,36 @@ 
 /* Have __atomic_exchange for 8 byte integers. */
 #undef HAVE_ATOMIC_EXCHANGE_8
 
+/* Have __atomic_fetch_{add,sub} for floating point type double. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fp
+
+/* Have __atomic_fetch_{add,sub} for floating point type float. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf
+
+/* Have __atomic_fetch_{add,sub} for floating point type _Float128. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf128
+
+/* Have __atomic_fetch_{add,sub} for floating point type _Float16. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf16
+
+/* Have __atomic_fetch_{add,sub} for floating point type bfloat16. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf16b
+
+/* Have __atomic_fetch_{add,sub} for floating point type _Float32. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf32
+
+/* Have __atomic_fetch_{add,sub} for floating point type _Float32x. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf32x
+
+/* Have __atomic_fetch_{add,sub} for floating point type _Float64. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf64
+
+/* Have __atomic_fetch_{add,sub} for floating point type _Float64x. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpf64x
+
+/* Have __atomic_fetch_{add,sub} for floating point type long double. */
+#undef HAVE_ATOMIC_FETCH_ADDSUB_fpl
+
 /* Have __atomic_fetch_add for 1 byte integers. */
 #undef HAVE_ATOMIC_FETCH_ADD_1
 
@@ -153,6 +183,36 @@ 
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Have support for floating type double. */
+#undef HAVE_fp
+
+/* Have support for floating type float. */
+#undef HAVE_fpf
+
+/* Have support for floating type _Float128. */
+#undef HAVE_fpf128
+
+/* Have support for floating type _Float16. */
+#undef HAVE_fpf16
+
+/* Have support for floating type bfloat16. */
+#undef HAVE_fpf16b
+
+/* Have support for floating type _Float32. */
+#undef HAVE_fpf32
+
+/* Have support for floating type _Float32x. */
+#undef HAVE_fpf32x
+
+/* Have support for floating type _Float64. */
+#undef HAVE_fpf64
+
+/* Have support for floating type _Float64x. */
+#undef HAVE_fpf64x
+
+/* Have support for floating type long double. */
+#undef HAVE_fpl
+
 /* Define ifunc resolver function argument. */
 #undef IFUNC_RESOLVER_ARGS
 
@@ -281,12 +341,32 @@ 
 
 #define MAYBE_HAVE_ATOMIC_FETCH_OP_16 HAVE_ATOMIC_FETCH_OP_16
 
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf HAVE_ATOMIC_FETCH_ADDSUB_fpf
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fp HAVE_ATOMIC_FETCH_ADDSUB_fp
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpl HAVE_ATOMIC_FETCH_ADDSUB_fpl
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf16b HAVE_ATOMIC_FETCH_ADDSUB_fpf16b
+
+#define FAST_ATOMIC_LDST_2 HAVE_ATOMIC_LDST_2
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf16 HAVE_ATOMIC_FETCH_ADDSUB_fpf16
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf32 HAVE_ATOMIC_FETCH_ADDSUB_fpf32
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf64 HAVE_ATOMIC_FETCH_ADDSUB_fpf64
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf128 HAVE_ATOMIC_FETCH_ADDSUB_fpf128
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf32x HAVE_ATOMIC_FETCH_ADDSUB_fpf32x
+
+#define MAYBE_HAVE_ATOMIC_FETCH_ADDSUB_fpf64x HAVE_ATOMIC_FETCH_ADDSUB_fpf64x
+
 #ifndef WORDS_BIGENDIAN
 #define WORDS_BIGENDIAN 0
 #endif
 
-#define FAST_ATOMIC_LDST_2 HAVE_ATOMIC_LDST_2
-
 #define MAYBE_HAVE_ATOMIC_LDST_4 HAVE_ATOMIC_LDST_4
 
 #define FAST_ATOMIC_LDST_4 HAVE_ATOMIC_LDST_4
diff --git a/libatomic/config/linux/aarch64/host-config.h b/libatomic/config/linux/aarch64/host-config.h
index 93f367d5878..639ed3efeaa 100644
--- a/libatomic/config/linux/aarch64/host-config.h
+++ b/libatomic/config/linux/aarch64/host-config.h
@@ -77,6 +77,8 @@  typedef struct __ifunc_arg_t {
 #   define IFUNC_NCOND(N)	0
 #   define IFUNC_ALT		1
 #  endif
+# elif defined(FLOATING)
+#  define IFUNC_NCOND(N)        0
 # else
 #  define IFUNC_COND_1		(hwcap & HWCAP_ATOMICS)
 #  define IFUNC_NCOND(N)	1
diff --git a/libatomic/configure b/libatomic/configure
index d579bab96f8..f68c18295f7 100755
--- a/libatomic/configure
+++ b/libatomic/configure
@@ -644,6 +644,7 @@  ARCH_AARCH64_LINUX_TRUE
 HAVE_IFUNC_FALSE
 HAVE_IFUNC_TRUE
 tmake_file
+FPSUFFIXES
 SIZES
 XLDFLAGS
 XCFLAGS
@@ -11456,7 +11457,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11459 "configure"
+#line 11460 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11562,7 +11563,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11565 "configure"
+#line 11566 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12665,6 +12666,317 @@  _ACEOF
 
 
 
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type float" >&5
+$as_echo_n "checking for type float... " >&6; }
+if ${libat_cv_have_type_fpf+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+float x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf=yes
+else
+  libat_cv_have_type_fpf=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf" >&5
+$as_echo "$libat_cv_have_type_fpf" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type double" >&5
+$as_echo_n "checking for type double... " >&6; }
+if ${libat_cv_have_type_fp+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+double x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fp=yes
+else
+  libat_cv_have_type_fp=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fp" >&5
+$as_echo "$libat_cv_have_type_fp" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fp | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fp $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fp = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fp"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type long double" >&5
+$as_echo_n "checking for type long double... " >&6; }
+if ${libat_cv_have_type_fpl+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+long double x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpl=yes
+else
+  libat_cv_have_type_fpl=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpl" >&5
+$as_echo "$libat_cv_have_type_fpl" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpl | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpl $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpl = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpl"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type bfloat16" >&5
+$as_echo_n "checking for type bfloat16... " >&6; }
+if ${libat_cv_have_type_fpf16b+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+bfloat16 x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf16b=yes
+else
+  libat_cv_have_type_fpf16b=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf16b" >&5
+$as_echo "$libat_cv_have_type_fpf16b" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf16b | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf16b $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf16b = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf16b"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type _Float16" >&5
+$as_echo_n "checking for type _Float16... " >&6; }
+if ${libat_cv_have_type_fpf16+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+_Float16 x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf16=yes
+else
+  libat_cv_have_type_fpf16=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf16" >&5
+$as_echo "$libat_cv_have_type_fpf16" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf16 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf16 $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf16 = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf16"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type _Float32" >&5
+$as_echo_n "checking for type _Float32... " >&6; }
+if ${libat_cv_have_type_fpf32+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+_Float32 x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf32=yes
+else
+  libat_cv_have_type_fpf32=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf32" >&5
+$as_echo "$libat_cv_have_type_fpf32" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf32 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf32 $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf32 = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf32"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type _Float64" >&5
+$as_echo_n "checking for type _Float64... " >&6; }
+if ${libat_cv_have_type_fpf64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+_Float64 x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf64=yes
+else
+  libat_cv_have_type_fpf64=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf64" >&5
+$as_echo "$libat_cv_have_type_fpf64" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf64 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf64 $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf64 = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf64"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type _Float128" >&5
+$as_echo_n "checking for type _Float128... " >&6; }
+if ${libat_cv_have_type_fpf128+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+_Float128 x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf128=yes
+else
+  libat_cv_have_type_fpf128=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf128" >&5
+$as_echo "$libat_cv_have_type_fpf128" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf128 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf128 $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf128 = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf128"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type _Float32x" >&5
+$as_echo_n "checking for type _Float32x... " >&6; }
+if ${libat_cv_have_type_fpf32x+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+_Float32x x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf32x=yes
+else
+  libat_cv_have_type_fpf32x=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf32x" >&5
+$as_echo "$libat_cv_have_type_fpf32x" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf32x | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf32x $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf32x = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf32x"
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type _Float64x" >&5
+$as_echo_n "checking for type _Float64x... " >&6; }
+if ${libat_cv_have_type_fpf64x+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+_Float64x x;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libat_cv_have_type_fpf64x=yes
+else
+  libat_cv_have_type_fpf64x=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_type_fpf64x" >&5
+$as_echo "$libat_cv_have_type_fpf64x" >&6; }
+
+  yesno=`echo $libat_cv_have_type_fpf64x | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_fpf64x $yesno
+_ACEOF
+
+
+  if test x$libat_cv_have_type_fpf64x = xyes; then
+    FPSUFFIXES="$FPSUFFIXES fpf64x"
+  fi
+
+
+
 # Check for compiler builtins of atomic operations.
 
   # Do link tests if possible, instead asm tests, limited to some platforms
@@ -14697,81 +15009,793 @@  _ACEOF
 
 
 
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
-$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
-if ${ac_cv_c_bigendian+:} false; then :
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type float" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type float... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-  ac_cv_c_bigendian=unknown
-    # See if we're dealing with a universal compiler.
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#ifndef __APPLE_CC__
-	       not a universal capable compiler
-	     #endif
-	     typedef int dummy;
-
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
 
-	# Check for potential -arch flags.  It is not universal unless
-	# there are at least two -arch flags with different values.
-	ac_arch=
-	ac_prev=
-	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
-	 if test -n "$ac_prev"; then
-	   case $ac_word in
-	     i?86 | x86_64 | ppc | ppc64)
-	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
-		 ac_arch=$ac_word
-	       else
-		 ac_cv_c_bigendian=universal
-		 break
-	       fi
-	       ;;
-	   esac
-	   ac_prev=
-	 elif test "x$ac_word" = "x-arch"; then
-	   ac_prev=arch
-	 fi
-       done
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-    if test $ac_cv_c_bigendian = unknown; then
-      # See if sys/param.h defines the BYTE_ORDER macro.
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#include <sys/types.h>
-	     #include <sys/param.h>
 
 int
 main ()
 {
-#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
-		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
-		     && LITTLE_ENDIAN)
-	      bogus endian macros
-	     #endif
+
+      float *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (float)(1.0), 0);
+      __atomic_add_fetch (x, (float)(1.0), 0);
+      __atomic_fetch_sub (x, (float)(1.0), 0);
+      __atomic_sub_fetch (x, (float)(1.0), 0);
 
   ;
   return 0;
 }
 _ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  # It does; now see whether it defined to BIG_ENDIAN or not.
-	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <sys/types.h>
-		#include <sys/param.h>
-
-int
-main ()
-{
-#if BYTE_ORDER != BIG_ENDIAN
-		 not big endian
-		#endif
-
-  ;
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type double" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type double... " >&6; }
+if ${libat_cv_have_at_faddsub_fp+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      double *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (double)(1.0), 0);
+      __atomic_add_fetch (x, (double)(1.0), 0);
+      __atomic_fetch_sub (x, (double)(1.0), 0);
+      __atomic_sub_fetch (x, (double)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fp=yes
+      else
+        eval libat_cv_have_at_faddsub_fp=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fp=no
+        else
+	  eval libat_cv_have_at_faddsub_fp=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fp=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fp" >&5
+$as_echo "$libat_cv_have_at_faddsub_fp" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fp | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fp $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type long double" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type long double... " >&6; }
+if ${libat_cv_have_at_faddsub_fpl+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      long double *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (long double)(1.0), 0);
+      __atomic_add_fetch (x, (long double)(1.0), 0);
+      __atomic_fetch_sub (x, (long double)(1.0), 0);
+      __atomic_sub_fetch (x, (long double)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpl=yes
+      else
+        eval libat_cv_have_at_faddsub_fpl=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpl=no
+        else
+	  eval libat_cv_have_at_faddsub_fpl=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpl=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpl" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpl" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpl | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpl $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type bfloat16" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type bfloat16... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf16b+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      bfloat16 *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (bfloat16)(1.0), 0);
+      __atomic_add_fetch (x, (bfloat16)(1.0), 0);
+      __atomic_fetch_sub (x, (bfloat16)(1.0), 0);
+      __atomic_sub_fetch (x, (bfloat16)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf16b=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf16b=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf16b=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf16b=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf16b=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf16b" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf16b" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf16b | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf16b $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type _Float16" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type _Float16... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf16+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      _Float16 *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (_Float16)(1.0), 0);
+      __atomic_add_fetch (x, (_Float16)(1.0), 0);
+      __atomic_fetch_sub (x, (_Float16)(1.0), 0);
+      __atomic_sub_fetch (x, (_Float16)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf16=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf16=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf16=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf16=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf16=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf16" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf16" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf16 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf16 $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type _Float32" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type _Float32... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf32+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      _Float32 *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (_Float32)(1.0), 0);
+      __atomic_add_fetch (x, (_Float32)(1.0), 0);
+      __atomic_fetch_sub (x, (_Float32)(1.0), 0);
+      __atomic_sub_fetch (x, (_Float32)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf32=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf32=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf32=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf32=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf32=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf32" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf32" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf32 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf32 $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type _Float64" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type _Float64... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf64+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      _Float64 *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (_Float64)(1.0), 0);
+      __atomic_add_fetch (x, (_Float64)(1.0), 0);
+      __atomic_fetch_sub (x, (_Float64)(1.0), 0);
+      __atomic_sub_fetch (x, (_Float64)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf64=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf64=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf64=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf64=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf64=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf64" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf64" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf64 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf64 $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type _Float128" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type _Float128... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf128+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      _Float128 *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (_Float128)(1.0), 0);
+      __atomic_add_fetch (x, (_Float128)(1.0), 0);
+      __atomic_fetch_sub (x, (_Float128)(1.0), 0);
+      __atomic_sub_fetch (x, (_Float128)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf128=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf128=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf128=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf128=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf128=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf128" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf128" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf128 | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf128 $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type _Float32x" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type _Float32x... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf32x+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      _Float32x *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (_Float32x)(1.0), 0);
+      __atomic_add_fetch (x, (_Float32x)(1.0), 0);
+      __atomic_fetch_sub (x, (_Float32x)(1.0), 0);
+      __atomic_sub_fetch (x, (_Float32x)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf32x=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf32x=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf32x=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf32x=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf32x=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf32x" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf32x" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf32x | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf32x $yesno
+_ACEOF
+
+
+
+
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __atomic_fetch_{add,sub} for floating type _Float64x" >&5
+$as_echo_n "checking for __atomic_fetch_{add,sub} for floating type _Float64x... " >&6; }
+if ${libat_cv_have_at_faddsub_fpf64x+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+      _Float64x *x;
+      asm("" : "=g"(x));
+      __atomic_fetch_add (x, (_Float64x)(1.0), 0);
+      __atomic_add_fetch (x, (_Float64x)(1.0), 0);
+      __atomic_fetch_sub (x, (_Float64x)(1.0), 0);
+      __atomic_sub_fetch (x, (_Float64x)(1.0), 0);
+
+  ;
+  return 0;
+}
+_ACEOF
+    if test x$atomic_builtins_link_tests = xyes; then
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        eval libat_cv_have_at_faddsub_fpf64x=yes
+      else
+        eval libat_cv_have_at_faddsub_fpf64x=no
+      fi
+    else
+      old_CFLAGS="$CFLAGS"
+      # Compile unoptimized.
+      CFLAGS="$CFLAGS -O0 -S"
+      if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+        if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+	  eval libat_cv_have_at_faddsub_fpf64x=no
+        else
+	  eval libat_cv_have_at_faddsub_fpf64x=yes
+        fi
+      else
+        eval libat_cv_have_at_faddsub_fpf64x=no
+      fi
+      CFLAGS="$old_CFLAGS"
+    fi
+    rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libat_cv_have_at_faddsub_fpf64x" >&5
+$as_echo "$libat_cv_have_at_faddsub_fpf64x" >&6; }
+
+
+  yesno=`echo $libat_cv_have_at_faddsub_fpf64x | tr 'yesno' '1  0 '`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ATOMIC_FETCH_ADDSUB_fpf64x $yesno
+_ACEOF
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_bigendian=unknown
+    # See if we're dealing with a universal compiler.
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifndef __APPLE_CC__
+	       not a universal capable compiler
+	     #endif
+	     typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+	# Check for potential -arch flags.  It is not universal unless
+	# there are at least two -arch flags with different values.
+	ac_arch=
+	ac_prev=
+	for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+	 if test -n "$ac_prev"; then
+	   case $ac_word in
+	     i?86 | x86_64 | ppc | ppc64)
+	       if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+		 ac_arch=$ac_word
+	       else
+		 ac_cv_c_bigendian=universal
+		 break
+	       fi
+	       ;;
+	   esac
+	   ac_prev=
+	 elif test "x$ac_word" = "x-arch"; then
+	   ac_prev=arch
+	 fi
+       done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    if test $ac_cv_c_bigendian = unknown; then
+      # See if sys/param.h defines the BYTE_ORDER macro.
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+	     #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+		     && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+		     && LITTLE_ENDIAN)
+	      bogus endian macros
+	     #endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+		#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+		 not big endian
+		#endif
+
+  ;
   return 0;
 }
 _ACEOF
@@ -15761,6 +16785,7 @@  XCFLAGS="$XCFLAGS $XPCFLAGS"
 
 
 
+
 # Conditionalize the makefile for this target machine.
 tmake_file_=
 for f in ${tmake_file}
diff --git a/libatomic/configure.ac b/libatomic/configure.ac
index 32a2cdb13ae..597f88b073e 100644
--- a/libatomic/configure.ac
+++ b/libatomic/configure.ac
@@ -196,6 +196,7 @@  AC_CHECK_HEADERS([fenv.h])
 
 # Check for common type sizes
 LIBAT_FORALL_MODES([LIBAT_HAVE_INT_MODE])
+LIBAT_FOR_FLOATING_TYPES([LIBAT_HAVE_FLOATING_TYPE])
 
 # Check for compiler builtins of atomic operations.
 LIBAT_TEST_ATOMIC_INIT
@@ -205,6 +206,8 @@  LIBAT_FORALL_MODES([LIBAT_HAVE_ATOMIC_EXCHANGE])
 LIBAT_FORALL_MODES([LIBAT_HAVE_ATOMIC_CAS])
 LIBAT_FORALL_MODES([LIBAT_HAVE_ATOMIC_FETCH_ADD])
 LIBAT_FORALL_MODES([LIBAT_HAVE_ATOMIC_FETCH_OP])
+LIBAT_FOR_FLOATING_TYPES([LIBAT_HAVE_ATOMIC_FETCH_ADDSUB_FP])
+
 
 AC_C_BIGENDIAN
 # I don't like the default behaviour of WORDS_BIGENDIAN undefined for LE.
@@ -273,6 +276,7 @@  AC_SUBST(XCFLAGS)
 AC_SUBST(XLDFLAGS)
 AC_SUBST(LIBS)
 AC_SUBST(SIZES)
+AC_SUBST(FPSUFFIXES)
 
 # Conditionalize the makefile for this target machine.
 tmake_file_=
diff --git a/libatomic/fadd_n.c b/libatomic/fadd_n.c
index 32b75cec654..bae6b95d728 100644
--- a/libatomic/fadd_n.c
+++ b/libatomic/fadd_n.c
@@ -28,6 +28,28 @@ 
 #define NAME	add
 #define OP(X,Y)	((X) + (Y))
 
+/*
+  When compiling this file for the floating point operations, some of the names
+  become a bit of a misnomer.
+  - SIZE now logically creates a token suffixed by a "floating point suffix"
+    rather than suffixed by "size".
+  - UTYPE is now something like U_fp for double and they are typedef'd to the
+    corresponding floating point type.
+  - N is no longer a number, but instead a floating point suffix.
+*/
+#if FLOATING
+# define HAVE_ATOMIC_FETCH_OP_fpf HAVE_ATOMIC_FETCH_ADDSUB_fpf
+# define HAVE_ATOMIC_FETCH_OP_fpf HAVE_ATOMIC_FETCH_ADDSUB_fpf
+# define HAVE_ATOMIC_FETCH_OP_fp HAVE_ATOMIC_FETCH_ADDSUB_fp
+# define HAVE_ATOMIC_FETCH_OP_fpl HAVE_ATOMIC_FETCH_ADDSUB_fpl
+# define HAVE_ATOMIC_FETCH_OP_fpf16 HAVE_ATOMIC_FETCH_ADDSUB_fpf16
+# define HAVE_ATOMIC_FETCH_OP_fpf32 HAVE_ATOMIC_FETCH_ADDSUB_fpf32
+# define HAVE_ATOMIC_FETCH_OP_fpf64 HAVE_ATOMIC_FETCH_ADDSUB_fpf64
+# define HAVE_ATOMIC_FETCH_OP_fpf128 HAVE_ATOMIC_FETCH_ADDSUB_fpf128
+# define HAVE_ATOMIC_FETCH_OP_fpf32x HAVE_ATOMIC_FETCH_ADDSUB_fpf32x
+# define HAVE_ATOMIC_FETCH_OP_fpf64x HAVE_ATOMIC_FETCH_ADDSUB_fpf64x
+#endif
+
 /* Defer to HAVE_ATOMIC_FETCH_ADD, which some targets implement specially,
    even if HAVE_ATOMIC_FETCH_OP is not defined.  */
 #if !SIZE(HAVE_ATOMIC_FETCH_OP)
@@ -44,4 +66,5 @@ 
 #endif
 
 #include "fop_n.c"
+
 #undef LAT_FADD_N
diff --git a/libatomic/fop_n.c b/libatomic/fop_n.c
index fefff3a57a4..5cba1dcb3c9 100644
--- a/libatomic/fop_n.c
+++ b/libatomic/fop_n.c
@@ -104,8 +104,9 @@  SIZE(C3(libat_,NAME,_fetch)) (UTYPE *mptr, UTYPE opval, int smodel)
 
 
 /* If this type is no larger than word-sized, fall back to a word-sized
-   compare-and-swap loop.  */
-#if !DONE && N < WORDSIZE && defined(atomic_compare_exchange_w)
+   compare-and-swap loop.  Avoid doing this with floating point types since the
+   preprocessor does not know the size of those types.  */
+#if !DONE && !defined(FLOATING) && N < WORDSIZE && defined(atomic_compare_exchange_w)
 UTYPE
 SIZE(C2(libat_fetch_,NAME)) (UTYPE *mptr, UTYPE opval, int smodel)
 {
diff --git a/libatomic/fsub_n.c b/libatomic/fsub_n.c
index 49b375a543f..bc99f22797e 100644
--- a/libatomic/fsub_n.c
+++ b/libatomic/fsub_n.c
@@ -1,5 +1,28 @@ 
 #define LAT_FSUB_N
 #define NAME	sub
 #define OP(X,Y)	((X) - (Y))
+
+/*
+  When compiling this file for the floating point operations, some of the names
+  become a bit of a misnomer.
+  - SIZE now logically creates a token suffixed by a "floating point suffix"
+    rather than suffixed by "size".
+  - UTYPE is now something like U_fp for double and they are typedef'd to the
+    corresponding floating point type.
+  - N is no longer a number, but instead a floating point suffix.
+*/
+#if FLOATING
+# define HAVE_ATOMIC_FETCH_OP_fpf HAVE_ATOMIC_FETCH_ADDSUB_fpf
+# define HAVE_ATOMIC_FETCH_OP_fpf HAVE_ATOMIC_FETCH_ADDSUB_fpf
+# define HAVE_ATOMIC_FETCH_OP_fp HAVE_ATOMIC_FETCH_ADDSUB_fp
+# define HAVE_ATOMIC_FETCH_OP_fpl HAVE_ATOMIC_FETCH_ADDSUB_fpl
+# define HAVE_ATOMIC_FETCH_OP_fpf16 HAVE_ATOMIC_FETCH_ADDSUB_fpf16
+# define HAVE_ATOMIC_FETCH_OP_fpf32 HAVE_ATOMIC_FETCH_ADDSUB_fpf32
+# define HAVE_ATOMIC_FETCH_OP_fpf64 HAVE_ATOMIC_FETCH_ADDSUB_fpf64
+# define HAVE_ATOMIC_FETCH_OP_fpf128 HAVE_ATOMIC_FETCH_ADDSUB_fpf128
+# define HAVE_ATOMIC_FETCH_OP_fpf32x HAVE_ATOMIC_FETCH_ADDSUB_fpf32x
+# define HAVE_ATOMIC_FETCH_OP_fpf64x HAVE_ATOMIC_FETCH_ADDSUB_fpf64x
+#endif
+
 #include "fop_n.c"
 #undef LAT_FSUB_N
diff --git a/libatomic/libatomic.map b/libatomic/libatomic.map
index 39e7c2c6b9a..b08fb8d6bc8 100644
--- a/libatomic/libatomic.map
+++ b/libatomic/libatomic.map
@@ -108,3 +108,47 @@  LIBATOMIC_1.2 {
 	atomic_flag_clear;
 	atomic_flag_clear_explicit;
 } LIBATOMIC_1.1;
+
+LIBATOMIC_1.3 {
+  global:
+	__atomic_add_fetch_fpf;
+	__atomic_add_fetch_fp;
+	__atomic_add_fetch_fpl;
+	__atomic_add_fetch_fpf16b;
+	__atomic_add_fetch_fpf16;
+	__atomic_add_fetch_fpf32;
+	__atomic_add_fetch_fpf64;
+	__atomic_add_fetch_fpf128;
+	__atomic_add_fetch_fpf32x;
+	__atomic_add_fetch_fpf64x;
+	__atomic_fetch_add_fpf;
+	__atomic_fetch_add_fp;
+	__atomic_fetch_add_fpl;
+	__atomic_fetch_add_fpf16b;
+	__atomic_fetch_add_fpf16;
+	__atomic_fetch_add_fpf32;
+	__atomic_fetch_add_fpf64;
+	__atomic_fetch_add_fpf128;
+	__atomic_fetch_add_fpf32x;
+	__atomic_fetch_add_fpf64x;
+	__atomic_fetch_sub_fpf;
+	__atomic_fetch_sub_fp;
+	__atomic_fetch_sub_fpl;
+	__atomic_fetch_sub_fpf16b;
+	__atomic_fetch_sub_fpf16;
+	__atomic_fetch_sub_fpf32;
+	__atomic_fetch_sub_fpf64;
+	__atomic_fetch_sub_fpf128;
+	__atomic_fetch_sub_fpf32x;
+	__atomic_fetch_sub_fpf64x;
+	__atomic_sub_fetch_fpf;
+	__atomic_sub_fetch_fp;
+	__atomic_sub_fetch_fpl;
+	__atomic_sub_fetch_fpf16b;
+	__atomic_sub_fetch_fpf16;
+	__atomic_sub_fetch_fpf32;
+	__atomic_sub_fetch_fpf64;
+	__atomic_sub_fetch_fpf128;
+	__atomic_sub_fetch_fpf32x;
+	__atomic_sub_fetch_fpf64x;
+} LIBATOMIC_1.2;
diff --git a/libatomic/libatomic_i.h b/libatomic/libatomic_i.h
index 861a22da152..8dc13fd459d 100644
--- a/libatomic/libatomic_i.h
+++ b/libatomic/libatomic_i.h
@@ -63,6 +63,31 @@  typedef unsigned U_8 __attribute__((mode(DI)));
 typedef unsigned U_16 __attribute__((mode(TI)));
 #endif
 
+typedef float U_fpf;
+typedef double U_fp;
+typedef long double U_fpl;
+#if HAVE_fpf16b
+typedef bfloat16 U_fpf16b;
+#endif
+#if HAVE_fpf16
+typedef _Float16 U_fpf16;
+#endif
+#if HAVE_fpf32
+typedef _Float32 U_fpf32;
+#endif
+#if HAVE_fpf64
+typedef _Float64 U_fpf64;
+#endif
+#if HAVE_fpf128
+typedef _Float128 U_fpf128;
+#endif
+#if HAVE_fpf32x
+typedef _Float32x U_fpf32x;
+#endif
+#if HAVE_fpf64x
+typedef _Float64x U_fpf64x;
+#endif
+
 /* The widest type that we support.  */
 #if HAVE_INT16
 # define MAX_SIZE	16
@@ -92,6 +117,28 @@  typedef U_MAX U_8;
 #if !HAVE_INT16
 typedef U_MAX U_16;
 #endif
+#if !HAVE_fpf16b
+typedef U_MAX U_fpf16b;
+#endif
+#if !HAVE_fpf16
+typedef U_MAX U_fpf16;
+#endif
+#if !HAVE_fpf32
+typedef U_MAX U_fpf32;
+#endif
+#if !HAVE_fpf64
+typedef U_MAX U_fpf64;
+#endif
+#if !HAVE_fpf128
+typedef U_MAX U_fpf128;
+#endif
+#if !HAVE_fpf32x
+typedef U_MAX U_fpf32x;
+#endif
+#if !HAVE_fpf64x
+typedef U_MAX U_fpf64x;
+#endif
+
 
 union max_size_u
 {
@@ -215,6 +262,17 @@  DECLARE_ALL_SIZED(4);
 DECLARE_ALL_SIZED(8);
 DECLARE_ALL_SIZED(16);
 
+DECLARE_ALL_SIZED(fpf);
+DECLARE_ALL_SIZED(fp);
+DECLARE_ALL_SIZED(fpl);
+DECLARE_ALL_SIZED(fpf16b);
+DECLARE_ALL_SIZED(fpf16);
+DECLARE_ALL_SIZED(fpf32);
+DECLARE_ALL_SIZED(fpf64);
+DECLARE_ALL_SIZED(fpf128);
+DECLARE_ALL_SIZED(fpf32x);
+DECLARE_ALL_SIZED(fpf64x);
+
 #undef DECLARE_1
 #undef DECLARE_ALL_SIZED
 #undef DECLARE_ALL_SIZED_
diff --git a/libatomic/testsuite/Makefile.in b/libatomic/testsuite/Makefile.in
index 247268f1949..e617e8f67ac 100644
--- a/libatomic/testsuite/Makefile.in
+++ b/libatomic/testsuite/Makefile.in
@@ -159,6 +159,7 @@  ECHO_T = @ECHO_T@
 EGREP = @EGREP@
 EXEEXT = @EXEEXT@
 FGREP = @FGREP@
+FPSUFFIXES = @FPSUFFIXES@
 GREP = @GREP@
 INSTALL = @INSTALL@
 INSTALL_DATA = @INSTALL_DATA@