From: Jonathan Wakely Date: Thu, 24 Oct 2024 10:06:42 +0000 (+0100) Subject: libstdc++: Define __memcpyable as true X-Git-Tag: basepoints/gcc-16~4777 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30563d8978a39c402a425e958b5b51936ee76cff;p=thirdparty%2Fgcc.git libstdc++: Define __memcpyable as true 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. Reviewed-by: Patrick Palka --- diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index 2f9ce75e82c2..e412f8d07703 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 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 struct __memcpyable<_Tp*, _Up*> { @@ -554,6 +556,27 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) struct __memcpyable_integer { 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 { 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 { 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 { 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