Currently the GLIBCXX_ENABLE_ATOMIC_BUILTINS macro checks for a variety
of __atomic built-ins for bool, short and int. If all those checks pass,
then it defines _GLIBCXX_ATOMIC_BUILTINS and uses the definitions from
config/cpu/generic/atomicity_builtins/atomicity.h for the non-inline
versions of __exchange_and_add and __atomic_add that get compiled into
libsupc++.

However, the config/cpu/generic/atomicity_builtins/atomicity.h
definitions only depend on __atomic_fetch_add not on
__atomic_test_and_set or __atomic_compare_exchange. And they only
operate on a variable of type _Atomic word, which is not necessarily one
of bool, short or int (e.g. for sparcv9 _Atomic_word is 64-bit long).

This means that for a target where _Atomic_word is int but there are no
1-byte or 2-byte atomic instructions, GLIBCXX_ENABLE_ATOMIC_BUILTINS
will fail the checks for bool and short and not define the macro
_GLIBCXX_ATOMIC_BUILTINS. That means that we will use a single global
mutex for reference counting in the COW std::string and std::locale,
even though we could use __atomic_fetch_add to do it lock-free.

This commit removes most of the GLIBCXX_ENABLE_ATOMIC_BUILTINS checks,
so that it only checks __atomic_fetch_add on _Atomic_word. This will
enable the atomic versions of __exchange_and_add and __atomic_add for
more targets. This is not an ABI change, because for targets which
didn't previously use the atomic definitions of those function, they
always make a non-inlined call to the functions in the library. If the
definition of those functions now start using atomics, that doesn't
change the semantics for the code calling those functions.

On affected targets, new code compiled after this change will see the
_GLIBCXX_ATOMIC_BUILTINS macro and so will use the always-inline
versions of __exchange_and_add and __atomic_add, which use
__atomic_fetch_add directly. That is also compatible with older code
which calls the non-inline definitions, because those non-inline
definitions now also use __atomic_fetch_add.

The only configuration where this could be an ABI change is for a target
which currently defines _GLIBCXX_ATOMIC_BUILTINS (because all the atomic
built-ins for bool, short and int are supported), but which defines
_Atomic_word to some other type for which __atomic_fetch_add is _not_
supported. For such a target, we would previously have used inline calls
to __atomic_fetch_add, which would have dependend on libatomic. After
this commit, we would make non-inline calls into the library where
__exchange_and_add and __atomic_add would use the global mutex. That
would be an ABI break. I don't consider that a realistic scenario,
because it wouldn't have made any sense to define _Atomic_word to a
wider type than int, when doing so would have required libatomic to make
libstdc++.so work. Surely such a target would have just used int for its
_Atomic_word type.

The GLIBCXX_ENABLE_BACKTRACE macro currently uses the
glibcxx_ac_atomic_int macro defined by the checks that this commit
removes from GLIBCXX_ENABLE_ATOMIC_BUILTINS. That wasn't a good check
anyway, because libbacktrace actually depends on atomic loads+stores for
pointers as well as int, and for atomic stores for size_t. This commit
replaces the glibcxx_ac_atomic_int check with a proper test for all the
required atomic operations on all three of int, void* and size_t. This
ensures that the libbacktrace code used for std::stacktrace will either
use native atomics, or implement those loads and stores only in terms of
__sync_bool_compare_and_swap (possibly requiring that to come from
libatomic or elsewhere).

libstdc++-v3/ChangeLog:

        PR libstdc++/70560
        PR libstdc++/119667
        * acinclude.m4 (GLIBCXX_ENABLE_ATOMIC_BUILTINS): Only check for
        __atomic_fetch_add on _Atomic_word.
        (GLIBCXX_ENABLE_BACKTRACE): Check for __atomic_load_n and
        __atomic_store_n on int, void* and size_t.
        * config.h.in: Regenerate.
        * configure: Regenerate.
        * configure.host: Fix typo in comment.
---

Tested x86_64-linux, no changes to the c++config.h results.
I need to do more testing on other targets.

 libstdc++-v3/acinclude.m4   | 301 +++++++++-----------------
 libstdc++-v3/config.h.in    |   2 +-
 libstdc++-v3/configure      | 418 ++++++++++++------------------------
 libstdc++-v3/configure.host |   2 +-
 4 files changed, 239 insertions(+), 484 deletions(-)

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index a0094c2dd95..8dddcada071 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -3709,16 +3709,22 @@ AC_DEFUN([GLIBCXX_ENABLE_PCH], [
   AC_SUBST(glibcxx_PCHFLAGS)
 ])
 
