[2/3] libstdc++: Define __memcpyable<float*, _Float32*> as true

Message ID 20241024144427.1430030-2-jwakely@redhat.com
State Committed
Commit 30563d8978a39c402a425e958b5b51936ee76cff
Headers
Series [1/3] libstdc++: Fix typos in tests using macros for std::float128_t support |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Jonathan Wakely Oct. 24, 2024, 2:05 p.m. UTC
  This allows optimizing copying ranges of floating-point types when they
have the same size and representation, e.g. between _Float32 and float
when we know that float uses the same IEEE binary32 format as _Float32.

On some targets double and long double both use IEEE binary64 format so
we could enable memcpy between those types, but we don't have existing
macros to check for that case.

libstdc++-v3/ChangeLog:

	* include/bits/cpp_type_traits.h (__memcpyable): Add
	specializations for compatible floating-point types.
---
Tested powerpc64le-linux.

 libstdc++-v3/include/bits/cpp_type_traits.h | 23 +++++++++++++++++++++
 1 file changed, 23 insertions(+)
  

Patch

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h
index 2f9ce75e82c..e412f8d0770 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -472,6 +472,8 @@  __INT_N(__GLIBCXX_TYPE_INT_N_3)
   template<typename _Tp> struct __memcpyable_integer;
 
   // For heterogeneous types, allow memcpy between equal-sized integers.
+  // N.B. we cannot do the same for equal-sized enums, they're not assignable.
+  // We cannot do it for pointers, because derived-to-base can adjust offset.
   template<typename _Tp, typename _Up>
     struct __memcpyable<_Tp*, _Up*>
     {
@@ -554,6 +556,27 @@  __INT_N(__GLIBCXX_TYPE_INT_N_3)
     struct __memcpyable_integer<unsigned __int128> { enum { __width = 128 }; };
 #endif
 
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  template<>
+    struct __memcpyable<_Float32*, float*> { enum { __value = true }; };
+  template<>
+    struct __memcpyable<float*, _Float32*> { enum { __value = true }; };
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  template<>
+    struct __memcpyable<_Float64*, double*> { enum { __value = true }; };
+  template<>
+    struct __memcpyable<double*, _Float64*> { enum { __value = true }; };
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  template<>
+    struct __memcpyable<_Float128*, long double*> { enum { __value = true }; };
+  template<>
+    struct __memcpyable<long double*, _Float128*> { enum { __value = true }; };
+#endif
+
   // Whether two iterator types can be used with memcmp.
   // This trait only says it's well-formed to use memcmp, not that it
   // gives the right answer for a given algorithm. So for example, std::equal