diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 1ef21f30bbcee42931238c2cfb9a94c092f8711d..b56007b7bf5f76b8e32a51042c775a6f6584fad7 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -1209,54 +1209,90 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __xor_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept
       { return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
 
+    template<typename _Tp>
+      concept __atomic_fetch_addable
+	= requires (_Tp __t) { __atomic_fetch_add(&__t, __t, 0); };
+
     template<typename _Tp>
       _Tp
       __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept
       {
-	_Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
-	_Val<_Tp> __newval = __oldval + __i;
-	while (!compare_exchange_weak(__ptr, __oldval, __newval, __m,
-				      memory_order_relaxed))
-	  __newval = __oldval + __i;
-	return __oldval;
+	if constexpr (__atomic_fetch_addable<_Tp>)
+	  return __atomic_fetch_add(__ptr, __i, int(__m));
+	else
+	  {
+	    _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
+	    _Val<_Tp> __newval = __oldval + __i;
+	    while (!compare_exchange_weak (__ptr, __oldval, __newval, __m,
+					   memory_order_relaxed))
+	      __newval = __oldval + __i;
+	    return __oldval;
+	  }
       }
 
+    template<typename _Tp>
+      concept __atomic_fetch_subtractable
+	= requires (_Tp __t) { __atomic_fetch_sub(&__t, __t, 0); };
+
     template<typename _Tp>
       _Tp
       __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept
       {
-	_Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
-	_Val<_Tp> __newval = __oldval - __i;
-	while (!compare_exchange_weak(__ptr, __oldval, __newval, __m,
-				      memory_order_relaxed))
-	  __newval = __oldval - __i;
-	return __oldval;
+	if constexpr (__atomic_fetch_subtractable<_Tp>)
+	  return __atomic_fetch_sub(__ptr, __i, int(__m));
+	else
+	  {
+	    _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
+	    _Val<_Tp> __newval = __oldval - __i;
+	    while (!compare_exchange_weak (__ptr, __oldval, __newval, __m,
+					   memory_order_relaxed))
+	      __newval = __oldval - __i;
+	    return __oldval;
+	  }
       }
 
+    template<typename _Tp>
+      concept __atomic_add_fetchable
+	= requires (_Tp __t) { __atomic_add_fetch(&__t, __t, 0); };
+
     template<typename _Tp>
       _Tp
       __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept
       {
-	_Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
-	_Val<_Tp> __newval = __oldval + __i;
-	while (!compare_exchange_weak(__ptr, __oldval, __newval,
-				      memory_order_seq_cst,
-				      memory_order_relaxed))
-	  __newval = __oldval + __i;
-	return __newval;
+	if constexpr (__atomic_add_fetchable<_Tp>)
+	  return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST);
+	else
+	  {
+	    _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
+	    _Val<_Tp> __newval = __oldval + __i;
+	    while (!compare_exchange_weak (__ptr, __oldval, __newval,
+					   memory_order_seq_cst,
+					   memory_order_relaxed))
+	      __newval = __oldval + __i;
+	    return __newval;
+	  }
       }
 
+    template<typename _Tp>
+      concept __atomic_sub_fetchable
+	= requires (_Tp __t) { __atomic_sub_fetch(&__t, __t, 0); };
+
     template<typename _Tp>
       _Tp
       __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept
       {
-	_Val<_Tp> __oldval = load(__ptr, memory_order_relaxed);
-	_Val<_Tp> __newval = __oldval - __i;
-	while (!compare_exchange_weak(__ptr, __oldval, __newval,
-				      memory_order_seq_cst,
-				      memory_order_relaxed))
-	  __newval = __oldval - __i;
-	return __newval;
+	if constexpr (__atomic_sub_fetchable<_Tp>)
+	  return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST);
+	else
+	  {
+	    _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
+	    _Val<_Tp> __newval = __oldval - __i;
+	    while (!compare_exchange_weak (__ptr, __oldval, __newval,
+					   memory_order_seq_cst,
+					   memory_order_relaxed))
+	      __newval = __oldval - __i;
+	    return __newval;
+	  }
       }
   } // namespace __atomic_impl