-
 dnl
 dnl Check for atomic builtins.
 dnl See:
 dnl http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
 dnl
-dnl This checks to see if the host supports the compiler-generated
-dnl builtins for atomic operations for various integral sizes. Note, this
-dnl is intended to be an all-or-nothing switch, so all the atomic operations
-dnl that are used should be checked.
+dnl This checks to see if the host supports __atomic_fetch_add on _Atomic_word.
+dnl
+dnl We don't want libstdc++.so to depend on libatomic.so for basic
+dnl functionality like library-internal reference counting. This means we
+dnl should not use atomics for reference counting unless it can be done
+dnl using native instructions and not by calling into libatomic.
+dnl This policy could change if linking to libatomic.so becomes implicit.
+dnl
+dnl Defines:
+dnl  GLIBCXX_ATOMIC_BUILTINS - if atomic builtins should be used for
+dnl                            increments and decrements of _Atomic_word.
 dnl
 dnl Note:
 dnl libgomp and libgfortran use a link test, see CHECK_SYNC_FETCH_AND_ADD.
@@ -3728,7 +3734,7 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
   AC_LANG_CPLUSPLUS
   old_CXXFLAGS="$CXXFLAGS"
 
-  # Do link tests if possible, instead asm tests, limited to some platforms
+  # Do link tests if possible, otherwise asm tests. Limited to some platforms
   # see discussion in PR target/40134, PR libstdc++/40133 and the thread
   # starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
   atomic_builtins_link_tests=no
@@ -3741,223 +3747,59 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
     esac
   fi
 
-  if test x$atomic_builtins_link_tests = xyes; then
+  if test "$atomic_builtins_link_tests" = yes; then
 
-  # Do link tests.
+    # Do link tests.
 
-  CXXFLAGS="$CXXFLAGS -fno-exceptions"
+    CXXFLAGS="$CXXFLAGS -fno-exceptions"
 
-  AC_CACHE_CHECK([for atomic builtins for bool],
-    glibcxx_cv_atomic_bool, [
-    AC_TRY_LINK(
-      [ ],
-      [typedef bool atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       // N.B. __atomic_fetch_add is not supported for bool.
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-      ],
-      [glibcxx_cv_atomic_bool=yes],
-      [glibcxx_cv_atomic_bool=no])
-  ])
-
-  AC_CACHE_CHECK([for atomic builtins for short],
-    glibcxx_cv_atomic_short, [
-    AC_TRY_LINK(
-      [ ],
-      [typedef short atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-      ],
-      [glibcxx_cv_atomic_short=yes],
-      [glibcxx_cv_atomic_short=no])
-  ])
-
-  AC_CACHE_CHECK([for atomic builtins for int],
-    glibcxx_cv_atomic_int, [
-    AC_TRY_LINK(
-      [ ],
-      [typedef int atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-      ],
-      [glibcxx_cv_atomic_int=yes],
-      [glibcxx_cv_atomic_int=no])
-  ])
-
-  AC_CACHE_CHECK([for atomic builtins for long long],
-    glibcxx_cv_atomic_long_long, [
-    AC_TRY_LINK(
-      [ ],
-      [typedef long long atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-      ],
-      [glibcxx_cv_atomic_long_long=yes],
-      [glibcxx_cv_atomic_long_long=no])
-  ])
+    AC_CACHE_CHECK([for atomic builtins for _Atomic_word],
+       glibcxx_cv_atomic_word,
+       [AC_TRY_LINK([#include 
"${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"],
+                    [_Atomic_word a = 0, b;
+                     b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);],
+                    [glibcxx_cv_atomic_word=yes],
+                    [glibcxx_cv_atomic_word=no])])
 
   else
+    # Do asm tests.
 
-  # Do asm tests.
+    # Compile unoptimized.
+    CXXFLAGS='-O0 -S'
 
