* [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor @ 2024-01-08 1:01 xndcn 2024-01-15 0:45 ` [PING][PATCH] " xndcn 2024-01-15 3:46 ` [PATCH] " H.J. Lu 0 siblings, 2 replies; 28+ messages in thread From: xndcn @ 2024-01-08 1:01 UTC (permalink / raw) To: gcc-patches [-- Attachment #1: Type: text/plain, Size: 1541 bytes --] Hi, I found __atomic_float constructor does not clear padding, while __compare_exchange assumes it as zeroed padding. So it is easy to reproducing a infinite loop in X86-64 with long double type like: --- -O0 -std=c++23 -mlong-double-80 #include <stdio.h> #include <atomic> #define T long double int main() { std::atomic<T> t(0.5); t.fetch_add(0.5); float x = t; printf("%f\n", x); } --- So we should add __builtin_clear_padding in __atomic_float constructor, just like the generic atomic struct. regtested on x86_64-linux. Is it OK for trunk? --- libstdc++: atomic: Add missing clear_padding in __atomic_float constructor. libstdc++-v3/ChangeLog: * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. --- libstdc++-v3/include/bits/atomic_base.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index f4ce0fa53..d59c2209e 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr __atomic_float(_Fp __t) : _M_fp(__t) - { } + { +#if __has_builtin(__builtin_clear_padding) + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) + __builtin_clear_padding(std::__addressof(_M_fp)); +#endif + } __atomic_float(const __atomic_float&) = delete; __atomic_float& operator=(const __atomic_float&) = delete; -- 2.25.1 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PING][PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-08 1:01 [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor xndcn @ 2024-01-15 0:45 ` xndcn 2024-01-15 3:46 ` [PATCH] " H.J. Lu 1 sibling, 0 replies; 28+ messages in thread From: xndcn @ 2024-01-15 0:45 UTC (permalink / raw) To: gcc-patches, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 1781 bytes --] Ping. Thanks. xndcn <xndchn@gmail.com> 于2024年1月8日周一 09:01写道: > Hi, I found __atomic_float constructor does not clear padding, > while __compare_exchange assumes it as zeroed padding. So it is easy to > reproducing a infinite loop in X86-64 with long double type like: > --- > -O0 -std=c++23 -mlong-double-80 > #include <stdio.h> > #include <atomic> > > #define T long double > int main() { > std::atomic<T> t(0.5); > t.fetch_add(0.5); > float x = t; > printf("%f\n", x); > } > --- > > So we should add __builtin_clear_padding in __atomic_float constructor, > just like the generic atomic struct. > > regtested on x86_64-linux. Is it OK for trunk? > > --- > libstdc++: atomic: Add missing clear_padding in __atomic_float constructor. > > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in > __atomic_float constructor. > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/libstdc++-v3/include/bits/atomic_base.h > b/libstdc++-v3/include/bits/atomic_base.h > index f4ce0fa53..d59c2209e 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __has_builtin(__builtin_clear_padding) > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-08 1:01 [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor xndcn 2024-01-15 0:45 ` [PING][PATCH] " xndcn @ 2024-01-15 3:46 ` H.J. Lu 2024-01-16 9:53 ` xndcn 1 sibling, 1 reply; 28+ messages in thread From: H.J. Lu @ 2024-01-15 3:46 UTC (permalink / raw) To: xndcn; +Cc: GCC Patches [-- Attachment #1: Type: text/plain, Size: 1746 bytes --] On Sun, Jan 7, 2024, 5:02 PM xndcn <xndchn@gmail.com> wrote: > Hi, I found __atomic_float constructor does not clear padding, > while __compare_exchange assumes it as zeroed padding. So it is easy to > reproducing a infinite loop in X86-64 with long double type like: > --- > -O0 -std=c++23 -mlong-double-80 > #include <stdio.h> > #include <atomic> > > #define T long double > int main() { > std::atomic<T> t(0.5); > t.fetch_add(0.5); > float x = t; > printf("%f\n", x); > } > --- > > So we should add __builtin_clear_padding in __atomic_float constructor, > just like the generic atomic struct. > > regtested on x86_64-linux. Is it OK for trunk? > > --- > libstdc++: atomic: Add missing clear_padding in __atomic_float constructor. > > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in > __atomic_float constructor. > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++++++- > 1 file changed, 6 insertions(+), 1 deletion(-) > > diff --git a/libstdc++-v3/include/bits/atomic_base.h > b/libstdc++-v3/include/bits/atomic_base.h > index f4ce0fa53..d59c2209e 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __has_builtin(__builtin_clear_padding) > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > -- > 2.25.1 > Can you add a testcase? Thanks. H.J. > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-15 3:46 ` [PATCH] " H.J. Lu @ 2024-01-16 9:53 ` xndcn 2024-01-16 10:12 ` Xi Ruoyao 0 siblings, 1 reply; 28+ messages in thread From: xndcn @ 2024-01-16 9:53 UTC (permalink / raw) To: H.J. Lu; +Cc: GCC Patches, Jakub Jelinek [-- Attachment #1: Type: text/plain, Size: 5543 bytes --] Thanks, so I add a test: atomic_float/compare_exchange_padding.cc, which will fail due to timeout without the patch. --- libstdc++-v3/ChangeLog: * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. * testsuite/lib/dg-options.exp: enable libatomic for IA32 and X86-64. * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. --- libstdc++-v3/include/bits/atomic_base.h | 7 ++- .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ libstdc++-v3/testsuite/lib/dg-options.exp | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index d3a2c4f3805..cbe3749e17f 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr __atomic_float(_Fp __t) : _M_fp(__t) - { } + { +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) + __builtin_clear_padding(std::__addressof(_M_fp)); +#endif + } __atomic_float(const __atomic_float&) = delete; __atomic_float& operator=(const __atomic_float&) = delete; diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc new file mode 100644 index 00000000000..9376ab22850 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc @@ -0,0 +1,50 @@ +// { dg-do run { target c++20 } } +// { dg-options "-O0" } +// { dg-timeout 10 } +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } +// { dg-do run { target { ia32 || x86_64-*-* } } } +// { dg-add-options libatomic } + +#include <atomic> +#include <testsuite_hooks.h> + +template<typename T> +void __attribute__((noinline,noipa)) +fill_padding(T& f) +{ + T mask; + __builtin_memset(&mask, 0xff, sizeof(T)); + __builtin_clear_padding(&mask); + unsigned char* ptr_f = (unsigned char*)&f; + unsigned char* ptr_mask = (unsigned char*)&mask; + for (int i = 0; i < sizeof(T); i++) + { + if (ptr_mask[i] == 0x00) + { + ptr_f[i] = 0xff; + } + } +} + +void +test01() +{ + long double f = 0.5f; // long double may contains padding on X86 + fill_padding(f); + std::atomic<long double> as{ f }; // padding cleared on constructor + long double t = 1.5; + + as.fetch_add(t); + long double s = f + t; + t = as.load(); + VERIFY(s == t); // padding ignored on float comparing + fill_padding(s); + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg + fill_padding(f); + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp index bc387d17ed7..d9a19dadd7f 100644 --- a/libstdc++-v3/testsuite/lib/dg-options.exp +++ b/libstdc++-v3/testsuite/lib/dg-options.exp @@ -337,6 +337,7 @@ proc add_options_for_libatomic { flags } { || ([istarget powerpc*-*-*] && [check_effective_target_ilp32]) || [istarget riscv*-*-*] || ([istarget sparc*-*-linux-gnu] && [check_effective_target_ilp32]) + || ([istarget i?86-*-*] || [istarget x86_64-*-*]) } { global TOOL_OPTIONS -- 2.25.1 H.J. Lu <hjl.tools@gmail.com> 于2024年1月15日周一 11:46写道: > On Sun, Jan 7, 2024, 5:02 PM xndcn <xndchn@gmail.com> wrote: > >> Hi, I found __atomic_float constructor does not clear padding, >> while __compare_exchange assumes it as zeroed padding. So it is easy to >> reproducing a infinite loop in X86-64 with long double type like: >> --- >> -O0 -std=c++23 -mlong-double-80 >> #include <stdio.h> >> #include <atomic> >> >> #define T long double >> int main() { >> std::atomic<T> t(0.5); >> t.fetch_add(0.5); >> float x = t; >> printf("%f\n", x); >> } >> --- >> >> So we should add __builtin_clear_padding in __atomic_float constructor, >> just like the generic atomic struct. >> >> regtested on x86_64-linux. Is it OK for trunk? >> >> --- >> libstdc++: atomic: Add missing clear_padding in __atomic_float >> constructor. >> >> libstdc++-v3/ChangeLog: >> >> * include/bits/atomic_base.h: add __builtin_clear_padding in >> __atomic_float constructor. >> --- >> libstdc++-v3/include/bits/atomic_base.h | 7 ++++++- >> 1 file changed, 6 insertions(+), 1 deletion(-) >> >> diff --git a/libstdc++-v3/include/bits/atomic_base.h >> b/libstdc++-v3/include/bits/atomic_base.h >> index f4ce0fa53..d59c2209e 100644 >> --- a/libstdc++-v3/include/bits/atomic_base.h >> +++ b/libstdc++-v3/include/bits/atomic_base.h >> @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> >> constexpr >> __atomic_float(_Fp __t) : _M_fp(__t) >> - { } >> + { >> +#if __has_builtin(__builtin_clear_padding) >> + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) >> + __builtin_clear_padding(std::__addressof(_M_fp)); >> +#endif >> + } >> >> __atomic_float(const __atomic_float&) = delete; >> __atomic_float& operator=(const __atomic_float&) = delete; >> -- >> 2.25.1 >> > > Can you add a testcase? > > Thanks. > > H.J. > >> ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-16 9:53 ` xndcn @ 2024-01-16 10:12 ` Xi Ruoyao 2024-01-16 16:16 ` xndcn 0 siblings, 1 reply; 28+ messages in thread From: Xi Ruoyao @ 2024-01-16 10:12 UTC (permalink / raw) To: xndcn, H.J. Lu; +Cc: GCC Patches, Jakub Jelinek, libstdc++ On Tue, 2024-01-16 at 17:53 +0800, xndcn wrote: > Thanks, so I add a test: atomic_float/compare_exchange_padding.cc, > which will fail due to timeout without the patch. Please resend in plain text instead of HTML. Sending in HTML causes the patch mangled. And libstdc++ patches should CC libstdc++@gcc.gnu.org, in addition to gcc-patches@gcc.gnu.org. > --- > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. > * testsuite/lib/dg-options.exp: enable libatomic for IA32 and X86-64. > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > libstdc++-v3/testsuite/lib/dg-options.exp | 1 + > 3 files changed, 57 insertions(+), 1 deletion(-) > create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h > index d3a2c4f3805..cbe3749e17f 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > new file mode 100644 > index 00000000000..9376ab22850 > --- /dev/null > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > @@ -0,0 +1,50 @@ > +// { dg-do run { target c++20 } } > +// { dg-options "-O0" } > +// { dg-timeout 10 } > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > +// { dg-do run { target { ia32 || x86_64-*-* } } } > +// { dg-add-options libatomic } > + > +#include <atomic> > +#include <testsuite_hooks.h> > + > +template<typename T> > +void __attribute__((noinline,noipa)) > +fill_padding(T& f) > +{ > + T mask; > + __builtin_memset(&mask, 0xff, sizeof(T)); > + __builtin_clear_padding(&mask); > + unsigned char* ptr_f = (unsigned char*)&f; > + unsigned char* ptr_mask = (unsigned char*)&mask; > + for (int i = 0; i < sizeof(T); i++) > + { > + if (ptr_mask[i] == 0x00) > + { > + ptr_f[i] = 0xff; > + } > + } > +} > + > +void > +test01() > +{ > + long double f = 0.5f; // long double may contains padding on X86 > + fill_padding(f); > + std::atomic<long double> as{ f }; // padding cleared on constructor > + long double t = 1.5; > + > + as.fetch_add(t); > + long double s = f + t; > + t = as.load(); > + VERIFY(s == t); // padding ignored on float comparing > + fill_padding(s); > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > + fill_padding(f); > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > +} > + > +int main() > +{ > + test01(); > +} > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp > index bc387d17ed7..d9a19dadd7f 100644 > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > @@ -337,6 +337,7 @@ proc add_options_for_libatomic { flags } { > || ([istarget powerpc*-*-*] && [check_effective_target_ilp32]) > || [istarget riscv*-*-*] > || ([istarget sparc*-*-linux-gnu] && [check_effective_target_ilp32]) > + || ([istarget i?86-*-*] || [istarget x86_64-*-*]) This seems too overkill as "dg-add-options libatomic" is not intended to handle 16-byte atomics. Maybe we can fork this to a new dg-add-options like "add_options_for_libatomic_16b"? > } { > global TOOL_OPTIONS > > -- > 2.25.1 -- Xi Ruoyao <xry111@xry111.site> School of Aerospace Science and Technology, Xidian University ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-16 10:12 ` Xi Ruoyao @ 2024-01-16 16:16 ` xndcn 2024-01-24 15:53 ` xndcn ` (3 more replies) 0 siblings, 4 replies; 28+ messages in thread From: xndcn @ 2024-01-16 16:16 UTC (permalink / raw) To: Xi Ruoyao; +Cc: H.J. Lu, GCC Patches, Jakub Jelinek, libstdc++ Sorry about the mangled content... So I add a new add-options for libatomic_16b: --- libstdc++-v3/ChangeLog: * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. * testsuite/lib/dg-options.exp: add new add-options for libatomic_16b. * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. --- libstdc++-v3/include/bits/atomic_base.h | 7 ++- .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ libstdc++-v3/testsuite/lib/dg-options.exp | 22 ++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index f4ce0fa53..104ddfdbe 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr __atomic_float(_Fp __t) : _M_fp(__t) - { } + { +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) + __builtin_clear_padding(std::__addressof(_M_fp)); +#endif + } __atomic_float(const __atomic_float&) = delete; __atomic_float& operator=(const __atomic_float&) = delete; diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc new file mode 100644 index 000000000..d538b3d55 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc @@ -0,0 +1,50 @@ +// { dg-do run { target c++20 } } +// { dg-options "-O0" } +// { dg-timeout 10 } +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } +// { dg-do run { target { ia32 || x86_64-*-* } } } +// { dg-add-options libatomic_16b } + +#include <atomic> +#include <testsuite_hooks.h> + +template<typename T> +void __attribute__((noinline,noipa)) +fill_padding(T& f) +{ + T mask; + __builtin_memset(&mask, 0xff, sizeof(T)); + __builtin_clear_padding(&mask); + unsigned char* ptr_f = (unsigned char*)&f; + unsigned char* ptr_mask = (unsigned char*)&mask; + for (int i = 0; i < sizeof(T); i++) + { + if (ptr_mask[i] == 0x00) + { + ptr_f[i] = 0xff; + } + } +} + +void +test01() +{ + long double f = 0.5f; // long double may contains padding on X86 + fill_padding(f); + std::atomic<long double> as{ f }; // padding cleared on constructor + long double t = 1.5; + + as.fetch_add(t); + long double s = f + t; + t = as.load(); + VERIFY(s == t); // padding ignored on float comparing + fill_padding(s); + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg + fill_padding(f); + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp index 850442b6b..25da20d58 100644 --- a/libstdc++-v3/testsuite/lib/dg-options.exp +++ b/libstdc++-v3/testsuite/lib/dg-options.exp @@ -356,6 +356,28 @@ proc add_options_for_libatomic { flags } { return $flags } +# Add option to link to libatomic, if required for atomics on 16-byte (128-bit) +proc add_options_for_libatomic_16b { flags } { + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) + } { + global TOOL_OPTIONS + + set link_flags "" + if ![is_remote host] { + if [info exists TOOL_OPTIONS] { + set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]" + } else { + set link_flags "[atomic_link_flags [get_multilibs]]" + } + } + + append link_flags " -latomic " + + return "$flags $link_flags" + } + return $flags +} + # Add options to enable use of deprecated features. proc add_options_for_using-deprecated { flags } { return "$flags -U_GLIBCXX_USE_DEPRECATED -D_GLIBCXX_USE_DEPRECATED=1" -- 2.25.1 Xi Ruoyao <xry111@xry111.site> 于2024年1月16日周二 18:12写道: > > On Tue, 2024-01-16 at 17:53 +0800, xndcn wrote: > > Thanks, so I add a test: atomic_float/compare_exchange_padding.cc, > > which will fail due to timeout without the patch. > > Please resend in plain text instead of HTML. Sending in HTML causes the > patch mangled. > > And libstdc++ patches should CC libstdc++@gcc.gnu.org, in addition to > gcc-patches@gcc.gnu.org. > > > --- > > libstdc++-v3/ChangeLog: > > > > * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. > > * testsuite/lib/dg-options.exp: enable libatomic for IA32 and X86-64. > > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > > --- > > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > > libstdc++-v3/testsuite/lib/dg-options.exp | 1 + > > 3 files changed, 57 insertions(+), 1 deletion(-) > > create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > > diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h > > index d3a2c4f3805..cbe3749e17f 100644 > > --- a/libstdc++-v3/include/bits/atomic_base.h > > +++ b/libstdc++-v3/include/bits/atomic_base.h > > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > > constexpr > > __atomic_float(_Fp __t) : _M_fp(__t) > > - { } > > + { > > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > > + __builtin_clear_padding(std::__addressof(_M_fp)); > > +#endif > > + } > > > > __atomic_float(const __atomic_float&) = delete; > > __atomic_float& operator=(const __atomic_float&) = delete; > > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > new file mode 100644 > > index 00000000000..9376ab22850 > > --- /dev/null > > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > @@ -0,0 +1,50 @@ > > +// { dg-do run { target c++20 } } > > +// { dg-options "-O0" } > > +// { dg-timeout 10 } > > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > > +// { dg-do run { target { ia32 || x86_64-*-* } } } > > +// { dg-add-options libatomic } > > + > > +#include <atomic> > > +#include <testsuite_hooks.h> > > + > > +template<typename T> > > +void __attribute__((noinline,noipa)) > > +fill_padding(T& f) > > +{ > > + T mask; > > + __builtin_memset(&mask, 0xff, sizeof(T)); > > + __builtin_clear_padding(&mask); > > + unsigned char* ptr_f = (unsigned char*)&f; > > + unsigned char* ptr_mask = (unsigned char*)&mask; > > + for (int i = 0; i < sizeof(T); i++) > > + { > > + if (ptr_mask[i] == 0x00) > > + { > > + ptr_f[i] = 0xff; > > + } > > + } > > +} > > + > > +void > > +test01() > > +{ > > + long double f = 0.5f; // long double may contains padding on X86 > > + fill_padding(f); > > + std::atomic<long double> as{ f }; // padding cleared on constructor > > + long double t = 1.5; > > + > > + as.fetch_add(t); > > + long double s = f + t; > > + t = as.load(); > > + VERIFY(s == t); // padding ignored on float comparing > > + fill_padding(s); > > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > > + fill_padding(f); > > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > > +} > > + > > +int main() > > +{ > > + test01(); > > +} > > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp > > index bc387d17ed7..d9a19dadd7f 100644 > > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > > @@ -337,6 +337,7 @@ proc add_options_for_libatomic { flags } { > > || ([istarget powerpc*-*-*] && [check_effective_target_ilp32]) > > || [istarget riscv*-*-*] > > || ([istarget sparc*-*-linux-gnu] && [check_effective_target_ilp32]) > > + || ([istarget i?86-*-*] || [istarget x86_64-*-*]) > > This seems too overkill as "dg-add-options libatomic" is not intended to > handle 16-byte atomics. Maybe we can fork this to a new dg-add-options > like "add_options_for_libatomic_16b"? > > > } { > > global TOOL_OPTIONS > > > > -- > > 2.25.1 > > -- > Xi Ruoyao <xry111@xry111.site> > School of Aerospace Science and Technology, Xidian University ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-16 16:16 ` xndcn @ 2024-01-24 15:53 ` xndcn 2024-01-30 16:08 ` [PING][PATCH] " xndcn ` (2 subsequent siblings) 3 siblings, 0 replies; 28+ messages in thread From: xndcn @ 2024-01-24 15:53 UTC (permalink / raw) To: Xi Ruoyao, Jakub Jelinek, H.J. Lu; +Cc: GCC Patches, libstdc++ Hi, is it OK for trunk? I do not have access to the repo, can you please help me submit the patch? Thanks. xndcn <xndchn@gmail.com> 于2024年1月17日周三 00:16写道: > > Sorry about the mangled content... > So I add a new add-options for libatomic_16b: > > --- > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in > __atomic_float constructor. > * testsuite/lib/dg-options.exp: add new add-options for libatomic_16b. > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > libstdc++-v3/testsuite/lib/dg-options.exp | 22 ++++++++ > 3 files changed, 78 insertions(+), 1 deletion(-) > create mode 100644 > libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > diff --git a/libstdc++-v3/include/bits/atomic_base.h > b/libstdc++-v3/include/bits/atomic_base.h > index f4ce0fa53..104ddfdbe 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > new file mode 100644 > index 000000000..d538b3d55 > --- /dev/null > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > @@ -0,0 +1,50 @@ > +// { dg-do run { target c++20 } } > +// { dg-options "-O0" } > +// { dg-timeout 10 } > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > +// { dg-do run { target { ia32 || x86_64-*-* } } } > +// { dg-add-options libatomic_16b } > + > +#include <atomic> > +#include <testsuite_hooks.h> > + > +template<typename T> > +void __attribute__((noinline,noipa)) > +fill_padding(T& f) > +{ > + T mask; > + __builtin_memset(&mask, 0xff, sizeof(T)); > + __builtin_clear_padding(&mask); > + unsigned char* ptr_f = (unsigned char*)&f; > + unsigned char* ptr_mask = (unsigned char*)&mask; > + for (int i = 0; i < sizeof(T); i++) > + { > + if (ptr_mask[i] == 0x00) > + { > + ptr_f[i] = 0xff; > + } > + } > +} > + > +void > +test01() > +{ > + long double f = 0.5f; // long double may contains padding on X86 > + fill_padding(f); > + std::atomic<long double> as{ f }; // padding cleared on constructor > + long double t = 1.5; > + > + as.fetch_add(t); > + long double s = f + t; > + t = as.load(); > + VERIFY(s == t); // padding ignored on float comparing > + fill_padding(s); > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > + fill_padding(f); > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > +} > + > +int main() > +{ > + test01(); > +} > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp > b/libstdc++-v3/testsuite/lib/dg-options.exp > index 850442b6b..25da20d58 100644 > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > @@ -356,6 +356,28 @@ proc add_options_for_libatomic { flags } { > return $flags > } > > +# Add option to link to libatomic, if required for atomics on 16-byte (128-bit) > +proc add_options_for_libatomic_16b { flags } { > + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) > + } { > + global TOOL_OPTIONS > + > + set link_flags "" > + if ![is_remote host] { > + if [info exists TOOL_OPTIONS] { > + set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]" > + } else { > + set link_flags "[atomic_link_flags [get_multilibs]]" > + } > + } > + > + append link_flags " -latomic " > + > + return "$flags $link_flags" > + } > + return $flags > +} > + > # Add options to enable use of deprecated features. > proc add_options_for_using-deprecated { flags } { > return "$flags -U_GLIBCXX_USE_DEPRECATED -D_GLIBCXX_USE_DEPRECATED=1" > -- > 2.25.1 > > > Xi Ruoyao <xry111@xry111.site> 于2024年1月16日周二 18:12写道: > > > > On Tue, 2024-01-16 at 17:53 +0800, xndcn wrote: > > > Thanks, so I add a test: atomic_float/compare_exchange_padding.cc, > > > which will fail due to timeout without the patch. > > > > Please resend in plain text instead of HTML. Sending in HTML causes the > > patch mangled. > > > > And libstdc++ patches should CC libstdc++@gcc.gnu.org, in addition to > > gcc-patches@gcc.gnu.org. > > > > > --- > > > libstdc++-v3/ChangeLog: > > > > > > * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. > > > * testsuite/lib/dg-options.exp: enable libatomic for IA32 and X86-64. > > > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > > > --- > > > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > > > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > > > libstdc++-v3/testsuite/lib/dg-options.exp | 1 + > > > 3 files changed, 57 insertions(+), 1 deletion(-) > > > create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > > > > diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h > > > index d3a2c4f3805..cbe3749e17f 100644 > > > --- a/libstdc++-v3/include/bits/atomic_base.h > > > +++ b/libstdc++-v3/include/bits/atomic_base.h > > > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > > > > constexpr > > > __atomic_float(_Fp __t) : _M_fp(__t) > > > - { } > > > + { > > > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > > > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > > > + __builtin_clear_padding(std::__addressof(_M_fp)); > > > +#endif > > > + } > > > > > > __atomic_float(const __atomic_float&) = delete; > > > __atomic_float& operator=(const __atomic_float&) = delete; > > > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > new file mode 100644 > > > index 00000000000..9376ab22850 > > > --- /dev/null > > > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > @@ -0,0 +1,50 @@ > > > +// { dg-do run { target c++20 } } > > > +// { dg-options "-O0" } > > > +// { dg-timeout 10 } > > > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > > > +// { dg-do run { target { ia32 || x86_64-*-* } } } > > > +// { dg-add-options libatomic } > > > + > > > +#include <atomic> > > > +#include <testsuite_hooks.h> > > > + > > > +template<typename T> > > > +void __attribute__((noinline,noipa)) > > > +fill_padding(T& f) > > > +{ > > > + T mask; > > > + __builtin_memset(&mask, 0xff, sizeof(T)); > > > + __builtin_clear_padding(&mask); > > > + unsigned char* ptr_f = (unsigned char*)&f; > > > + unsigned char* ptr_mask = (unsigned char*)&mask; > > > + for (int i = 0; i < sizeof(T); i++) > > > + { > > > + if (ptr_mask[i] == 0x00) > > > + { > > > + ptr_f[i] = 0xff; > > > + } > > > + } > > > +} > > > + > > > +void > > > +test01() > > > +{ > > > + long double f = 0.5f; // long double may contains padding on X86 > > > + fill_padding(f); > > > + std::atomic<long double> as{ f }; // padding cleared on constructor > > > + long double t = 1.5; > > > + > > > + as.fetch_add(t); > > > + long double s = f + t; > > > + t = as.load(); > > > + VERIFY(s == t); // padding ignored on float comparing > > > + fill_padding(s); > > > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > > > + fill_padding(f); > > > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > > > +} > > > + > > > +int main() > > > +{ > > > + test01(); > > > +} > > > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp > > > index bc387d17ed7..d9a19dadd7f 100644 > > > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > > > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > > > @@ -337,6 +337,7 @@ proc add_options_for_libatomic { flags } { > > > || ([istarget powerpc*-*-*] && [check_effective_target_ilp32]) > > > || [istarget riscv*-*-*] > > > || ([istarget sparc*-*-linux-gnu] && [check_effective_target_ilp32]) > > > + || ([istarget i?86-*-*] || [istarget x86_64-*-*]) > > > > This seems too overkill as "dg-add-options libatomic" is not intended to > > handle 16-byte atomics. Maybe we can fork this to a new dg-add-options > > like "add_options_for_libatomic_16b"? > > > > > } { > > > global TOOL_OPTIONS > > > > > > -- > > > 2.25.1 > > > > -- > > Xi Ruoyao <xry111@xry111.site> > > School of Aerospace Science and Technology, Xidian University ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PING][PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-16 16:16 ` xndcn 2024-01-24 15:53 ` xndcn @ 2024-01-30 16:08 ` xndcn 2024-01-30 16:31 ` [PATCH] " Jonathan Wakely 2024-01-30 16:34 ` Jonathan Wakely 3 siblings, 0 replies; 28+ messages in thread From: xndcn @ 2024-01-30 16:08 UTC (permalink / raw) To: Xi Ruoyao; +Cc: H.J. Lu, GCC Patches, Jakub Jelinek, libstdc++ Ping, thanks. I do not have access to the repo, anyone can please help me submit the patch? Thanks. xndcn <xndchn@gmail.com> 于2024年1月17日周三 00:16写道: > > Sorry about the mangled content... > So I add a new add-options for libatomic_16b: > > --- > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in > __atomic_float constructor. > * testsuite/lib/dg-options.exp: add new add-options for libatomic_16b. > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > libstdc++-v3/testsuite/lib/dg-options.exp | 22 ++++++++ > 3 files changed, 78 insertions(+), 1 deletion(-) > create mode 100644 > libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > diff --git a/libstdc++-v3/include/bits/atomic_base.h > b/libstdc++-v3/include/bits/atomic_base.h > index f4ce0fa53..104ddfdbe 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > new file mode 100644 > index 000000000..d538b3d55 > --- /dev/null > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > @@ -0,0 +1,50 @@ > +// { dg-do run { target c++20 } } > +// { dg-options "-O0" } > +// { dg-timeout 10 } > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > +// { dg-do run { target { ia32 || x86_64-*-* } } } > +// { dg-add-options libatomic_16b } > + > +#include <atomic> > +#include <testsuite_hooks.h> > + > +template<typename T> > +void __attribute__((noinline,noipa)) > +fill_padding(T& f) > +{ > + T mask; > + __builtin_memset(&mask, 0xff, sizeof(T)); > + __builtin_clear_padding(&mask); > + unsigned char* ptr_f = (unsigned char*)&f; > + unsigned char* ptr_mask = (unsigned char*)&mask; > + for (int i = 0; i < sizeof(T); i++) > + { > + if (ptr_mask[i] == 0x00) > + { > + ptr_f[i] = 0xff; > + } > + } > +} > + > +void > +test01() > +{ > + long double f = 0.5f; // long double may contains padding on X86 > + fill_padding(f); > + std::atomic<long double> as{ f }; // padding cleared on constructor > + long double t = 1.5; > + > + as.fetch_add(t); > + long double s = f + t; > + t = as.load(); > + VERIFY(s == t); // padding ignored on float comparing > + fill_padding(s); > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > + fill_padding(f); > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > +} > + > +int main() > +{ > + test01(); > +} > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp > b/libstdc++-v3/testsuite/lib/dg-options.exp > index 850442b6b..25da20d58 100644 > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > @@ -356,6 +356,28 @@ proc add_options_for_libatomic { flags } { > return $flags > } > > +# Add option to link to libatomic, if required for atomics on 16-byte (128-bit) > +proc add_options_for_libatomic_16b { flags } { > + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) > + } { > + global TOOL_OPTIONS > + > + set link_flags "" > + if ![is_remote host] { > + if [info exists TOOL_OPTIONS] { > + set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]" > + } else { > + set link_flags "[atomic_link_flags [get_multilibs]]" > + } > + } > + > + append link_flags " -latomic " > + > + return "$flags $link_flags" > + } > + return $flags > +} > + > # Add options to enable use of deprecated features. > proc add_options_for_using-deprecated { flags } { > return "$flags -U_GLIBCXX_USE_DEPRECATED -D_GLIBCXX_USE_DEPRECATED=1" > -- > 2.25.1 > > > Xi Ruoyao <xry111@xry111.site> 于2024年1月16日周二 18:12写道: > > > > On Tue, 2024-01-16 at 17:53 +0800, xndcn wrote: > > > Thanks, so I add a test: atomic_float/compare_exchange_padding.cc, > > > which will fail due to timeout without the patch. > > > > Please resend in plain text instead of HTML. Sending in HTML causes the > > patch mangled. > > > > And libstdc++ patches should CC libstdc++@gcc.gnu.org, in addition to > > gcc-patches@gcc.gnu.org. > > > > > --- > > > libstdc++-v3/ChangeLog: > > > > > > * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. > > > * testsuite/lib/dg-options.exp: enable libatomic for IA32 and X86-64. > > > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > > > --- > > > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > > > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > > > libstdc++-v3/testsuite/lib/dg-options.exp | 1 + > > > 3 files changed, 57 insertions(+), 1 deletion(-) > > > create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > > > > diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h > > > index d3a2c4f3805..cbe3749e17f 100644 > > > --- a/libstdc++-v3/include/bits/atomic_base.h > > > +++ b/libstdc++-v3/include/bits/atomic_base.h > > > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > > > > constexpr > > > __atomic_float(_Fp __t) : _M_fp(__t) > > > - { } > > > + { > > > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > > > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > > > + __builtin_clear_padding(std::__addressof(_M_fp)); > > > +#endif > > > + } > > > > > > __atomic_float(const __atomic_float&) = delete; > > > __atomic_float& operator=(const __atomic_float&) = delete; > > > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > new file mode 100644 > > > index 00000000000..9376ab22850 > > > --- /dev/null > > > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > @@ -0,0 +1,50 @@ > > > +// { dg-do run { target c++20 } } > > > +// { dg-options "-O0" } > > > +// { dg-timeout 10 } > > > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > > > +// { dg-do run { target { ia32 || x86_64-*-* } } } > > > +// { dg-add-options libatomic } > > > + > > > +#include <atomic> > > > +#include <testsuite_hooks.h> > > > + > > > +template<typename T> > > > +void __attribute__((noinline,noipa)) > > > +fill_padding(T& f) > > > +{ > > > + T mask; > > > + __builtin_memset(&mask, 0xff, sizeof(T)); > > > + __builtin_clear_padding(&mask); > > > + unsigned char* ptr_f = (unsigned char*)&f; > > > + unsigned char* ptr_mask = (unsigned char*)&mask; > > > + for (int i = 0; i < sizeof(T); i++) > > > + { > > > + if (ptr_mask[i] == 0x00) > > > + { > > > + ptr_f[i] = 0xff; > > > + } > > > + } > > > +} > > > + > > > +void > > > +test01() > > > +{ > > > + long double f = 0.5f; // long double may contains padding on X86 > > > + fill_padding(f); > > > + std::atomic<long double> as{ f }; // padding cleared on constructor > > > + long double t = 1.5; > > > + > > > + as.fetch_add(t); > > > + long double s = f + t; > > > + t = as.load(); > > > + VERIFY(s == t); // padding ignored on float comparing > > > + fill_padding(s); > > > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > > > + fill_padding(f); > > > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > > > +} > > > + > > > +int main() > > > +{ > > > + test01(); > > > +} > > > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp > > > index bc387d17ed7..d9a19dadd7f 100644 > > > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > > > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > > > @@ -337,6 +337,7 @@ proc add_options_for_libatomic { flags } { > > > || ([istarget powerpc*-*-*] && [check_effective_target_ilp32]) > > > || [istarget riscv*-*-*] > > > || ([istarget sparc*-*-linux-gnu] && [check_effective_target_ilp32]) > > > + || ([istarget i?86-*-*] || [istarget x86_64-*-*]) > > > > This seems too overkill as "dg-add-options libatomic" is not intended to > > handle 16-byte atomics. Maybe we can fork this to a new dg-add-options > > like "add_options_for_libatomic_16b"? > > > > > } { > > > global TOOL_OPTIONS > > > > > > -- > > > 2.25.1 > > > > -- > > Xi Ruoyao <xry111@xry111.site> > > School of Aerospace Science and Technology, Xidian University ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-16 16:16 ` xndcn 2024-01-24 15:53 ` xndcn 2024-01-30 16:08 ` [PING][PATCH] " xndcn @ 2024-01-30 16:31 ` Jonathan Wakely 2024-01-30 16:34 ` Jonathan Wakely 3 siblings, 0 replies; 28+ messages in thread From: Jonathan Wakely @ 2024-01-30 16:31 UTC (permalink / raw) To: xndcn; +Cc: Xi Ruoyao, H.J. Lu, GCC Patches, Jakub Jelinek, libstdc++ On Tue, 16 Jan 2024 at 16:17, xndcn <xndchn@gmail.com> wrote: > > Sorry about the mangled content... > So I add a new add-options for libatomic_16b: > > --- > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in > __atomic_float constructor. > * testsuite/lib/dg-options.exp: add new add-options for libatomic_16b. > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > libstdc++-v3/testsuite/lib/dg-options.exp | 22 ++++++++ > 3 files changed, 78 insertions(+), 1 deletion(-) > create mode 100644 > libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > diff --git a/libstdc++-v3/include/bits/atomic_base.h > b/libstdc++-v3/include/bits/atomic_base.h > index f4ce0fa53..104ddfdbe 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) This code is not compiled for C++11 and C++14, so this should just use constexpr not _GLIBCXX17_CONSTEXPR. Apart from that I think this patch looks OK. > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > new file mode 100644 > index 000000000..d538b3d55 > --- /dev/null > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > @@ -0,0 +1,50 @@ > +// { dg-do run { target c++20 } } > +// { dg-options "-O0" } > +// { dg-timeout 10 } > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > +// { dg-do run { target { ia32 || x86_64-*-* } } } > +// { dg-add-options libatomic_16b } > + > +#include <atomic> > +#include <testsuite_hooks.h> > + > +template<typename T> > +void __attribute__((noinline,noipa)) > +fill_padding(T& f) > +{ > + T mask; > + __builtin_memset(&mask, 0xff, sizeof(T)); > + __builtin_clear_padding(&mask); > + unsigned char* ptr_f = (unsigned char*)&f; > + unsigned char* ptr_mask = (unsigned char*)&mask; > + for (int i = 0; i < sizeof(T); i++) > + { > + if (ptr_mask[i] == 0x00) > + { > + ptr_f[i] = 0xff; > + } > + } > +} > + > +void > +test01() > +{ > + long double f = 0.5f; // long double may contains padding on X86 > + fill_padding(f); > + std::atomic<long double> as{ f }; // padding cleared on constructor > + long double t = 1.5; > + > + as.fetch_add(t); > + long double s = f + t; > + t = as.load(); > + VERIFY(s == t); // padding ignored on float comparing > + fill_padding(s); > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > + fill_padding(f); > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > +} > + > +int main() > +{ > + test01(); > +} > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp > b/libstdc++-v3/testsuite/lib/dg-options.exp > index 850442b6b..25da20d58 100644 > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > @@ -356,6 +356,28 @@ proc add_options_for_libatomic { flags } { > return $flags > } > > +# Add option to link to libatomic, if required for atomics on 16-byte (128-bit) > +proc add_options_for_libatomic_16b { flags } { > + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) > + } { > + global TOOL_OPTIONS > + > + set link_flags "" > + if ![is_remote host] { > + if [info exists TOOL_OPTIONS] { > + set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]" > + } else { > + set link_flags "[atomic_link_flags [get_multilibs]]" > + } > + } > + > + append link_flags " -latomic " > + > + return "$flags $link_flags" > + } > + return $flags > +} > + > # Add options to enable use of deprecated features. > proc add_options_for_using-deprecated { flags } { > return "$flags -U_GLIBCXX_USE_DEPRECATED -D_GLIBCXX_USE_DEPRECATED=1" > -- > 2.25.1 > > > Xi Ruoyao <xry111@xry111.site> 于2024年1月16日周二 18:12写道: > > > > On Tue, 2024-01-16 at 17:53 +0800, xndcn wrote: > > > Thanks, so I add a test: atomic_float/compare_exchange_padding.cc, > > > which will fail due to timeout without the patch. > > > > Please resend in plain text instead of HTML. Sending in HTML causes the > > patch mangled. > > > > And libstdc++ patches should CC libstdc++@gcc.gnu.org, in addition to > > gcc-patches@gcc.gnu.org. > > > > > --- > > > libstdc++-v3/ChangeLog: > > > > > > * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. > > > * testsuite/lib/dg-options.exp: enable libatomic for IA32 and X86-64. > > > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > > > --- > > > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > > > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > > > libstdc++-v3/testsuite/lib/dg-options.exp | 1 + > > > 3 files changed, 57 insertions(+), 1 deletion(-) > > > create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > > > > diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h > > > index d3a2c4f3805..cbe3749e17f 100644 > > > --- a/libstdc++-v3/include/bits/atomic_base.h > > > +++ b/libstdc++-v3/include/bits/atomic_base.h > > > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > > > > constexpr > > > __atomic_float(_Fp __t) : _M_fp(__t) > > > - { } > > > + { > > > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > > > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > > > + __builtin_clear_padding(std::__addressof(_M_fp)); > > > +#endif > > > + } > > > > > > __atomic_float(const __atomic_float&) = delete; > > > __atomic_float& operator=(const __atomic_float&) = delete; > > > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > new file mode 100644 > > > index 00000000000..9376ab22850 > > > --- /dev/null > > > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > @@ -0,0 +1,50 @@ > > > +// { dg-do run { target c++20 } } > > > +// { dg-options "-O0" } > > > +// { dg-timeout 10 } > > > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > > > +// { dg-do run { target { ia32 || x86_64-*-* } } } > > > +// { dg-add-options libatomic } > > > + > > > +#include <atomic> > > > +#include <testsuite_hooks.h> > > > + > > > +template<typename T> > > > +void __attribute__((noinline,noipa)) > > > +fill_padding(T& f) > > > +{ > > > + T mask; > > > + __builtin_memset(&mask, 0xff, sizeof(T)); > > > + __builtin_clear_padding(&mask); > > > + unsigned char* ptr_f = (unsigned char*)&f; > > > + unsigned char* ptr_mask = (unsigned char*)&mask; > > > + for (int i = 0; i < sizeof(T); i++) > > > + { > > > + if (ptr_mask[i] == 0x00) > > > + { > > > + ptr_f[i] = 0xff; > > > + } > > > + } > > > +} > > > + > > > +void > > > +test01() > > > +{ > > > + long double f = 0.5f; // long double may contains padding on X86 > > > + fill_padding(f); > > > + std::atomic<long double> as{ f }; // padding cleared on constructor > > > + long double t = 1.5; > > > + > > > + as.fetch_add(t); > > > + long double s = f + t; > > > + t = as.load(); > > > + VERIFY(s == t); // padding ignored on float comparing > > > + fill_padding(s); > > > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > > > + fill_padding(f); > > > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > > > +} > > > + > > > +int main() > > > +{ > > > + test01(); > > > +} > > > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp > > > index bc387d17ed7..d9a19dadd7f 100644 > > > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > > > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > > > @@ -337,6 +337,7 @@ proc add_options_for_libatomic { flags } { > > > || ([istarget powerpc*-*-*] && [check_effective_target_ilp32]) > > > || [istarget riscv*-*-*] > > > || ([istarget sparc*-*-linux-gnu] && [check_effective_target_ilp32]) > > > + || ([istarget i?86-*-*] || [istarget x86_64-*-*]) > > > > This seems too overkill as "dg-add-options libatomic" is not intended to > > handle 16-byte atomics. Maybe we can fork this to a new dg-add-options > > like "add_options_for_libatomic_16b"? > > > > > } { > > > global TOOL_OPTIONS > > > > > > -- > > > 2.25.1 > > > > -- > > Xi Ruoyao <xry111@xry111.site> > > School of Aerospace Science and Technology, Xidian University > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-16 16:16 ` xndcn ` (2 preceding siblings ...) 2024-01-30 16:31 ` [PATCH] " Jonathan Wakely @ 2024-01-30 16:34 ` Jonathan Wakely 2024-01-30 16:50 ` Jakub Jelinek 3 siblings, 1 reply; 28+ messages in thread From: Jonathan Wakely @ 2024-01-30 16:34 UTC (permalink / raw) To: xndcn; +Cc: Xi Ruoyao, H.J. Lu, GCC Patches, Jakub Jelinek, libstdc++ On Tue, 16 Jan 2024 at 16:17, xndcn <xndchn@gmail.com> wrote: > > Sorry about the mangled content... > So I add a new add-options for libatomic_16b: > > --- > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in > __atomic_float constructor. > * testsuite/lib/dg-options.exp: add new add-options for libatomic_16b. > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > libstdc++-v3/testsuite/lib/dg-options.exp | 22 ++++++++ > 3 files changed, 78 insertions(+), 1 deletion(-) > create mode 100644 > libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > diff --git a/libstdc++-v3/include/bits/atomic_base.h > b/libstdc++-v3/include/bits/atomic_base.h > index f4ce0fa53..104ddfdbe 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > new file mode 100644 > index 000000000..d538b3d55 > --- /dev/null > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > @@ -0,0 +1,50 @@ > +// { dg-do run { target c++20 } } > +// { dg-options "-O0" } > +// { dg-timeout 10 } > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > +// { dg-do run { target { ia32 || x86_64-*-* } } } > +// { dg-add-options libatomic_16b } Why not just use -latomic unconditionally here? You're adding a new libatomic_16b option that expands to -latomic for x86 and nothing otherwise, and then using it in a test that only runs for x86. So it's just adding -latomic to all targets that run the test, right? Also, this patch needs either a copyright assignment or a DCO sign-off: https://gcc.gnu.org/contribute.html#legal > + > +#include <atomic> > +#include <testsuite_hooks.h> > + > +template<typename T> > +void __attribute__((noinline,noipa)) > +fill_padding(T& f) > +{ > + T mask; > + __builtin_memset(&mask, 0xff, sizeof(T)); > + __builtin_clear_padding(&mask); > + unsigned char* ptr_f = (unsigned char*)&f; > + unsigned char* ptr_mask = (unsigned char*)&mask; > + for (int i = 0; i < sizeof(T); i++) > + { > + if (ptr_mask[i] == 0x00) > + { > + ptr_f[i] = 0xff; > + } > + } > +} > + > +void > +test01() > +{ > + long double f = 0.5f; // long double may contains padding on X86 > + fill_padding(f); > + std::atomic<long double> as{ f }; // padding cleared on constructor > + long double t = 1.5; > + > + as.fetch_add(t); > + long double s = f + t; > + t = as.load(); > + VERIFY(s == t); // padding ignored on float comparing > + fill_padding(s); > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > + fill_padding(f); > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > +} > + > +int main() > +{ > + test01(); > +} > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp > b/libstdc++-v3/testsuite/lib/dg-options.exp > index 850442b6b..25da20d58 100644 > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > @@ -356,6 +356,28 @@ proc add_options_for_libatomic { flags } { > return $flags > } > > +# Add option to link to libatomic, if required for atomics on 16-byte (128-bit) > +proc add_options_for_libatomic_16b { flags } { > + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) > + } { > + global TOOL_OPTIONS > + > + set link_flags "" > + if ![is_remote host] { > + if [info exists TOOL_OPTIONS] { > + set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]" > + } else { > + set link_flags "[atomic_link_flags [get_multilibs]]" > + } > + } > + > + append link_flags " -latomic " > + > + return "$flags $link_flags" > + } > + return $flags > +} > + > # Add options to enable use of deprecated features. > proc add_options_for_using-deprecated { flags } { > return "$flags -U_GLIBCXX_USE_DEPRECATED -D_GLIBCXX_USE_DEPRECATED=1" > -- > 2.25.1 > > > Xi Ruoyao <xry111@xry111.site> 于2024年1月16日周二 18:12写道: > > > > On Tue, 2024-01-16 at 17:53 +0800, xndcn wrote: > > > Thanks, so I add a test: atomic_float/compare_exchange_padding.cc, > > > which will fail due to timeout without the patch. > > > > Please resend in plain text instead of HTML. Sending in HTML causes the > > patch mangled. > > > > And libstdc++ patches should CC libstdc++@gcc.gnu.org, in addition to > > gcc-patches@gcc.gnu.org. > > > > > --- > > > libstdc++-v3/ChangeLog: > > > > > > * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. > > > * testsuite/lib/dg-options.exp: enable libatomic for IA32 and X86-64. > > > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > > > --- > > > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > > > .../atomic_float/compare_exchange_padding.cc | 50 +++++++++++++++++++ > > > libstdc++-v3/testsuite/lib/dg-options.exp | 1 + > > > 3 files changed, 57 insertions(+), 1 deletion(-) > > > create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > > > > diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h > > > index d3a2c4f3805..cbe3749e17f 100644 > > > --- a/libstdc++-v3/include/bits/atomic_base.h > > > +++ b/libstdc++-v3/include/bits/atomic_base.h > > > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > > > > constexpr > > > __atomic_float(_Fp __t) : _M_fp(__t) > > > - { } > > > + { > > > +#if __cplusplus >= 201402L && __has_builtin(__builtin_clear_padding) > > > + if _GLIBCXX17_CONSTEXPR (__atomic_impl::__maybe_has_padding<_Fp>()) > > > + __builtin_clear_padding(std::__addressof(_M_fp)); > > > +#endif > > > + } > > > > > > __atomic_float(const __atomic_float&) = delete; > > > __atomic_float& operator=(const __atomic_float&) = delete; > > > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > new file mode 100644 > > > index 00000000000..9376ab22850 > > > --- /dev/null > > > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > > @@ -0,0 +1,50 @@ > > > +// { dg-do run { target c++20 } } > > > +// { dg-options "-O0" } > > > +// { dg-timeout 10 } > > > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > > > +// { dg-do run { target { ia32 || x86_64-*-* } } } > > > +// { dg-add-options libatomic } > > > + > > > +#include <atomic> > > > +#include <testsuite_hooks.h> > > > + > > > +template<typename T> > > > +void __attribute__((noinline,noipa)) > > > +fill_padding(T& f) > > > +{ > > > + T mask; > > > + __builtin_memset(&mask, 0xff, sizeof(T)); > > > + __builtin_clear_padding(&mask); > > > + unsigned char* ptr_f = (unsigned char*)&f; > > > + unsigned char* ptr_mask = (unsigned char*)&mask; > > > + for (int i = 0; i < sizeof(T); i++) > > > + { > > > + if (ptr_mask[i] == 0x00) > > > + { > > > + ptr_f[i] = 0xff; > > > + } > > > + } > > > +} > > > + > > > +void > > > +test01() > > > +{ > > > + long double f = 0.5f; // long double may contains padding on X86 > > > + fill_padding(f); > > > + std::atomic<long double> as{ f }; // padding cleared on constructor > > > + long double t = 1.5; > > > + > > > + as.fetch_add(t); > > > + long double s = f + t; > > > + t = as.load(); > > > + VERIFY(s == t); // padding ignored on float comparing > > > + fill_padding(s); > > > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > > > + fill_padding(f); > > > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > > > +} > > > + > > > +int main() > > > +{ > > > + test01(); > > > +} > > > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp > > > index bc387d17ed7..d9a19dadd7f 100644 > > > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > > > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > > > @@ -337,6 +337,7 @@ proc add_options_for_libatomic { flags } { > > > || ([istarget powerpc*-*-*] && [check_effective_target_ilp32]) > > > || [istarget riscv*-*-*] > > > || ([istarget sparc*-*-linux-gnu] && [check_effective_target_ilp32]) > > > + || ([istarget i?86-*-*] || [istarget x86_64-*-*]) > > > > This seems too overkill as "dg-add-options libatomic" is not intended to > > handle 16-byte atomics. Maybe we can fork this to a new dg-add-options > > like "add_options_for_libatomic_16b"? > > > > > } { > > > global TOOL_OPTIONS > > > > > > -- > > > 2.25.1 > > > > -- > > Xi Ruoyao <xry111@xry111.site> > > School of Aerospace Science and Technology, Xidian University > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-30 16:34 ` Jonathan Wakely @ 2024-01-30 16:50 ` Jakub Jelinek 2024-01-31 17:19 ` xndcn 0 siblings, 1 reply; 28+ messages in thread From: Jakub Jelinek @ 2024-01-30 16:50 UTC (permalink / raw) To: Jonathan Wakely; +Cc: xndcn, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ On Tue, Jan 30, 2024 at 04:34:30PM +0000, Jonathan Wakely wrote: > > --- /dev/null > > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > @@ -0,0 +1,50 @@ > > +// { dg-do run { target c++20 } } > > +// { dg-options "-O0" } > > +// { dg-timeout 10 } Why dg-timeout? I don't see it used in any of the libstdc++ tests and I don't see anything expensive on this test. Just leave it out. > > +// { dg-additional-options "-mlong-double-80" { target x86_64-*-* } } > > +// { dg-do run { target { ia32 || x86_64-*-* } } } Also, the target selectors above look wrong. Generally, one should use { i?86-*-* x86_64-*-* } because e.g. on some OSes like Solaris, one builds i?86 compiler which supports -m32 or -m64 options. I wouldn't add the -mlong-double-80 at all, it is an ABI changing option, if you rely in the test on some 80-bit long double properties (but on which ones? Sure, if -mlong-double-64 or -mlong-double-128 is in effect, the type won't have any padding, but __builtin_clear_padding should reflect that), it is better to guard the part of the test with some checks, whether std::numeric_limits<long double>::digits == 64, or preprocessor __LDBL_MANT_DIG__ == 64. > > +// { dg-add-options libatomic_16b } > > Why not just use -latomic unconditionally here? > > You're adding a new libatomic_16b option that expands to -latomic for > x86 and nothing otherwise, and then using it in a test that only runs > for x86. So it's just adding -latomic to all targets that run the > test, right? > > Also, this patch needs either a copyright assignment or a DCO sign-off: > https://gcc.gnu.org/contribute.html#legal And if somebody would need to commit it for you, also patch in non-garbled state (e.g. sent as an attachment, or even compressed attachment if using really bad MUAs). Jakub ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-30 16:50 ` Jakub Jelinek @ 2024-01-31 17:19 ` xndcn 2024-02-01 13:54 ` Jonathan Wakely 0 siblings, 1 reply; 28+ messages in thread From: xndcn @ 2024-01-31 17:19 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Jonathan Wakely, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ Thanks! > Why not just use -latomic unconditionally here? testsuites of libstdc++ seems to have some tricks to find and link libatomic.a by using "dg-add-options libatomic", which do nothing for x86 target. In previous email, we decide not to pollute the current option, so we add a new libatomic_16b option here. > Why dg-timeout? without the patch, "as.fetch_add(t);" will result in an infinite loop, so I add timeout to help it escape. Should I keep it or not? > Also, the target selectors above look wrong. Thanks, fixed with checking "std::numeric_limits<long double>::digits == 64". > This code is not compiled for C++11 and C++14, so this should just use > constexpr not _GLIBCXX17_CONSTEXPR. Thanks, fixed with "constexpr". So here is the fixed patch, please review it again, thanks: --- libstdc++-v3/ChangeLog: * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. * testsuite/lib/dg-options.exp: add new add-options for libatomic_16b. * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. Signed-off-by: xndcn <xndchn@gmail.com> --- libstdc++-v3/include/bits/atomic_base.h | 7 ++- .../atomic_float/compare_exchange_padding.cc | 54 +++++++++++++++++++ libstdc++-v3/testsuite/lib/dg-options.exp | 22 ++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index f4ce0fa53..90e3f0e4b 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr __atomic_float(_Fp __t) : _M_fp(__t) - { } + { +#if __has_builtin(__builtin_clear_padding) + if constexpr (__atomic_impl::__maybe_has_padding<_Fp>()) + __builtin_clear_padding(std::__addressof(_M_fp)); +#endif + } __atomic_float(const __atomic_float&) = delete; __atomic_float& operator=(const __atomic_float&) = delete; diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc new file mode 100644 index 000000000..e6e17e4b5 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc @@ -0,0 +1,54 @@ +// { dg-do run { target c++20 } } +// { dg-options "-O0" } +// { dg-timeout 10 } +// { dg-do run { target { i?86-*-* x86_64-*-* } } } +// { dg-add-options libatomic_16b } + +#include <atomic> +#include <limits> +#include <testsuite_hooks.h> + +template<typename T> +void __attribute__((noinline,noipa)) +fill_padding(T& f) +{ + T mask; + __builtin_memset(&mask, 0xff, sizeof(T)); + __builtin_clear_padding(&mask); + unsigned char* ptr_f = (unsigned char*)&f; + unsigned char* ptr_mask = (unsigned char*)&mask; + for (int i = 0; i < sizeof(T); i++) + { + if (ptr_mask[i] == 0x00) + { + ptr_f[i] = 0xff; + } + } +} + +void +test01() +{ + // test for long double with padding (float80) + if constexpr (std::numeric_limits<long double>::digits == 64) + { + long double f = 0.5f; // long double may contains padding on X86 + fill_padding(f); + std::atomic<long double> as{ f }; // padding cleared on constructor + long double t = 1.5; + + as.fetch_add(t); + long double s = f + t; + t = as.load(); + VERIFY(s == t); // padding ignored on float comparing + fill_padding(s); + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg + fill_padding(f); + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg + } +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp index 850442b6b..75b27a136 100644 --- a/libstdc++-v3/testsuite/lib/dg-options.exp +++ b/libstdc++-v3/testsuite/lib/dg-options.exp @@ -356,6 +356,28 @@ proc add_options_for_libatomic { flags } { return $flags } +# Add option to link to libatomic, if required for atomics on 16-byte (128-bit) +proc add_options_for_libatomic_16b { flags } { + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) + } { + global TOOL_OPTIONS + + set link_flags "" + if ![is_remote host] { + if [info exists TOOL_OPTIONS] { + set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]" + } else { + set link_flags "[atomic_link_flags [get_multilibs]]" + } + } + + append link_flags " -latomic " + + return "$flags $link_flags" + } + return $flags +} + # Add options to enable use of deprecated features. proc add_options_for_using-deprecated { flags } { return "$flags -U_GLIBCXX_USE_DEPRECATED -D_GLIBCXX_USE_DEPRECATED=1" -- 2.25.1 ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-01-31 17:19 ` xndcn @ 2024-02-01 13:54 ` Jonathan Wakely 2024-02-02 16:52 ` xndcn 0 siblings, 1 reply; 28+ messages in thread From: Jonathan Wakely @ 2024-02-01 13:54 UTC (permalink / raw) To: xndcn; +Cc: Jakub Jelinek, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ On Wed, 31 Jan 2024 at 17:20, xndcn <xndchn@gmail.com> wrote: > > Thanks! > > > Why not just use -latomic unconditionally here? > testsuites of libstdc++ seems to have some tricks to find and link > libatomic.a by using "dg-add-options libatomic", which do nothing for > x86 target. In previous email, we decide not to pollute the current > option, so we add a new libatomic_16b option here. Right, we don't want to change the existing libatomic option. But we don't need a new one if it's going to be used in exactly one test and if the new option does the same thing for all targets that run the test. However, on that subject, does the test really need to be restricted to x86? It shouldn't loop on any target, right? > > > Why dg-timeout? > without the patch, "as.fetch_add(t);" will result in an infinite loop, > so I add timeout to help it escape. Should I keep it or not? No, because the patch is supposed to prevent the infinite loop, and so there's no need to stop it looping after 10s. It won't loop at all. > > > Also, the target selectors above look wrong. > Thanks, fixed with checking "std::numeric_limits<long double>::digits == 64". > > > This code is not compiled for C++11 and C++14, so this should just use > > constexpr not _GLIBCXX17_CONSTEXPR. > Thanks, fixed with "constexpr". Actually, why are you using the built-in directly in the first place? See below. > > So here is the fixed patch, please review it again, thanks: > --- > libstdc++-v3/ChangeLog: > > * include/bits/atomic_base.h: add __builtin_clear_padding in > __atomic_float constructor. > * testsuite/lib/dg-options.exp: add new add-options for libatomic_16b. > * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. > > Signed-off-by: xndcn <xndchn@gmail.com> > --- > libstdc++-v3/include/bits/atomic_base.h | 7 ++- > .../atomic_float/compare_exchange_padding.cc | 54 +++++++++++++++++++ > libstdc++-v3/testsuite/lib/dg-options.exp | 22 ++++++++ > 3 files changed, 82 insertions(+), 1 deletion(-) > create mode 100644 > libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > > diff --git a/libstdc++-v3/include/bits/atomic_base.h > b/libstdc++-v3/include/bits/atomic_base.h > index f4ce0fa53..90e3f0e4b 100644 > --- a/libstdc++-v3/include/bits/atomic_base.h > +++ b/libstdc++-v3/include/bits/atomic_base.h > @@ -1283,7 +1283,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > constexpr > __atomic_float(_Fp __t) : _M_fp(__t) > - { } > + { > +#if __has_builtin(__builtin_clear_padding) > + if constexpr (__atomic_impl::__maybe_has_padding<_Fp>()) > + __builtin_clear_padding(std::__addressof(_M_fp)); > +#endif > + } Why can't this be simply: { __atomic_impl::__clear_padding(_M_fp); } ? We only need to clear padding for long double, not float and double, right? > > __atomic_float(const __atomic_float&) = delete; > __atomic_float& operator=(const __atomic_float&) = delete; > diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > new file mode 100644 > index 000000000..e6e17e4b5 > --- /dev/null > +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc > @@ -0,0 +1,54 @@ > +// { dg-do run { target c++20 } } > +// { dg-options "-O0" } > +// { dg-timeout 10 } > +// { dg-do run { target { i?86-*-* x86_64-*-* } } } Why can't we run this on all targets? > +// { dg-add-options libatomic_16b } Let's just add -latomic to the dg-options line for this one test. We don't want that in general because we want to know that atomics work without it in most cases. It should be fine to use it for one test. > + > +#include <atomic> > +#include <limits> > +#include <testsuite_hooks.h> > + > +template<typename T> > +void __attribute__((noinline,noipa)) > +fill_padding(T& f) > +{ > + T mask; > + __builtin_memset(&mask, 0xff, sizeof(T)); There's no reason to use __builtin_memset here, just include <cstring> and use std::memcpy. > + __builtin_clear_padding(&mask); > + unsigned char* ptr_f = (unsigned char*)&f; > + unsigned char* ptr_mask = (unsigned char*)&mask; > + for (int i = 0; i < sizeof(T); i++) > + { > + if (ptr_mask[i] == 0x00) > + { > + ptr_f[i] = 0xff; > + } > + } > +} > + > +void > +test01() > +{ > + // test for long double with padding (float80) > + if constexpr (std::numeric_limits<long double>::digits == 64) > + { > + long double f = 0.5f; // long double may contains padding on X86 It definitely does have padding, just say "long double has padding bits on x86" > + fill_padding(f); > + std::atomic<long double> as{ f }; // padding cleared on constructor > + long double t = 1.5; > + > + as.fetch_add(t); > + long double s = f + t; > + t = as.load(); > + VERIFY(s == t); // padding ignored on float comparing > + fill_padding(s); > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > + fill_padding(f); > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > + } > +} > + > +int main() > +{ > + test01(); > +} > diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp > b/libstdc++-v3/testsuite/lib/dg-options.exp > index 850442b6b..75b27a136 100644 > --- a/libstdc++-v3/testsuite/lib/dg-options.exp > +++ b/libstdc++-v3/testsuite/lib/dg-options.exp > @@ -356,6 +356,28 @@ proc add_options_for_libatomic { flags } { > return $flags > } > > +# Add option to link to libatomic, if required for atomics on 16-byte (128-bit) > +proc add_options_for_libatomic_16b { flags } { > + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) > + } { > + global TOOL_OPTIONS > + > + set link_flags "" > + if ![is_remote host] { > + if [info exists TOOL_OPTIONS] { > + set link_flags "[atomic_link_flags [get_multilibs ${TOOL_OPTIONS}]]" > + } else { > + set link_flags "[atomic_link_flags [get_multilibs]]" > + } > + } > + > + append link_flags " -latomic " > + > + return "$flags $link_flags" > + } > + return $flags > +} > + > # Add options to enable use of deprecated features. > proc add_options_for_using-deprecated { flags } { > return "$flags -U_GLIBCXX_USE_DEPRECATED -D_GLIBCXX_USE_DEPRECATED=1" > -- > 2.25.1 > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-02-01 13:54 ` Jonathan Wakely @ 2024-02-02 16:52 ` xndcn 2024-02-16 12:38 ` Jonathan Wakely 0 siblings, 1 reply; 28+ messages in thread From: xndcn @ 2024-02-02 16:52 UTC (permalink / raw) To: Jonathan Wakely; +Cc: Jakub Jelinek, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ Thank you for your careful review! > But we don't need a new one if it's going to be used in exactly one test and if the new option does the same thing for all targets that run the test. Got it, thanks. Now add option "-latomic" directly, but it still rely on the trick "[atomic_link_flags [get_multilibs]]" > No, because the patch is supposed to prevent the infinite loop, and so there's no need to stop it looping after 10s. It won't loop at all. Thanks, deleted. > We only need to clear padding for long double, not float and double, right? Yes, actually there is a check "if constexpr (__atomic_impl::__maybe_has_padding<_Fp>())". But "__atomic_impl::__clear_padding(_M_fp); " is indeed simply, so fixed here. > Why can't we run this on all targets? Got it, now target option deleted. > There's no reason to use __builtin_memset here, just include <cstring> and use std::memcpy. Thanks, fixed. > It definitely does have padding, just say "long double has padding bits on x86" Thanks, fixed. So here comes the latest patch: --- libstdc++-v3/ChangeLog: * include/bits/atomic_base.h: add __builtin_clear_padding in __atomic_float constructor. * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. Signed-off-by: xndcn <xndchn@gmail.com> --- libstdc++-v3/include/bits/atomic_base.h | 2 +- .../atomic_float/compare_exchange_padding.cc | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index f4ce0fa53..cdd6f07da 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1283,7 +1283,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr __atomic_float(_Fp __t) : _M_fp(__t) - { } + { __atomic_impl::__clear_padding(_M_fp); } __atomic_float(const __atomic_float&) = delete; __atomic_float& operator=(const __atomic_float&) = delete; diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc new file mode 100644 index 000000000..eeace251c --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc @@ -0,0 +1,53 @@ +// { dg-do run { target c++20 } } +// { dg-options "-O0" } +// { dg-additional-options "[atomic_link_flags [get_multilibs]] -latomic" } + +#include <atomic> +#include <cstring> +#include <limits> +#include <testsuite_hooks.h> + +template<typename T> +void __attribute__((noinline,noipa)) +fill_padding(T& f) +{ + T mask; + std::memset(&mask, 0xff, sizeof(T)); + __builtin_clear_padding(&mask); + unsigned char* ptr_f = (unsigned char*)&f; + unsigned char* ptr_mask = (unsigned char*)&mask; + for (int i = 0; i < sizeof(T); i++) + { + if (ptr_mask[i] == 0x00) + { + ptr_f[i] = 0xff; + } + } +} + +void +test01() +{ + // test for long double with padding (float80) + if constexpr (std::numeric_limits<long double>::digits == 64) + { + long double f = 0.5f; // long double has padding bits on x86 + fill_padding(f); + std::atomic<long double> as{ f }; // padding cleared on constructor + long double t = 1.5; + + as.fetch_add(t); + long double s = f + t; + t = as.load(); + VERIFY(s == t); // padding ignored on float comparing + fill_padding(s); + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg + fill_padding(f); + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg + } +} + +int main() +{ + test01(); +} -- 2.25.1 ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-02-02 16:52 ` xndcn @ 2024-02-16 12:38 ` Jonathan Wakely 2024-02-16 13:51 ` Jonathan Wakely 0 siblings, 1 reply; 28+ messages in thread From: Jonathan Wakely @ 2024-02-16 12:38 UTC (permalink / raw) To: xndcn; +Cc: Jakub Jelinek, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ On Fri, 2 Feb 2024 at 16:52, xndcn <xndchn@gmail.com> wrote: > > Thank you for your careful review! > > > But we don't need a new one if it's going to be used in exactly one test and if the new option does the same thing for all targets that run the test. > Got it, thanks. Now add option "-latomic" directly, but it still rely > on the trick "[atomic_link_flags [get_multilibs]]" > > > No, because the patch is supposed to prevent the infinite loop, and so there's no need to stop it looping after 10s. It won't loop at all. > Thanks, deleted. > > > We only need to clear padding for long double, not float and double, right? > Yes, actually there is a check "if constexpr > (__atomic_impl::__maybe_has_padding<_Fp>())". > But "__atomic_impl::__clear_padding(_M_fp); " is indeed simply, so fixed here. > > > Why can't we run this on all targets? > Got it, now target option deleted. > > > There's no reason to use __builtin_memset here, just include <cstring> and use std::memcpy. > Thanks, fixed. > > > It definitely does have padding, just say "long double has padding bits on x86" > Thanks, fixed. > > So here comes the latest patch: Thanks. I've applied the patch to my tree, but the new test fails pretty reliably. The infinite loop in std::atomic<long double>::fetch_add is fixed by clearing padding in the constructor, but the test fails on the compare_exchange_weak or compare_exchange_strong lines here: > + as.fetch_add(t); > + long double s = f + t; > + t = as.load(); > + VERIFY(s == t); // padding ignored on float comparing > + fill_padding(s); > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > + fill_padding(f); > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > I think the problem is here in __atomic_impl::__compare_exchange: if (__atomic_compare_exchange(__pval, __pexp, __pi, __is_weak, int(__s), int(__f))) return true; Even though padding in *__pexp and *__pi has been cleared, the value of *__pval after a successful __atomic_compare_exchange has non-zero padding. That means that the next compare_exchange will fail, because we assume that the stored value always has zeroed padding bits. Here's a gdb session showing that __atomic_compare_exchange stores a value with non-zero padding: Breakpoint 2, test01 () at compare_exchange_padding.cc:43 43 long double s2 = s; (gdb) n 44 fill_padding(s2); (gdb) 45 while (!as.compare_exchange_weak(s2, f)) // padding cleared on compexchg (gdb) p/x as._M_fp $11 = 0x40008000000000000000 (gdb) step std::__atomic_float<long double>::compare_exchange_weak (this=0x7fffffffd8c0, __expected=@0x7fffffffd8a0: 2, __desired=0.5, __order=std::memory_order::seq_cst) at /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:1387 1387 return compare_exchange_weak(__expected, __desired, __order, (gdb) step std::__atomic_float<long double>::compare_exchange_weak (this=0x7fffffffd8c0, __expected=@0x7fffffffd8a0: 2, __desired=0.5, __success=std::memory_order::seq_cst, __failure=std::memory_order::seq_cst) at /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:1347 1347 return __atomic_impl::compare_exchange_weak(&_M_fp, (gdb) step std::__atomic_impl::compare_exchange_weak<false, long double> (__check_padding=false, __failure=std::memory_order::seq_cst, __success=std::memory_order::seq_cst, __desired=0.5, __expected=@0x7fffffffd8a0: 2, __ptr=0x7fffffffd8c0) at /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:1123 1123 return __atomic_impl::__compare_exchange<_AtomicRef>( (gdb) std::__atomic_impl::__compare_exchange<false, long double> (__f=std::memory_order::seq_cst, __s=std::memory_order::seq_cst, __is_weak=true, __i=<optimized out>, __e=@0x7fffffffd8a0: 2, __val=@0x7fffffffd8c0: 2) at /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:994 994 __glibcxx_assert(__is_valid_cmpexch_failure_order(__f)); (gdb) n 997 _Tp* const __pval = std::__addressof(__val); (gdb) 1008 _Vp* const __pi = __atomic_impl::__clear_padding(__i); (gdb) 1010 _Vp __exp = __e; (gdb) 1012 _Vp* const __pexp = __atomic_impl::__clear_padding(__exp); (gdb) 1016 if (__atomic_compare_exchange(__pval, __pexp, __pi, (gdb) p/x *__pval $12 = 0x40008000000000000000 (gdb) p/x *__pexp $13 = 0x40008000000000000000 (gdb) p/x *__pi $14 = 0x3ffe8000000000000000 (gdb) n 1018 return true; (gdb) p/x *__pval $15 = 0x7ffff7bf3ffe8000000000000000 (gdb) We stored *__pi which has zero padding, but the result in *__pval has non-zero padding. This doesn't seem to be gdb being misleading by loading *__pval into a FP register which doesn't preserve the zero padding, because if I do this then it fails: as.fetch_add(t); VERIFY(as.load() == s); __builtin_clear_padding(&s); VERIFY( std::memcmp(&s, &as, sizeof(s)) == 0 ); So the value stored by fetch_add (which uses compare_exchange_weak in a loop) really doesn't have zero padding bits. I'm not sure what's going on here yet, maybe __atomic_compare_exchange recognizes that the pointers are long double* and so only copies the non-padding bits into the value? I think I'll push the fix to the __atomic_float constructor, but with a simplified test case that doesn't include the compare_exchange_{weak,strong} calls, until I figure out how to fix it. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-02-16 12:38 ` Jonathan Wakely @ 2024-02-16 13:51 ` Jonathan Wakely 2024-02-16 14:10 ` Jakub Jelinek 2024-02-19 7:55 ` [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange Jakub Jelinek 0 siblings, 2 replies; 28+ messages in thread From: Jonathan Wakely @ 2024-02-16 13:51 UTC (permalink / raw) To: xndcn; +Cc: Jakub Jelinek, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ On Fri, 16 Feb 2024 at 12:38, Jonathan Wakely <jwakely@redhat.com> wrote: > > On Fri, 2 Feb 2024 at 16:52, xndcn <xndchn@gmail.com> wrote: > > > > Thank you for your careful review! > > > > > But we don't need a new one if it's going to be used in exactly one test and if the new option does the same thing for all targets that run the test. > > Got it, thanks. Now add option "-latomic" directly, but it still rely > > on the trick "[atomic_link_flags [get_multilibs]]" > > > > > No, because the patch is supposed to prevent the infinite loop, and so there's no need to stop it looping after 10s. It won't loop at all. > > Thanks, deleted. > > > > > We only need to clear padding for long double, not float and double, right? > > Yes, actually there is a check "if constexpr > > (__atomic_impl::__maybe_has_padding<_Fp>())". > > But "__atomic_impl::__clear_padding(_M_fp); " is indeed simply, so fixed here. > > > > > Why can't we run this on all targets? > > Got it, now target option deleted. > > > > > There's no reason to use __builtin_memset here, just include <cstring> and use std::memcpy. > > Thanks, fixed. > > > > > It definitely does have padding, just say "long double has padding bits on x86" > > Thanks, fixed. > > > > So here comes the latest patch: > > > Thanks. I've applied the patch to my tree, but the new test fails > pretty reliably. > > The infinite loop in std::atomic<long double>::fetch_add is fixed by > clearing padding in the constructor, but the test fails on the > compare_exchange_weak or compare_exchange_strong lines here: > > > > + as.fetch_add(t); > > + long double s = f + t; > > + t = as.load(); > > + VERIFY(s == t); // padding ignored on float comparing > > + fill_padding(s); > > + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg > > + fill_padding(f); > > + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg > > > > > I think the problem is here in __atomic_impl::__compare_exchange: > > if (__atomic_compare_exchange(__pval, __pexp, __pi, > __is_weak, int(__s), int(__f))) > return true; > > Even though padding in *__pexp and *__pi has been cleared, the value > of *__pval after a successful __atomic_compare_exchange has non-zero > padding. That means that the next compare_exchange will fail, because > we assume that the stored value always has zeroed padding bits. > > Here's a gdb session showing that __atomic_compare_exchange stores a > value with non-zero padding: > > Breakpoint 2, test01 () at compare_exchange_padding.cc:43 > 43 long double s2 = s; > (gdb) n > 44 fill_padding(s2); > (gdb) > 45 while (!as.compare_exchange_weak(s2, f)) // padding cleared > on compexchg > (gdb) p/x as._M_fp > $11 = 0x40008000000000000000 > (gdb) step > std::__atomic_float<long double>::compare_exchange_weak > (this=0x7fffffffd8c0, __expected=@0x7fffffffd8a0: 2, __desired=0.5, > __order=std::memory_order::seq_cst) at > /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:1387 > 1387 return compare_exchange_weak(__expected, __desired, __order, > (gdb) step > std::__atomic_float<long double>::compare_exchange_weak > (this=0x7fffffffd8c0, __expected=@0x7fffffffd8a0: 2, __desired=0.5, > __success=std::memory_order::seq_cst, > __failure=std::memory_order::seq_cst) at > /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:1347 > 1347 return __atomic_impl::compare_exchange_weak(&_M_fp, > (gdb) step > std::__atomic_impl::compare_exchange_weak<false, long double> > (__check_padding=false, __failure=std::memory_order::seq_cst, > __success=std::memory_order::seq_cst, __desired=0.5, > __expected=@0x7fffffffd8a0: 2, __ptr=0x7fffffffd8c0) > at /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:1123 > 1123 return __atomic_impl::__compare_exchange<_AtomicRef>( > (gdb) > std::__atomic_impl::__compare_exchange<false, long double> > (__f=std::memory_order::seq_cst, __s=std::memory_order::seq_cst, > __is_weak=true, > __i=<optimized out>, __e=@0x7fffffffd8a0: 2, > __val=@0x7fffffffd8c0: 2) at > /home/jwakely/gcc/14/include/c++/14.0.1/bits/atomic_base.h:994 > 994 __glibcxx_assert(__is_valid_cmpexch_failure_order(__f)); > (gdb) n > 997 _Tp* const __pval = std::__addressof(__val); > (gdb) > 1008 _Vp* const __pi = __atomic_impl::__clear_padding(__i); > (gdb) > 1010 _Vp __exp = __e; > (gdb) > 1012 _Vp* const __pexp = __atomic_impl::__clear_padding(__exp); > (gdb) > 1016 if (__atomic_compare_exchange(__pval, __pexp, __pi, > (gdb) p/x *__pval > $12 = 0x40008000000000000000 > (gdb) p/x *__pexp > $13 = 0x40008000000000000000 > (gdb) p/x *__pi > $14 = 0x3ffe8000000000000000 > (gdb) n > 1018 return true; > (gdb) p/x *__pval > $15 = 0x7ffff7bf3ffe8000000000000000 > (gdb) > > We stored *__pi which has zero padding, but the result in *__pval has > non-zero padding. This doesn't seem to be gdb being misleading by > loading *__pval into a FP register which doesn't preserve the zero > padding, because if I do this then it fails: > > as.fetch_add(t); > VERIFY(as.load() == s); > __builtin_clear_padding(&s); > VERIFY( std::memcmp(&s, &as, sizeof(s)) == 0 ); > > So the value stored by fetch_add (which uses compare_exchange_weak in > a loop) really doesn't have zero padding bits. > > I'm not sure what's going on here yet, maybe __atomic_compare_exchange > recognizes that the pointers are long double* and so only copies the > non-padding bits into the value? Ah, although __atomic_compare_exchange only takes pointers, the compiler replaces that with a call to __atomic_compare_exchange_n which takes the newval by value, which presumably uses an 80-bit FP register and so the padding bits become indeterminate again. Maybe we can make std::atomic<long double> actually store a 16-byte struct containing an opaque char buffer, which we store a long double into. That should stop FP registers being used for it. We never need an actual long double, because we only access the value using the __atomic_xxx built-ins. Maybe we need that for every std::atomic<T> where T has padding bits, because even for struct S { int i; char c; } passing S by value could be scalarized and only copy the value representation, not preserve the padding that we've carefully cleared. > > I think I'll push the fix to the __atomic_float constructor, but with > a simplified test case that doesn't include the > compare_exchange_{weak,strong} calls, until I figure out how to fix > it. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-02-16 13:51 ` Jonathan Wakely @ 2024-02-16 14:10 ` Jakub Jelinek 2024-02-16 15:15 ` Jonathan Wakely 2024-02-19 7:55 ` [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange Jakub Jelinek 1 sibling, 1 reply; 28+ messages in thread From: Jakub Jelinek @ 2024-02-16 14:10 UTC (permalink / raw) To: Jonathan Wakely; +Cc: xndcn, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: > Ah, although __atomic_compare_exchange only takes pointers, the > compiler replaces that with a call to __atomic_compare_exchange_n > which takes the newval by value, which presumably uses an 80-bit FP > register and so the padding bits become indeterminate again. __atomic_compare_exchange_n only works with integers, so I guess it is doing VIEW_CONVERT_EXPR (aka union-style type punning) on the argument. Do you have preprocessed source for the testcase? Jakub ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-02-16 14:10 ` Jakub Jelinek @ 2024-02-16 15:15 ` Jonathan Wakely 2024-03-14 15:13 ` Jonathan Wakely 0 siblings, 1 reply; 28+ messages in thread From: Jonathan Wakely @ 2024-02-16 15:15 UTC (permalink / raw) To: Jakub Jelinek; +Cc: xndcn, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ On Fri, 16 Feb 2024 at 14:10, Jakub Jelinek wrote: > > On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: > > Ah, although __atomic_compare_exchange only takes pointers, the > > compiler replaces that with a call to __atomic_compare_exchange_n > > which takes the newval by value, which presumably uses an 80-bit FP > > register and so the padding bits become indeterminate again. > > __atomic_compare_exchange_n only works with integers, so I guess > it is doing VIEW_CONVERT_EXPR (aka union-style type punning) on the > argument. > > Do you have preprocessed source for the testcase? Sent offlist. ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-02-16 15:15 ` Jonathan Wakely @ 2024-03-14 15:13 ` Jonathan Wakely 2024-03-25 15:42 ` [PING][PATCH] " xndcn 0 siblings, 1 reply; 28+ messages in thread From: Jonathan Wakely @ 2024-03-14 15:13 UTC (permalink / raw) To: Jakub Jelinek; +Cc: xndcn, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ [-- Attachment #1: Type: text/plain, Size: 787 bytes --] On Fri, 16 Feb 2024 at 15:15, Jonathan Wakely wrote: > > On Fri, 16 Feb 2024 at 14:10, Jakub Jelinek wrote: > > > > On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: > > > Ah, although __atomic_compare_exchange only takes pointers, the > > > compiler replaces that with a call to __atomic_compare_exchange_n > > > which takes the newval by value, which presumably uses an 80-bit FP > > > register and so the padding bits become indeterminate again. > > > > __atomic_compare_exchange_n only works with integers, so I guess > > it is doing VIEW_CONVERT_EXPR (aka union-style type punning) on the > > argument. > > > > Do you have preprocessed source for the testcase? > > Sent offlist. Jakub fixed the compiler, so I've pushed the attached patch now. Tested x86_64-linux. [-- Attachment #2: patch.txt --] [-- Type: text/plain, Size: 2795 bytes --] commit 0adc8c5f146b108f99c4df09e43276e3a2419262 Author: xndcn <xndchn@gmail.com> Date: Fri Feb 16 11:00:13 2024 libstdc++: Add missing clear_padding in __atomic_float constructor For 80-bit long double we need to clear the padding bits on construction. libstdc++-v3/ChangeLog: * include/bits/atomic_base.h (__atomic_float::__atomic_float(Fp)): Clear padding. * testsuite/29_atomics/atomic_float/compare_exchange_padding.cc: New test. Signed-off-by: xndcn <xndchn@gmail.com> Reviewed-by: Jonathan Wakely <jwakely@redhat.com> diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index b857b441169..dd360302f80 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1283,7 +1283,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr __atomic_float(_Fp __t) : _M_fp(__t) - { } + { __atomic_impl::__clear_padding(_M_fp); } __atomic_float(const __atomic_float&) = delete; __atomic_float& operator=(const __atomic_float&) = delete; diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc new file mode 100644 index 00000000000..49626ac6651 --- /dev/null +++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/compare_exchange_padding.cc @@ -0,0 +1,53 @@ +// { dg-do run { target c++20 } } +// { dg-options "-O0" } +// { dg-additional-options "[atomic_link_flags [get_multilibs]] -latomic" } + +#include <atomic> +#include <cstring> +#include <limits> +#include <testsuite_hooks.h> + +template<typename T> +void __attribute__((noinline,noipa)) +fill_padding(T& f) +{ + T mask; + std::memset(&mask, 0xff, sizeof(T)); + __builtin_clear_padding(&mask); + unsigned char* ptr_f = (unsigned char*)&f; + unsigned char* ptr_mask = (unsigned char*)&mask; + for (unsigned i = 0; i < sizeof(T); i++) + { + if (ptr_mask[i] == 0x00) + { + ptr_f[i] = 0xff; + } + } +} + +void +test01() +{ + // test for long double with padding (float80) + if constexpr (std::numeric_limits<long double>::digits == 64) + { + long double f = 0.5f; // long double has padding bits on x86 + fill_padding(f); + std::atomic<long double> as{ f }; // padding cleared on constructor + long double t = 1.5; + + as.fetch_add(t); + long double s = f + t; + t = as.load(); + VERIFY(s == t); // padding ignored on comparison + fill_padding(s); + VERIFY(as.compare_exchange_weak(s, f)); // padding cleared on cmpexchg + fill_padding(f); + VERIFY(as.compare_exchange_strong(f, t)); // padding cleared on cmpexchg + } +} + +int main() +{ + test01(); +} ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PING][PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor 2024-03-14 15:13 ` Jonathan Wakely @ 2024-03-25 15:42 ` xndcn 0 siblings, 0 replies; 28+ messages in thread From: xndcn @ 2024-03-25 15:42 UTC (permalink / raw) To: Jonathan Wakely; +Cc: Jakub Jelinek, Xi Ruoyao, H.J. Lu, GCC Patches, libstdc++ [-- Attachment #1: Type: text/plain, Size: 966 bytes --] Wow, thank you all, you guys! 在 2024年3月14日星期四,Jonathan Wakely <jwakely@redhat.com> 写道: > On Fri, 16 Feb 2024 at 15:15, Jonathan Wakely wrote: > > > > On Fri, 16 Feb 2024 at 14:10, Jakub Jelinek wrote: > > > > > > On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: > > > > Ah, although __atomic_compare_exchange only takes pointers, the > > > > compiler replaces that with a call to __atomic_compare_exchange_n > > > > which takes the newval by value, which presumably uses an 80-bit FP > > > > register and so the padding bits become indeterminate again. > > > > > > __atomic_compare_exchange_n only works with integers, so I guess > > > it is doing VIEW_CONVERT_EXPR (aka union-style type punning) on the > > > argument. > > > > > > Do you have preprocessed source for the testcase? > > > > Sent offlist. > > Jakub fixed the compiler, so I've pushed the attached patch now. > > Tested x86_64-linux. > ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-16 13:51 ` Jonathan Wakely 2024-02-16 14:10 ` Jakub Jelinek @ 2024-02-19 7:55 ` Jakub Jelinek 2024-02-20 0:12 ` Jason Merrill 1 sibling, 1 reply; 28+ messages in thread From: Jakub Jelinek @ 2024-02-19 7:55 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches, Jonathan Wakely On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: > Ah, although __atomic_compare_exchange only takes pointers, the > compiler replaces that with a call to __atomic_compare_exchange_n > which takes the newval by value, which presumably uses an 80-bit FP > register and so the padding bits become indeterminate again. The problem is that __atomic_{,compare_}exchange lowering if it has a supported atomic 1/2/4/8/16 size emits code like: _3 = *p2; _4 = VIEW_CONVERT_EXPR<I_type> (_3); so if long double or some small struct etc. has some carefully filled padding bits, those bits can be lost on the assignment. The library call for __atomic_{,compare_}exchange would actually work because it woiuld load the value from memory using integral type or memcpy. E.g. on void foo (long double *a, long double *b, long double *c) { __atomic_compare_exchange (a, b, c, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED); } we end up with -O0 with: fldt (%rax) fstpt -48(%rbp) movq -48(%rbp), %rax movq -40(%rbp), %rdx i.e. load *c from memory into 387 register, store it back to uninitialized stack slot (the padding bits are now random in there) and then load a __uint128_t (pair of GPR regs). The problem is that we first load it using whatever type the pointer points to and then VIEW_CONVERT_EXPR that value: p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); The following patch fixes that by creating a MEM_REF instead, with the I_type type, but with the original pointer type on the second argument for aliasing purposes, so we actually preserve the padding bits that way. I've done that for types which may have padding and also for non-integral/pointer types, because I fear even on floating point types like double or float which don't have padding bits the copying through floating point could misbehave in presence of sNaNs or unsupported bit combinations. With this patch instead of the above assembly we emit movq 8(%rax), %rdx movq (%rax), %rax I had to add support for MEM_REF in pt.cc, though with the assumption that it has been already originally created with non-dependent types/operands (which is the case here for the __atomic*exchange lowering). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2024-02-19 Jakub Jelinek <jakub@redhat.com> gcc/c-family/ * c-common.cc (resolve_overloaded_atomic_exchange): For non-integral/pointer types or types which may need padding instead of setting p1 to VIEW_CONVERT_EXPR<I_type> (*p1), set it to MEM_REF with p1 and (typeof (p1)) 0 operands and I_type type. (resolve_overloaded_atomic_compare_exchange): Similarly for p2. gcc/cp/ * pt.cc (tsubst_expr): Handle MEM_REF. gcc/testsuite/ * g++.dg/ext/atomic-5.C: New test. --- gcc/c-family/c-common.cc.jj 2024-02-16 17:33:43.995739790 +0100 +++ gcc/c-family/c-common.cc 2024-02-17 11:11:34.029474214 +0100 @@ -7794,8 +7794,23 @@ resolve_overloaded_atomic_exchange (loca p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); (*params)[0] = p0; /* Convert new value to required type, and dereference it. */ - p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); + if ((!INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (p1))) + && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (p1)))) + || clear_padding_type_may_have_padding_p (TREE_TYPE (TREE_TYPE (p1)))) + { + /* If *p1 type can have padding or may involve floating point which + could e.g. be promoted to wider precision and demoted afterwards, + state of padding bits might not be preserved. */ + build_indirect_ref (loc, p1, RO_UNARY_STAR); + p1 = build2_loc (loc, MEM_REF, I_type, + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1), + build_zero_cst (TREE_TYPE (p1))); + } + else + { + p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); + p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); + } (*params)[1] = p1; /* Move memory model to the 3rd position, and end param list. */ @@ -7874,8 +7889,23 @@ resolve_overloaded_atomic_compare_exchan (*params)[1] = p1; /* Convert desired value to required type, and dereference it. */ - p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); - p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); + if ((!INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (p2))) + && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (p2)))) + || clear_padding_type_may_have_padding_p (TREE_TYPE (TREE_TYPE (p2)))) + { + /* If *p2 type can have padding or may involve floating point which + could e.g. be promoted to wider precision and demoted afterwards, + state of padding bits might not be preserved. */ + build_indirect_ref (loc, p2, RO_UNARY_STAR); + p2 = build2_loc (loc, MEM_REF, I_type, + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2), + build_zero_cst (TREE_TYPE (p2))); + } + else + { + p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); + p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); + } (*params)[2] = p2; /* The rest of the parameters are fine. NULL means no special return value --- gcc/cp/pt.cc.jj 2024-02-14 14:26:19.695811596 +0100 +++ gcc/cp/pt.cc 2024-02-17 11:05:47.988237152 +0100 @@ -20088,6 +20088,14 @@ tsubst_expr (tree t, tree args, tsubst_f RETURN (r); } + case MEM_REF: + { + tree op0 = RECUR (TREE_OPERAND (t, 0)); + tree op1 = RECUR (TREE_OPERAND (t, 0)); + tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); + RETURN (build2_loc (EXPR_LOCATION (t), MEM_REF, new_type, op0, op1)); + } + case NOP_EXPR: { tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); --- gcc/testsuite/g++.dg/ext/atomic-5.C.jj 2024-02-17 11:13:37.824770288 +0100 +++ gcc/testsuite/g++.dg/ext/atomic-5.C 2024-02-17 11:14:54.077720732 +0100 @@ -0,0 +1,42 @@ +// { dg-do compile { target c++14 } } + +template <int N> +void +foo (long double *ptr, long double *val, long double *ret) +{ + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); +} + +template <int N> +bool +bar (long double *ptr, long double *exp, long double *des) +{ + return __atomic_compare_exchange (ptr, exp, des, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +bool +baz (long double *p, long double *q, long double *r) +{ + foo<0> (p, q, r); + foo<1> (p + 1, q + 1, r + 1); + return bar<0> (p + 2, q + 2, r + 2) || bar<1> (p + 3, q + 3, r + 3); +} + +constexpr int +qux (long double *ptr, long double *val, long double *ret) +{ + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); + return 0; +} + +constexpr bool +corge (long double *ptr, long double *exp, long double *des) +{ + return __atomic_compare_exchange (ptr, exp, des, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +long double a[6]; +const int b = qux (a, a + 1, a + 2); +const bool c = corge (a + 3, a + 4, a + 5); Jakub ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-19 7:55 ` [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange Jakub Jelinek @ 2024-02-20 0:12 ` Jason Merrill 2024-02-20 0:51 ` Jakub Jelinek 0 siblings, 1 reply; 28+ messages in thread From: Jason Merrill @ 2024-02-20 0:12 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, Jonathan Wakely, Richard Biener On 2/19/24 02:55, Jakub Jelinek wrote: > On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: >> Ah, although __atomic_compare_exchange only takes pointers, the >> compiler replaces that with a call to __atomic_compare_exchange_n >> which takes the newval by value, which presumably uses an 80-bit FP >> register and so the padding bits become indeterminate again. > > The problem is that __atomic_{,compare_}exchange lowering if it has > a supported atomic 1/2/4/8/16 size emits code like: > _3 = *p2; > _4 = VIEW_CONVERT_EXPR<I_type> (_3); Hmm, I find that surprising; I thought of VIEW_CONVERT_EXPR as working on lvalues, not rvalues, based on the documentation describing it as roughly *(type2 *)&X. Now I see that gimplify_expr does what you describe, and I wonder what the advantage of that is. That seems to go back to richi's r206420 for PR59471. r270579 for PR limited it to cases where the caller wants an rvalue; perhaps it should also be avoided when the operand is an INDIRECT_REF? > so if long double or some small struct etc. has some carefully filled > padding bits, those bits can be lost on the assignment. The library call > for __atomic_{,compare_}exchange would actually work because it woiuld > load the value from memory using integral type or memcpy. > E.g. on > void > foo (long double *a, long double *b, long double *c) > { > __atomic_compare_exchange (a, b, c, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED); > } > we end up with -O0 with: > fldt (%rax) > fstpt -48(%rbp) > movq -48(%rbp), %rax > movq -40(%rbp), %rdx > i.e. load *c from memory into 387 register, store it back to uninitialized > stack slot (the padding bits are now random in there) and then load a > __uint128_t (pair of GPR regs). The problem is that we first load it using > whatever type the pointer points to and then VIEW_CONVERT_EXPR that value: > p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); > p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); > The following patch fixes that by creating a MEM_REF instead, with the > I_type type, but with the original pointer type on the second argument for > aliasing purposes, so we actually preserve the padding bits that way. > I've done that for types which may have padding and also for > non-integral/pointer types, because I fear even on floating point types > like double or float which don't have padding bits the copying through > floating point could misbehave in presence of sNaNs or unsupported bit > combinations. > With this patch instead of the above assembly we emit > movq 8(%rax), %rdx > movq (%rax), %rax > I had to add support for MEM_REF in pt.cc, though with the assumption > that it has been already originally created with non-dependent > types/operands (which is the case here for the __atomic*exchange lowering). > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2024-02-19 Jakub Jelinek <jakub@redhat.com> > > gcc/c-family/ > * c-common.cc (resolve_overloaded_atomic_exchange): For > non-integral/pointer types or types which may need padding > instead of setting p1 to VIEW_CONVERT_EXPR<I_type> (*p1), set it to > MEM_REF with p1 and (typeof (p1)) 0 operands and I_type type. > (resolve_overloaded_atomic_compare_exchange): Similarly for p2. > gcc/cp/ > * pt.cc (tsubst_expr): Handle MEM_REF. > gcc/testsuite/ > * g++.dg/ext/atomic-5.C: New test. > > --- gcc/c-family/c-common.cc.jj 2024-02-16 17:33:43.995739790 +0100 > +++ gcc/c-family/c-common.cc 2024-02-17 11:11:34.029474214 +0100 > @@ -7794,8 +7794,23 @@ resolve_overloaded_atomic_exchange (loca > p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); > (*params)[0] = p0; > /* Convert new value to required type, and dereference it. */ > - p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); > - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); > + if ((!INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (p1))) > + && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (p1)))) > + || clear_padding_type_may_have_padding_p (TREE_TYPE (TREE_TYPE (p1)))) > + { > + /* If *p1 type can have padding or may involve floating point which > + could e.g. be promoted to wider precision and demoted afterwards, > + state of padding bits might not be preserved. */ > + build_indirect_ref (loc, p1, RO_UNARY_STAR); > + p1 = build2_loc (loc, MEM_REF, I_type, > + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1), > + build_zero_cst (TREE_TYPE (p1))); > + } > + else > + { > + p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); > + p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); > + } > (*params)[1] = p1; > > /* Move memory model to the 3rd position, and end param list. */ > @@ -7874,8 +7889,23 @@ resolve_overloaded_atomic_compare_exchan > (*params)[1] = p1; > > /* Convert desired value to required type, and dereference it. */ > - p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); > - p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); > + if ((!INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (p2))) > + && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (p2)))) > + || clear_padding_type_may_have_padding_p (TREE_TYPE (TREE_TYPE (p2)))) > + { > + /* If *p2 type can have padding or may involve floating point which > + could e.g. be promoted to wider precision and demoted afterwards, > + state of padding bits might not be preserved. */ > + build_indirect_ref (loc, p2, RO_UNARY_STAR); > + p2 = build2_loc (loc, MEM_REF, I_type, > + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2), > + build_zero_cst (TREE_TYPE (p2))); > + } > + else > + { > + p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); > + p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); > + } > (*params)[2] = p2; > > /* The rest of the parameters are fine. NULL means no special return value > --- gcc/cp/pt.cc.jj 2024-02-14 14:26:19.695811596 +0100 > +++ gcc/cp/pt.cc 2024-02-17 11:05:47.988237152 +0100 > @@ -20088,6 +20088,14 @@ tsubst_expr (tree t, tree args, tsubst_f > RETURN (r); > } > > + case MEM_REF: > + { > + tree op0 = RECUR (TREE_OPERAND (t, 0)); > + tree op1 = RECUR (TREE_OPERAND (t, 0)); > + tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); > + RETURN (build2_loc (EXPR_LOCATION (t), MEM_REF, new_type, op0, op1)); > + } > + > case NOP_EXPR: > { > tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); > --- gcc/testsuite/g++.dg/ext/atomic-5.C.jj 2024-02-17 11:13:37.824770288 +0100 > +++ gcc/testsuite/g++.dg/ext/atomic-5.C 2024-02-17 11:14:54.077720732 +0100 > @@ -0,0 +1,42 @@ > +// { dg-do compile { target c++14 } } > + > +template <int N> > +void > +foo (long double *ptr, long double *val, long double *ret) > +{ > + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); > +} > + > +template <int N> > +bool > +bar (long double *ptr, long double *exp, long double *des) > +{ > + return __atomic_compare_exchange (ptr, exp, des, false, > + __ATOMIC_RELAXED, __ATOMIC_RELAXED); > +} > + > +bool > +baz (long double *p, long double *q, long double *r) > +{ > + foo<0> (p, q, r); > + foo<1> (p + 1, q + 1, r + 1); > + return bar<0> (p + 2, q + 2, r + 2) || bar<1> (p + 3, q + 3, r + 3); > +} > + > +constexpr int > +qux (long double *ptr, long double *val, long double *ret) > +{ > + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); > + return 0; > +} > + > +constexpr bool > +corge (long double *ptr, long double *exp, long double *des) > +{ > + return __atomic_compare_exchange (ptr, exp, des, false, > + __ATOMIC_RELAXED, __ATOMIC_RELAXED); > +} > + > +long double a[6]; > +const int b = qux (a, a + 1, a + 2); > +const bool c = corge (a + 3, a + 4, a + 5); > > Jakub > ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-20 0:12 ` Jason Merrill @ 2024-02-20 0:51 ` Jakub Jelinek 2024-02-20 8:01 ` Richard Biener 0 siblings, 1 reply; 28+ messages in thread From: Jakub Jelinek @ 2024-02-20 0:51 UTC (permalink / raw) To: Jason Merrill, Richard Biener; +Cc: gcc-patches, Jonathan Wakely On Tue, Feb 20, 2024 at 12:12:11AM +0000, Jason Merrill wrote: > On 2/19/24 02:55, Jakub Jelinek wrote: > > On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: > > > Ah, although __atomic_compare_exchange only takes pointers, the > > > compiler replaces that with a call to __atomic_compare_exchange_n > > > which takes the newval by value, which presumably uses an 80-bit FP > > > register and so the padding bits become indeterminate again. > > > > The problem is that __atomic_{,compare_}exchange lowering if it has > > a supported atomic 1/2/4/8/16 size emits code like: > > _3 = *p2; > > _4 = VIEW_CONVERT_EXPR<I_type> (_3); > > Hmm, I find that surprising; I thought of VIEW_CONVERT_EXPR as working on > lvalues, not rvalues, based on the documentation describing it as roughly > *(type2 *)&X. It works on both, if it is on the lhs, it obviously needs to be on an lvalue and is something like VIEW_CONVERT_EXPR<I_type> (mem) = something; and if it is on rhs, it can be on an rvalue, just reinterpret bits of something as something else, so more like ((union { typeof (val) x; I_type y; }) (val)).y > Now I see that gimplify_expr does what you describe, and I wonder what the > advantage of that is. That seems to go back to richi's r206420 for PR59471. > r270579 for PR limited it to cases where the caller wants an rvalue; perhaps > it should also be avoided when the operand is an INDIRECT_REF? Strangely we don't even try to optimize it, even at -O2 that _3 = *p2_2(D); _4 = VIEW_CONVERT_EXPR<I_type> (_3); stays around until optimized. I believe VIEW_CONVERT_EXPR<I_type> is valid around a memory reference, so it could be either _4 = VIEW_CONVERT_EXPR<I_type> (*p2_2(D)); or the MEM_REF with aliasing info from original pointer and type from VCE. For optimizations, guess it is a matter of writing some match.pd rule, but we can't rely on it for the atomics. Doing it in the gimplifier is possible, but not sure how to do that easily, given that the VIEW_CONVERT_EXPR argument can be either lvalue or rvalue and we need to gimplify it first. The first part is exactly what forces it into a separate SSA_NAME for the load vs. VIEW_CONVERT_EXPR around it: case VIEW_CONVERT_EXPR: if ((fallback & fb_rvalue) && is_gimple_reg_type (TREE_TYPE (*expr_p)) && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))) { ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_val, fb_rvalue); recalculate_side_effects (*expr_p); break; } /* Fallthru. */ case ARRAY_REF: case ARRAY_RANGE_REF: case REALPART_EXPR: case IMAGPART_EXPR: case COMPONENT_REF: ret = gimplify_compound_lval (expr_p, pre_p, post_p, fallback ? fallback : fb_rvalue); break; but if we do the gimplify_compound_lval, we'd actually force it to be addressable (with possible errors if that isn't possible) etc. Having just a special-case of VIEW_CONVERT_EXPR of INDIRECT_REF and do gimplify_compound_lval in that case mikght be wrong I think if e.g. INDIRECT_REF operand is ADDR_EXPR, shouldn't we cancel *& in that case and still not force it into memory? The INDIRECT_REF: case is: { bool volatilep = TREE_THIS_VOLATILE (*expr_p); bool notrap = TREE_THIS_NOTRAP (*expr_p); tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0)); *expr_p = fold_indirect_ref_loc (input_location, *expr_p); if (*expr_p != save_expr) { ret = GS_OK; break; } ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, is_gimple_reg, fb_rvalue); if (ret == GS_ERROR) break; recalculate_side_effects (*expr_p); *expr_p = fold_build2_loc (input_location, MEM_REF, TREE_TYPE (*expr_p), TREE_OPERAND (*expr_p, 0), build_int_cst (saved_ptr_type, 0)); TREE_THIS_VOLATILE (*expr_p) = volatilep; TREE_THIS_NOTRAP (*expr_p) = notrap; ret = GS_OK; break; } so I think if we want to special case VIEW_CONVERT_EXPR on INDIRECT_REF, we should basically copy and adjust that to the start of the case VIEW_CONVERT_EXPR:. In particular, if fold_indirect_ref_loc did something and it isn't a different INDIRECT_REF or something addressable, do what it does now (i.e. possibly treat as lvalue), otherwise gimplify the INDIRECT_REF operand and build a MEM_REF, but with the type of the VIEW_CONVERT_EXPR but still saved_ptr_type of the INDIRECT_REF. Though, that all still feels like an optimization rather than guarantee which is what we need for the atomics. Jakub ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-20 0:51 ` Jakub Jelinek @ 2024-02-20 8:01 ` Richard Biener 2024-02-20 10:02 ` [PATCH] c-family, c++, v2: " Jakub Jelinek 0 siblings, 1 reply; 28+ messages in thread From: Richard Biener @ 2024-02-20 8:01 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Jason Merrill, gcc-patches, Jonathan Wakely On Tue, 20 Feb 2024, Jakub Jelinek wrote: > On Tue, Feb 20, 2024 at 12:12:11AM +0000, Jason Merrill wrote: > > On 2/19/24 02:55, Jakub Jelinek wrote: > > > On Fri, Feb 16, 2024 at 01:51:54PM +0000, Jonathan Wakely wrote: > > > > Ah, although __atomic_compare_exchange only takes pointers, the > > > > compiler replaces that with a call to __atomic_compare_exchange_n > > > > which takes the newval by value, which presumably uses an 80-bit FP > > > > register and so the padding bits become indeterminate again. > > > > > > The problem is that __atomic_{,compare_}exchange lowering if it has > > > a supported atomic 1/2/4/8/16 size emits code like: > > > _3 = *p2; > > > _4 = VIEW_CONVERT_EXPR<I_type> (_3); > > > > Hmm, I find that surprising; I thought of VIEW_CONVERT_EXPR as working on > > lvalues, not rvalues, based on the documentation describing it as roughly > > *(type2 *)&X. > > It works on both, if it is on the lhs, it obviously needs to be on an lvalue > and is something like > VIEW_CONVERT_EXPR<I_type> (mem) = something; > and if it is on rhs, it can be on an rvalue, just reinterpret bits of > something as something else, so more like > ((union { typeof (val) x; I_type y; }) (val)).y > > > Now I see that gimplify_expr does what you describe, and I wonder what the > > advantage of that is. That seems to go back to richi's r206420 for PR59471. > > r270579 for PR limited it to cases where the caller wants an rvalue; perhaps > > it should also be avoided when the operand is an INDIRECT_REF? > > Strangely we don't even try to optimize it, even at -O2 that > _3 = *p2_2(D); > _4 = VIEW_CONVERT_EXPR<I_type> (_3); > stays around until optimized. I believe VIEW_CONVERT_EXPR<I_type> is valid > around a memory reference, so it could be either > _4 = VIEW_CONVERT_EXPR<I_type> (*p2_2(D)); > or the MEM_REF with aliasing info from original pointer and type from VCE. > For optimizations, guess it is a matter of writing some match.pd rule, but > we can't rely on it for the atomics. I'm not sure those would be really equivalent (MEM_REF vs. V_C_E as well as combined vs. split). It really depends how RTL expansion handles this (as you can see padding can be fun here). So I'd be nervous for a match.pd rule here (also we can't match memory defs). As for your patch I'd go with a MEM_REF unconditionally, I don't think we want different behavior whether there's padding or not ... > Doing it in the gimplifier is possible, but not sure how to do that easily, > given that the VIEW_CONVERT_EXPR argument can be either lvalue or rvalue > and we need to gimplify it first. > The first part is exactly what forces it into a separate SSA_NAME for the > load vs. VIEW_CONVERT_EXPR around it: > > case VIEW_CONVERT_EXPR: > if ((fallback & fb_rvalue) > && is_gimple_reg_type (TREE_TYPE (*expr_p)) > && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))) > { > ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, > post_p, is_gimple_val, fb_rvalue); > recalculate_side_effects (*expr_p); > break; > } that was done to help optimizing some cases (IIRC with vectors / int punning). > /* Fallthru. */ > > case ARRAY_REF: > case ARRAY_RANGE_REF: > case REALPART_EXPR: > case IMAGPART_EXPR: > case COMPONENT_REF: > ret = gimplify_compound_lval (expr_p, pre_p, post_p, > fallback ? fallback : fb_rvalue); > break; > > but if we do the gimplify_compound_lval, we'd actually force it to be > addressable (with possible errors if that isn't possible) etc. > Having just a special-case of VIEW_CONVERT_EXPR of INDIRECT_REF and > do gimplify_compound_lval in that case mikght be wrong I think if > e.g. INDIRECT_REF operand is ADDR_EXPR, shouldn't we cancel *& in that case > and still not force it into memory? > > The INDIRECT_REF: case is: > { > bool volatilep = TREE_THIS_VOLATILE (*expr_p); > bool notrap = TREE_THIS_NOTRAP (*expr_p); > tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0)); > > *expr_p = fold_indirect_ref_loc (input_location, *expr_p); > if (*expr_p != save_expr) > { > ret = GS_OK; > break; > } > > ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, > is_gimple_reg, fb_rvalue); > if (ret == GS_ERROR) > break; > > recalculate_side_effects (*expr_p); > *expr_p = fold_build2_loc (input_location, MEM_REF, > TREE_TYPE (*expr_p), > TREE_OPERAND (*expr_p, 0), > build_int_cst (saved_ptr_type, 0)); > TREE_THIS_VOLATILE (*expr_p) = volatilep; > TREE_THIS_NOTRAP (*expr_p) = notrap; > ret = GS_OK; > break; > } > so I think if we want to special case VIEW_CONVERT_EXPR on INDIRECT_REF, > we should basically copy and adjust that to the start of the case > VIEW_CONVERT_EXPR:. In particular, if fold_indirect_ref_loc did something > and it isn't a different INDIRECT_REF or something addressable, do what it > does now (i.e. possibly treat as lvalue), otherwise gimplify the INDIRECT_REF > operand and build a MEM_REF, but with the type of the VIEW_CONVERT_EXPR but > still saved_ptr_type of the INDIRECT_REF. > > Though, that all still feels like an optimization rather than guarantee > which is what we need for the atomics. Yes, and I think the frontend does it wrong - if it wants to do a load of l_type it should do that, not re-interpret the result. I suppose the docs @defbuiltin{void __atomic_exchange (@var{type} *@var{ptr}, @var{type} *@var{val}, @var{type} *@var{ret}, int @var{memorder})} This is the generic version of an atomic exchange. It stores the contents of @code{*@var{val}} into @code{*@var{ptr}}. The original value of @code{*@var{ptr}} is copied into @code{*@var{ret}}. contain too little standards legalise to constrain 'type', it just appears to use lvalues of *ptr, *val and *ret here which for floats with padding possibly isn't well-defined and "contents" isn't a standard term (it doesn't say bit representation or something similar), it also says "stores" and "copied into". That said, if the FE determines in l_type a type suitable for copying then the access should use a MEM_REF, no further "conversion" required. Richard. ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH] c-family, c++, v2: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-20 8:01 ` Richard Biener @ 2024-02-20 10:02 ` Jakub Jelinek 2024-02-20 10:11 ` Richard Biener 2024-03-07 0:00 ` Jason Merrill 0 siblings, 2 replies; 28+ messages in thread From: Jakub Jelinek @ 2024-02-20 10:02 UTC (permalink / raw) To: Richard Biener, Jason Merrill; +Cc: gcc-patches, Jonathan Wakely On Tue, Feb 20, 2024 at 09:01:10AM +0100, Richard Biener wrote: > I'm not sure those would be really equivalent (MEM_REF vs. V_C_E > as well as combined vs. split). It really depends how RTL expansion > handles this (as you can see padding can be fun here). > > So I'd be nervous for a match.pd rule here (also we can't match > memory defs). Ok. Perhaps forwprop then; anyway, that would be an optimization. > As for your patch I'd go with a MEM_REF unconditionally, I don't > think we want different behavior whether there's padding or not ... I've made it conditional so that the MEM_REFs don't appear that often in the FE trees, but maybe that is fine. The unconditional patch would then be: 2024-02-20 Jakub Jelinek <jakub@redhat.com> gcc/c-family/ * c-common.cc (resolve_overloaded_atomic_exchange): Instead of setting p1 to VIEW_CONVERT_EXPR<I_type> (*p1), set it to MEM_REF with p1 and (typeof (p1)) 0 operands and I_type type. (resolve_overloaded_atomic_compare_exchange): Similarly for p2. gcc/cp/ * pt.cc (tsubst_expr): Handle MEM_REF. gcc/testsuite/ * g++.dg/ext/atomic-5.C: New test. --- gcc/c-family/c-common.cc.jj 2024-02-17 16:40:42.831571693 +0100 +++ gcc/c-family/c-common.cc 2024-02-20 10:58:56.599865656 +0100 @@ -7793,9 +7793,14 @@ resolve_overloaded_atomic_exchange (loca /* Convert object pointer to required type. */ p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); (*params)[0] = p0; - /* Convert new value to required type, and dereference it. */ - p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); + /* Convert new value to required type, and dereference it. + If *p1 type can have padding or may involve floating point which + could e.g. be promoted to wider precision and demoted afterwards, + state of padding bits might not be preserved. */ + build_indirect_ref (loc, p1, RO_UNARY_STAR); + p1 = build2_loc (loc, MEM_REF, I_type, + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1), + build_zero_cst (TREE_TYPE (p1))); (*params)[1] = p1; /* Move memory model to the 3rd position, and end param list. */ @@ -7873,9 +7878,14 @@ resolve_overloaded_atomic_compare_exchan p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1); (*params)[1] = p1; - /* Convert desired value to required type, and dereference it. */ - p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); - p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); + /* Convert desired value to required type, and dereference it. + If *p2 type can have padding or may involve floating point which + could e.g. be promoted to wider precision and demoted afterwards, + state of padding bits might not be preserved. */ + build_indirect_ref (loc, p2, RO_UNARY_STAR); + p2 = build2_loc (loc, MEM_REF, I_type, + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2), + build_zero_cst (TREE_TYPE (p2))); (*params)[2] = p2; /* The rest of the parameters are fine. NULL means no special return value --- gcc/cp/pt.cc.jj 2024-02-17 16:40:42.868571182 +0100 +++ gcc/cp/pt.cc 2024-02-20 10:57:36.646973603 +0100 @@ -20088,6 +20088,14 @@ tsubst_expr (tree t, tree args, tsubst_f RETURN (r); } + case MEM_REF: + { + tree op0 = RECUR (TREE_OPERAND (t, 0)); + tree op1 = RECUR (TREE_OPERAND (t, 0)); + tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); + RETURN (build2_loc (EXPR_LOCATION (t), MEM_REF, new_type, op0, op1)); + } + case NOP_EXPR: { tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); --- gcc/testsuite/g++.dg/ext/atomic-5.C.jj 2024-02-20 10:57:36.647973589 +0100 +++ gcc/testsuite/g++.dg/ext/atomic-5.C 2024-02-20 10:57:36.647973589 +0100 @@ -0,0 +1,42 @@ +// { dg-do compile { target c++14 } } + +template <int N> +void +foo (long double *ptr, long double *val, long double *ret) +{ + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); +} + +template <int N> +bool +bar (long double *ptr, long double *exp, long double *des) +{ + return __atomic_compare_exchange (ptr, exp, des, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +bool +baz (long double *p, long double *q, long double *r) +{ + foo<0> (p, q, r); + foo<1> (p + 1, q + 1, r + 1); + return bar<0> (p + 2, q + 2, r + 2) || bar<1> (p + 3, q + 3, r + 3); +} + +constexpr int +qux (long double *ptr, long double *val, long double *ret) +{ + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); + return 0; +} + +constexpr bool +corge (long double *ptr, long double *exp, long double *des) +{ + return __atomic_compare_exchange (ptr, exp, des, false, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); +} + +long double a[6]; +const int b = qux (a, a + 1, a + 2); +const bool c = corge (a + 3, a + 4, a + 5); Jakub ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] c-family, c++, v2: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-20 10:02 ` [PATCH] c-family, c++, v2: " Jakub Jelinek @ 2024-02-20 10:11 ` Richard Biener 2024-02-20 10:27 ` Jakub Jelinek 2024-03-07 0:00 ` Jason Merrill 1 sibling, 1 reply; 28+ messages in thread From: Richard Biener @ 2024-02-20 10:11 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Jason Merrill, gcc-patches, Jonathan Wakely On Tue, 20 Feb 2024, Jakub Jelinek wrote: > On Tue, Feb 20, 2024 at 09:01:10AM +0100, Richard Biener wrote: > > I'm not sure those would be really equivalent (MEM_REF vs. V_C_E > > as well as combined vs. split). It really depends how RTL expansion > > handles this (as you can see padding can be fun here). > > > > So I'd be nervous for a match.pd rule here (also we can't match > > memory defs). > > Ok. Perhaps forwprop then; anyway, that would be an optimization. > > > As for your patch I'd go with a MEM_REF unconditionally, I don't > > think we want different behavior whether there's padding or not ... > > I've made it conditional so that the MEM_REFs don't appear that often in the > FE trees, but maybe that is fine. > > The unconditional patch would then be: > > 2024-02-20 Jakub Jelinek <jakub@redhat.com> > > gcc/c-family/ > * c-common.cc (resolve_overloaded_atomic_exchange): Instead of setting > p1 to VIEW_CONVERT_EXPR<I_type> (*p1), set it to MEM_REF with p1 and > (typeof (p1)) 0 operands and I_type type. > (resolve_overloaded_atomic_compare_exchange): Similarly for p2. > gcc/cp/ > * pt.cc (tsubst_expr): Handle MEM_REF. > gcc/testsuite/ > * g++.dg/ext/atomic-5.C: New test. > > --- gcc/c-family/c-common.cc.jj 2024-02-17 16:40:42.831571693 +0100 > +++ gcc/c-family/c-common.cc 2024-02-20 10:58:56.599865656 +0100 > @@ -7793,9 +7793,14 @@ resolve_overloaded_atomic_exchange (loca > /* Convert object pointer to required type. */ > p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); > (*params)[0] = p0; > - /* Convert new value to required type, and dereference it. */ > - p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); > - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); > + /* Convert new value to required type, and dereference it. > + If *p1 type can have padding or may involve floating point which > + could e.g. be promoted to wider precision and demoted afterwards, > + state of padding bits might not be preserved. */ > + build_indirect_ref (loc, p1, RO_UNARY_STAR); > + p1 = build2_loc (loc, MEM_REF, I_type, > + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1), Why the V_C_E to I_type_ptr? The type of p1 doesn't really matter (unless it could be a non-pointer). Also note that I_type needs to be properly address-space qualified in case the access should be to an address-space. Formerly with the INDIRECT_REF that would likely be automagic. > + build_zero_cst (TREE_TYPE (p1))); > (*params)[1] = p1; > > /* Move memory model to the 3rd position, and end param list. */ > @@ -7873,9 +7878,14 @@ resolve_overloaded_atomic_compare_exchan > p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1); > (*params)[1] = p1; > > - /* Convert desired value to required type, and dereference it. */ > - p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); > - p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); > + /* Convert desired value to required type, and dereference it. > + If *p2 type can have padding or may involve floating point which > + could e.g. be promoted to wider precision and demoted afterwards, > + state of padding bits might not be preserved. */ > + build_indirect_ref (loc, p2, RO_UNARY_STAR); > + p2 = build2_loc (loc, MEM_REF, I_type, > + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2), > + build_zero_cst (TREE_TYPE (p2))); > (*params)[2] = p2; > > /* The rest of the parameters are fine. NULL means no special return value > --- gcc/cp/pt.cc.jj 2024-02-17 16:40:42.868571182 +0100 > +++ gcc/cp/pt.cc 2024-02-20 10:57:36.646973603 +0100 > @@ -20088,6 +20088,14 @@ tsubst_expr (tree t, tree args, tsubst_f > RETURN (r); > } > > + case MEM_REF: > + { > + tree op0 = RECUR (TREE_OPERAND (t, 0)); > + tree op1 = RECUR (TREE_OPERAND (t, 0)); > + tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); > + RETURN (build2_loc (EXPR_LOCATION (t), MEM_REF, new_type, op0, op1)); > + } > + > case NOP_EXPR: > { > tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); > --- gcc/testsuite/g++.dg/ext/atomic-5.C.jj 2024-02-20 10:57:36.647973589 +0100 > +++ gcc/testsuite/g++.dg/ext/atomic-5.C 2024-02-20 10:57:36.647973589 +0100 > @@ -0,0 +1,42 @@ > +// { dg-do compile { target c++14 } } > + > +template <int N> > +void > +foo (long double *ptr, long double *val, long double *ret) > +{ > + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); > +} > + > +template <int N> > +bool > +bar (long double *ptr, long double *exp, long double *des) > +{ > + return __atomic_compare_exchange (ptr, exp, des, false, > + __ATOMIC_RELAXED, __ATOMIC_RELAXED); > +} > + > +bool > +baz (long double *p, long double *q, long double *r) > +{ > + foo<0> (p, q, r); > + foo<1> (p + 1, q + 1, r + 1); > + return bar<0> (p + 2, q + 2, r + 2) || bar<1> (p + 3, q + 3, r + 3); > +} > + > +constexpr int > +qux (long double *ptr, long double *val, long double *ret) > +{ > + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); > + return 0; > +} > + > +constexpr bool > +corge (long double *ptr, long double *exp, long double *des) > +{ > + return __atomic_compare_exchange (ptr, exp, des, false, > + __ATOMIC_RELAXED, __ATOMIC_RELAXED); > +} > + > +long double a[6]; > +const int b = qux (a, a + 1, a + 2); > +const bool c = corge (a + 3, a + 4, a + 5); > > > Jakub > > -- Richard Biener <rguenther@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg) ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] c-family, c++, v2: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-20 10:11 ` Richard Biener @ 2024-02-20 10:27 ` Jakub Jelinek 0 siblings, 0 replies; 28+ messages in thread From: Jakub Jelinek @ 2024-02-20 10:27 UTC (permalink / raw) To: Richard Biener; +Cc: Jason Merrill, gcc-patches, Jonathan Wakely On Tue, Feb 20, 2024 at 11:11:22AM +0100, Richard Biener wrote: > > --- gcc/c-family/c-common.cc.jj 2024-02-17 16:40:42.831571693 +0100 > > +++ gcc/c-family/c-common.cc 2024-02-20 10:58:56.599865656 +0100 > > @@ -7793,9 +7793,14 @@ resolve_overloaded_atomic_exchange (loca > > /* Convert object pointer to required type. */ > > p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); > > (*params)[0] = p0; > > - /* Convert new value to required type, and dereference it. */ > > - p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); > > - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); > > + /* Convert new value to required type, and dereference it. > > + If *p1 type can have padding or may involve floating point which > > + could e.g. be promoted to wider precision and demoted afterwards, > > + state of padding bits might not be preserved. */ > > + build_indirect_ref (loc, p1, RO_UNARY_STAR); > > + p1 = build2_loc (loc, MEM_REF, I_type, > > + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1), > > Why the V_C_E to I_type_ptr? The type of p1 doesn't > really matter (unless it could be a non-pointer). Just to help the FE when trying to constexpr evaluate it, because for constexpr evaluation it evaluates MEM_REF the same as INDIRECT_REF (and punts on non-0 second argument). The actual call is non-constexpr, just wanted to avoid ICEs or something similar, constexpr evaluation can try to process the arguments (and succeed or fail, doesn't matter, but not ICE) and then the call will not be constant expression and so everything won't be. > Also note that I_type needs to be properly address-space qualified > in case the access should be to an address-space. Formerly with > the INDIRECT_REF that would likely be automagic. I don't think using __atomic_*exchange on non-default as is valid, if one doesn't have the exact __atomic_*exchange_N, it is handled as a library call which is passed pointers and that definitely will not deal with non-default address spaces. Furthermore, the type should be the same in all arguments, and the first argument is just converted to I_type_ptr and dealt with later, so I don't think it ever worked even for the supported sizes. int foo (__seg_gs int *a, __seg_gs int *b, __seg_gs int *c) { return __atomic_compare_exchange (a, b, c, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED); } results in movl (%rsi), %eax movl %gs:(%rdx), %edx lock cmpxchgl %edx, (%rdi) sete %dl je .L2 movl %eax, (%rsi) .L2: i.e. pretty much random what is loaded from a different AS and what is not. Jakub ^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH] c-family, c++, v2: Fix up handling of types which may have padding in __atomic_{compare_}exchange 2024-02-20 10:02 ` [PATCH] c-family, c++, v2: " Jakub Jelinek 2024-02-20 10:11 ` Richard Biener @ 2024-03-07 0:00 ` Jason Merrill 1 sibling, 0 replies; 28+ messages in thread From: Jason Merrill @ 2024-03-07 0:00 UTC (permalink / raw) To: Jakub Jelinek, Richard Biener; +Cc: gcc-patches, Jonathan Wakely On 2/20/24 05:02, Jakub Jelinek wrote: > On Tue, Feb 20, 2024 at 09:01:10AM +0100, Richard Biener wrote: >> I'm not sure those would be really equivalent (MEM_REF vs. V_C_E >> as well as combined vs. split). It really depends how RTL expansion >> handles this (as you can see padding can be fun here). >> >> So I'd be nervous for a match.pd rule here (also we can't match >> memory defs). > > Ok. Perhaps forwprop then; anyway, that would be an optimization. > >> As for your patch I'd go with a MEM_REF unconditionally, I don't >> think we want different behavior whether there's padding or not ... > > I've made it conditional so that the MEM_REFs don't appear that often in the > FE trees, but maybe that is fine. > > The unconditional patch would then be: OK. > 2024-02-20 Jakub Jelinek <jakub@redhat.com> > > gcc/c-family/ > * c-common.cc (resolve_overloaded_atomic_exchange): Instead of setting > p1 to VIEW_CONVERT_EXPR<I_type> (*p1), set it to MEM_REF with p1 and > (typeof (p1)) 0 operands and I_type type. > (resolve_overloaded_atomic_compare_exchange): Similarly for p2. > gcc/cp/ > * pt.cc (tsubst_expr): Handle MEM_REF. > gcc/testsuite/ > * g++.dg/ext/atomic-5.C: New test. > > --- gcc/c-family/c-common.cc.jj 2024-02-17 16:40:42.831571693 +0100 > +++ gcc/c-family/c-common.cc 2024-02-20 10:58:56.599865656 +0100 > @@ -7793,9 +7793,14 @@ resolve_overloaded_atomic_exchange (loca > /* Convert object pointer to required type. */ > p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0); > (*params)[0] = p0; > - /* Convert new value to required type, and dereference it. */ > - p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR); > - p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1); > + /* Convert new value to required type, and dereference it. > + If *p1 type can have padding or may involve floating point which > + could e.g. be promoted to wider precision and demoted afterwards, > + state of padding bits might not be preserved. */ > + build_indirect_ref (loc, p1, RO_UNARY_STAR); > + p1 = build2_loc (loc, MEM_REF, I_type, > + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1), > + build_zero_cst (TREE_TYPE (p1))); > (*params)[1] = p1; > > /* Move memory model to the 3rd position, and end param list. */ > @@ -7873,9 +7878,14 @@ resolve_overloaded_atomic_compare_exchan > p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1); > (*params)[1] = p1; > > - /* Convert desired value to required type, and dereference it. */ > - p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR); > - p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2); > + /* Convert desired value to required type, and dereference it. > + If *p2 type can have padding or may involve floating point which > + could e.g. be promoted to wider precision and demoted afterwards, > + state of padding bits might not be preserved. */ > + build_indirect_ref (loc, p2, RO_UNARY_STAR); > + p2 = build2_loc (loc, MEM_REF, I_type, > + build1 (VIEW_CONVERT_EXPR, I_type_ptr, p2), > + build_zero_cst (TREE_TYPE (p2))); > (*params)[2] = p2; > > /* The rest of the parameters are fine. NULL means no special return value > --- gcc/cp/pt.cc.jj 2024-02-17 16:40:42.868571182 +0100 > +++ gcc/cp/pt.cc 2024-02-20 10:57:36.646973603 +0100 > @@ -20088,6 +20088,14 @@ tsubst_expr (tree t, tree args, tsubst_f > RETURN (r); > } > > + case MEM_REF: > + { > + tree op0 = RECUR (TREE_OPERAND (t, 0)); > + tree op1 = RECUR (TREE_OPERAND (t, 0)); > + tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); > + RETURN (build2_loc (EXPR_LOCATION (t), MEM_REF, new_type, op0, op1)); > + } > + > case NOP_EXPR: > { > tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); > --- gcc/testsuite/g++.dg/ext/atomic-5.C.jj 2024-02-20 10:57:36.647973589 +0100 > +++ gcc/testsuite/g++.dg/ext/atomic-5.C 2024-02-20 10:57:36.647973589 +0100 > @@ -0,0 +1,42 @@ > +// { dg-do compile { target c++14 } } > + > +template <int N> > +void > +foo (long double *ptr, long double *val, long double *ret) > +{ > + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); > +} > + > +template <int N> > +bool > +bar (long double *ptr, long double *exp, long double *des) > +{ > + return __atomic_compare_exchange (ptr, exp, des, false, > + __ATOMIC_RELAXED, __ATOMIC_RELAXED); > +} > + > +bool > +baz (long double *p, long double *q, long double *r) > +{ > + foo<0> (p, q, r); > + foo<1> (p + 1, q + 1, r + 1); > + return bar<0> (p + 2, q + 2, r + 2) || bar<1> (p + 3, q + 3, r + 3); > +} > + > +constexpr int > +qux (long double *ptr, long double *val, long double *ret) > +{ > + __atomic_exchange (ptr, val, ret, __ATOMIC_RELAXED); > + return 0; > +} > + > +constexpr bool > +corge (long double *ptr, long double *exp, long double *des) > +{ > + return __atomic_compare_exchange (ptr, exp, des, false, > + __ATOMIC_RELAXED, __ATOMIC_RELAXED); > +} > + > +long double a[6]; > +const int b = qux (a, a + 1, a + 2); > +const bool c = corge (a + 3, a + 4, a + 5); > > > Jakub > ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2024-03-25 15:42 UTC | newest] Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-01-08 1:01 [PATCH] libstdc++: atomic: Add missing clear_padding in __atomic_float constructor xndcn 2024-01-15 0:45 ` [PING][PATCH] " xndcn 2024-01-15 3:46 ` [PATCH] " H.J. Lu 2024-01-16 9:53 ` xndcn 2024-01-16 10:12 ` Xi Ruoyao 2024-01-16 16:16 ` xndcn 2024-01-24 15:53 ` xndcn 2024-01-30 16:08 ` [PING][PATCH] " xndcn 2024-01-30 16:31 ` [PATCH] " Jonathan Wakely 2024-01-30 16:34 ` Jonathan Wakely 2024-01-30 16:50 ` Jakub Jelinek 2024-01-31 17:19 ` xndcn 2024-02-01 13:54 ` Jonathan Wakely 2024-02-02 16:52 ` xndcn 2024-02-16 12:38 ` Jonathan Wakely 2024-02-16 13:51 ` Jonathan Wakely 2024-02-16 14:10 ` Jakub Jelinek 2024-02-16 15:15 ` Jonathan Wakely 2024-03-14 15:13 ` Jonathan Wakely 2024-03-25 15:42 ` [PING][PATCH] " xndcn 2024-02-19 7:55 ` [PATCH] c-family, c++: Fix up handling of types which may have padding in __atomic_{compare_}exchange Jakub Jelinek 2024-02-20 0:12 ` Jason Merrill 2024-02-20 0:51 ` Jakub Jelinek 2024-02-20 8:01 ` Richard Biener 2024-02-20 10:02 ` [PATCH] c-family, c++, v2: " Jakub Jelinek 2024-02-20 10:11 ` Richard Biener 2024-02-20 10:27 ` Jakub Jelinek 2024-03-07 0:00 ` Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).