-  # Compile unoptimized.
-  CXXFLAGS='-O0 -S'
-
-  # Fake what AC_TRY_COMPILE does.
+    # Fake what AC_TRY_COMPILE does.
 
     cat > conftest.$ac_ext << EOF
 [#]line __oline__ "configure"
+[#]include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
 int main()
 {
-  typedef bool atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  // N.B. __atomic_fetch_add is not supported for bool.
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
+  _Atomic_word a = 0, b;
+  b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
 }
 EOF
 
-    AC_MSG_CHECKING([for atomic builtins for bool])
+    AC_MSG_CHECKING([for atomic builtins for _Atomic_word])
     if AC_TRY_EVAL(ac_compile); then
       if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
-       glibcxx_cv_atomic_bool=no
+       glibcxx_cv_atomic_word=no
       else
-       glibcxx_cv_atomic_bool=yes
+       glibcxx_cv_atomic_word=yes
       fi
     fi
-    AC_MSG_RESULT($glibcxx_cv_atomic_bool)
+    AC_MSG_RESULT($glibcxx_cv_atomic_word)
     rm -f conftest*
-
-    cat > conftest.$ac_ext << EOF
-[#]line __oline__ "configure"
-int main()
-{
-  typedef short atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
-}
-EOF
-
-    AC_MSG_CHECKING([for atomic builtins for short])
-    if AC_TRY_EVAL(ac_compile); then
-      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
-       glibcxx_cv_atomic_short=no
-      else
-       glibcxx_cv_atomic_short=yes
-      fi
-    fi
-    AC_MSG_RESULT($glibcxx_cv_atomic_short)
-    rm -f conftest*
-
-    cat > conftest.$ac_ext << EOF
-[#]line __oline__ "configure"
-int main()
-{
-  // NB: _Atomic_word not necessarily int.
-  typedef int atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
-}
-EOF
-
-    AC_MSG_CHECKING([for atomic builtins for int])
-    if AC_TRY_EVAL(ac_compile); then
-      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
-       glibcxx_cv_atomic_int=no
-      else
-       glibcxx_cv_atomic_int=yes
-      fi
-    fi
-    AC_MSG_RESULT($glibcxx_cv_atomic_int)
-    rm -f conftest*
-
-    cat > conftest.$ac_ext << EOF
-[#]line __oline__ "configure"
-int main()
-{
-  typedef long long atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
-}
-EOF
-
-    AC_MSG_CHECKING([for atomic builtins for long long])
-    if AC_TRY_EVAL(ac_compile); then
-      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
-       glibcxx_cv_atomic_long_long=no
-      else
-       glibcxx_cv_atomic_long_long=yes
-      fi
-    fi
-    AC_MSG_RESULT($glibcxx_cv_atomic_long_long)
-    rm -f conftest*
-
   fi
 
   CXXFLAGS="$old_CXXFLAGS"
   AC_LANG_RESTORE
 
-  # Set atomicity_dir to builtins if all but the long long test above passes,
+  # Set atomicity_dir to builtins if the test above passes,
   # or if the builtins were already chosen (e.g. by configure.host).
-  if { test "$glibcxx_cv_atomic_bool" = yes \
-     && test "$glibcxx_cv_atomic_short" = yes \
-     && test "$glibcxx_cv_atomic_int" = yes; } \
+  if test "$glibcxx_cv_atomic_word" = yes \
      || test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then
     AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS, 1,
-    [Define if the compiler supports C++11 atomics.])
+    [Define if the compiler supports native atomics for _Atomic_word.])
     atomicity_dir=cpu/generic/atomicity_builtins
   fi
 
@@ -5448,8 +5290,75 @@ AC_DEFUN([GLIBCXX_ENABLE_BACKTRACE], [
 
   BACKTRACE_CPPFLAGS="-D_GNU_SOURCE"
 
-  # libbacktrace only needs atomics for int, which we've already tested
-  if test "$glibcxx_cv_atomic_int" = "yes"; then
+  GLIBCXX_LANG_PUSH
+
+  # libbacktrace's own configure.ac only tests atomics for int,
+  # but the code actually uses atomics for size_t and pointers as well.
+  if test "$atomic_builtins_link_tests" = yes; then
+
+    CXXFLAGS='-O0'
+
+    AC_CACHE_CHECK([for atomic builtins for libbacktrace],
+       glibcxx_cv_libbacktrace_atomics,
+       [AC_TRY_LINK([], [
+           int i = 0;
+           int* p = &i;
+           size_t s = 0;
+           // backtrace_atomic_load_pointer
+           void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+           // backtrace_atomic_load_int
+           int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+           // backtrace_atomic_store_pointer
+           __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+           // backtrace_atomic_store_size_t
+           __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+           // backtrace_atomic_store_int
+           __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+                        ],
+                    [glibcxx_cv_libbacktrace_atomics=yes],
+                    [glibcxx_cv_libbacktrace_atomics=no])])
+
+  else
+    # Do asm tests.
+
+    CXXFLAGS='-O0 -S'
+
+    cat > conftest.$ac_ext << EOF
+[#]line __oline__ "configure"
+[#]include <stddef.h>
+int main()
+{
+  int i = 0;
+  int* p = &i;
+  size_t s = 0;
+  // backtrace_atomic_load_pointer
+  void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+  // backtrace_atomic_load_int
+  int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+  // backtrace_atomic_store_pointer
+  __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+  // backtrace_atomic_store_size_t
+  __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+  // backtrace_atomic_store_int
+  __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+}
+EOF
+
+    AC_MSG_CHECKING([for atomic builtins for libbacktrace])
+    if AC_TRY_EVAL(ac_compile); then
+      if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+       glibcxx_cv_libbacktrace_atomics=no
+      else
+       glibcxx_cv_libbacktrace_atomics=yes
+      fi
+    fi
+    AC_MSG_RESULT($glibcxx_cv_libbacktrace_atomics)
+    rm -f conftest*
+  fi
+
+  GLIBCXX_LANG_POP
+
+  if test "$glibcxx_cv_libbacktrace_atomics" = yes; then
     BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1"
   fi
 
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 77bbaf1beaa..ed067717a20 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -643,7 +643,7 @@
    <cwchar> in namespace std for C++98. */
 #undef _GLIBCXX98_USE_C99_WCHAR
 
-/* Define if the compiler supports C++11 atomics. */
+/* Define if the compiler supports native atomics for _Atomic_word. */
 #undef _GLIBCXX_ATOMIC_BUILTINS
 
 /* Define if global objects can be aligned to
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 819a1d82876..e084c59742f 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -15989,7 +15989,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 
   old_CXXFLAGS="$CXXFLAGS"
 
-  # Do link tests if possible, instead asm tests, limited to some platforms
+  # Do link tests if possible, otherwise asm tests. Limited to some platforms
   # see discussion in PR target/40134, PR libstdc++/40133 and the thread
   # starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
   atomic_builtins_link_tests=no
@@ -16002,326 +16002,77 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
     esac
   fi
 
-  if test x$atomic_builtins_link_tests = xyes; then
+  if test "$atomic_builtins_link_tests" = yes; then
 
-  # Do link tests.
+    # Do link tests.
 
-  CXXFLAGS="$CXXFLAGS -fno-exceptions"
+    CXXFLAGS="$CXXFLAGS -fno-exceptions"
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
bool" >&5
-$as_echo_n "checking for atomic builtins for bool... " >&6; }
-if ${glibcxx_cv_atomic_bool+:} false; then :
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
_Atomic_word" >&5
+$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; }
+if ${glibcxx_cv_atomic_word+:} false; then :
   $as_echo_n "(cached) " >&6
 else
-
-    if test x$gcc_no_link = xyes; then
+  if test x$gcc_no_link = xyes; then
   as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." 
"$LINENO" 5
 fi
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
 int
 main ()
 {
-typedef bool atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       // N.B. __atomic_fetch_add is not supported for bool.
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
+_Atomic_word a = 0, b;
+                     b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_cxx_try_link "$LINENO"; then :
-  glibcxx_cv_atomic_bool=yes
+  glibcxx_cv_atomic_word=yes
 else
-  glibcxx_cv_atomic_bool=no
+  glibcxx_cv_atomic_word=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
-
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool" >&5
-$as_echo "$glibcxx_cv_atomic_bool" >&6; }
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
short" >&5
-$as_echo_n "checking for atomic builtins for short... " >&6; }
-if ${glibcxx_cv_atomic_short+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-    if test x$gcc_no_link = xyes; then
-  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." 
"$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-typedef short atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
-  glibcxx_cv_atomic_short=yes
-else
-  glibcxx_cv_atomic_short=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_short" >&5
-$as_echo "$glibcxx_cv_atomic_short" >&6; }
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
int" >&5
-$as_echo_n "checking for atomic builtins for int... " >&6; }
-if ${glibcxx_cv_atomic_int+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-    if test x$gcc_no_link = xyes; then
-  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." 
"$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-typedef int atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
-  glibcxx_cv_atomic_int=yes
-else
-  glibcxx_cv_atomic_int=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_int" >&5
-$as_echo "$glibcxx_cv_atomic_int" >&6; }
-
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
long long" >&5
-$as_echo_n "checking for atomic builtins for long long... " >&6; }
-if ${glibcxx_cv_atomic_long_long+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-    if test x$gcc_no_link = xyes; then
-  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." 
"$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-typedef long long atomic_type;
-       atomic_type c1;
-       atomic_type c2;
-       atomic_type c3(0);
-       __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-       __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                                  __ATOMIC_RELAXED);
-       __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-       __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
-  glibcxx_cv_atomic_long_long=yes
-else
-  glibcxx_cv_atomic_long_long=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_long_long" 
>&5
-$as_echo "$glibcxx_cv_atomic_long_long" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_word" >&5
+$as_echo "$glibcxx_cv_atomic_word" >&6; }
 
   else
+    # Do asm tests.
 
-  # Do asm tests.
+    # Compile unoptimized.
+    CXXFLAGS='-O0 -S'
 
-  # Compile unoptimized.
-  CXXFLAGS='-O0 -S'
-
-  # Fake what AC_TRY_COMPILE does.
+    # Fake what AC_TRY_COMPILE does.
 
     cat > conftest.$ac_ext << EOF
-#line 16185 "configure"
+#line 16051 "configure"
+#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
 int main()
 {
-  typedef bool atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  // N.B. __atomic_fetch_add is not supported for bool.
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
+  _Atomic_word a = 0, b;
+  b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
 }
 EOF
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
bool" >&5
-$as_echo_n "checking for atomic builtins for bool... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
_Atomic_word" >&5
+$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; }
     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
-       glibcxx_cv_atomic_bool=no
+       glibcxx_cv_atomic_word=no
       else
-       glibcxx_cv_atomic_bool=yes
+       glibcxx_cv_atomic_word=yes
       fi
     fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool" 
>&5
-$as_echo "$glibcxx_cv_atomic_bool" >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_word" 
>&5
+$as_echo "$glibcxx_cv_atomic_word" >&6; }
     rm -f conftest*
-
-    cat > conftest.$ac_ext << EOF
-#line 16220 "configure"
-int main()
-{
-  typedef short atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
-}
-EOF
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
short" >&5
-$as_echo_n "checking for atomic builtins for short... " >&6; }
-    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
-       glibcxx_cv_atomic_short=no
-      else
-       glibcxx_cv_atomic_short=yes
-      fi
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_short" 
>&5
-$as_echo "$glibcxx_cv_atomic_short" >&6; }
-    rm -f conftest*
-
-    cat > conftest.$ac_ext << EOF
-#line 16255 "configure"
-int main()
-{
-  // NB: _Atomic_word not necessarily int.
-  typedef int atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
-}
-EOF
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
int" >&5
-$as_echo_n "checking for atomic builtins for int... " >&6; }
-    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
-       glibcxx_cv_atomic_int=no
-      else
-       glibcxx_cv_atomic_int=yes
-      fi
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_int" 
>&5
-$as_echo "$glibcxx_cv_atomic_int" >&6; }
-    rm -f conftest*
-
-    cat > conftest.$ac_ext << EOF
-#line 16291 "configure"
-int main()
-{
-  typedef long long atomic_type;
-  atomic_type c1;
-  atomic_type c2;
-  atomic_type c3(0);
-  __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
-  __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
-                             __ATOMIC_RELAXED);
-  __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
-  __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
-  return 0;
-}
-EOF
-
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
long long" >&5
-$as_echo_n "checking for atomic builtins for long long... " >&6; }
-    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
-       glibcxx_cv_atomic_long_long=no
-      else
-       glibcxx_cv_atomic_long_long=yes
-      fi
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: 
$glibcxx_cv_atomic_long_long" >&5
-$as_echo "$glibcxx_cv_atomic_long_long" >&6; }
-    rm -f conftest*
-
   fi
 
   CXXFLAGS="$old_CXXFLAGS"
@@ -16332,11 +16083,9 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS 
$LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-  # Set atomicity_dir to builtins if all but the long long test above passes,
+  # Set atomicity_dir to builtins if the test above passes,
   # or if the builtins were already chosen (e.g. by configure.host).
-  if { test "$glibcxx_cv_atomic_bool" = yes \
-     && test "$glibcxx_cv_atomic_short" = yes \
-     && test "$glibcxx_cv_atomic_int" = yes; } \
+  if test "$glibcxx_cv_atomic_word" = yes \
      || test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then
 
 $as_echo "#define _GLIBCXX_ATOMIC_BUILTINS 1" >>confdefs.h
@@ -16445,7 +16194,7 @@ $as_echo "mutex" >&6; }
   # unnecessary for this test.
 
     cat > conftest.$ac_ext << EOF
-#line 16448 "configure"
+#line 16197 "configure"
 int main()
 {
   _Decimal32 d1;
@@ -16487,7 +16236,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
   # unnecessary for this test.
 
   cat > conftest.$ac_ext << EOF
-#line 16490 "configure"
+#line 16239 "configure"
 template<typename T1, typename T2>
   struct same
   { typedef T2 type; };
@@ -53788,8 +53537,105 @@ fi
 
   BACKTRACE_CPPFLAGS="-D_GNU_SOURCE"
 
-  # libbacktrace only needs atomics for int, which we've already tested
-  if test "$glibcxx_cv_atomic_int" = "yes"; then
+  GLIBCXX_LANG_PUSH
+
+  # libbacktrace's own configure.ac only tests atomics for int,
+  # but the code actually uses atomics for size_t and pointers as well.
+  if test "$atomic_builtins_link_tests" = yes; then
+
+    CXXFLAGS='-O0'
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
libbacktrace" >&5
+$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; }
+if ${glibcxx_cv_libbacktrace_atomics+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test x$gcc_no_link = xyes; then
+  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." 
"$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+           int i = 0;
+           int* p = &i;
+           size_t s = 0;
+           // backtrace_atomic_load_pointer
+           void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+           // backtrace_atomic_load_int
+           int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+           // backtrace_atomic_store_pointer
+           __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+           // backtrace_atomic_store_size_t
+           __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+           // backtrace_atomic_store_int
+           __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  glibcxx_cv_libbacktrace_atomics=yes
+else
+  glibcxx_cv_libbacktrace_atomics=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: 
$glibcxx_cv_libbacktrace_atomics" >&5
+$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; }
+
+  else
+    # Do asm tests.
+
+    CXXFLAGS='-O0 -S'
+
+    cat > conftest.$ac_ext << EOF
+#line 53598 "configure"
+#include <stddef.h>
+int main()
+{
+  int i = 0;
+  int* p = &i;
+  size_t s = 0;
+  // backtrace_atomic_load_pointer
+  void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+  // backtrace_atomic_load_int
+  int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+  // backtrace_atomic_store_pointer
+  __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+  // backtrace_atomic_store_size_t
+  __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+  // backtrace_atomic_store_int
+  __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+}
+EOF
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for 
libbacktrace" >&5
+$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; }
+    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
+       glibcxx_cv_libbacktrace_atomics=no
+      else
+       glibcxx_cv_libbacktrace_atomics=yes
+      fi
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: 
$glibcxx_cv_libbacktrace_atomics" >&5
+$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; }
+    rm -f conftest*
+  fi
+
+  GLIBCXX_LANG_POP
+
+  if test "$glibcxx_cv_libbacktrace_atomics" = yes; then
     BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1"
   fi
 
diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
index 253e5a9ad0d..3cd1bb1c6ee 100644
--- a/libstdc++-v3/configure.host
+++ b/libstdc++-v3/configure.host
@@ -180,7 +180,7 @@ esac
 
 
 # Set specific CPU overrides for atomicity_dir.
-# This can be over-ridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS.
+# This can be overridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS.
 # THIS TABLE IS SORTED.  KEEP IT THAT WAY.
 if test -f ${glibcxx_srcdir}/config/${cpu_include_dir}/atomicity.h ; then
   atomicity_dir=$cpu_include_dir
-- 
2.49.0


Reply via email to