Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
> This should be fixed now. I rewrote the test to check the padding byte > directly, instead of inspecting a copy of it which might not preserve > the padding bits. Great, thanks! -- Eric Botcazou
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
On Mon, 31 Oct 2022 at 15:34, Eric Botcazou wrote: > > > The test was only failing for me with -m32 (and not -m64), so I didn't > > notice until now. That probably means we should make the test fail more > > reliably if the padding isn't being cleared. > > The tests fail randomly for me on SPARC64/Linux: > > FAIL: 29_atomics/atomic/compare_exchange_padding.cc execution test > FAIL: 29_atomics/atomic_ref/compare_exchange_padding.cc execution test > > /home/ebotcazou/src/libstdc++-v3/testsuite/29_atomics/atomic_ref/ > compare_exchange_padding.cc:34: int main(): Assertion 'compare_struct(ts, es)' > failed. > FAIL: 29_atomics/atomic_ref/compare_exchange_padding.cc execution test > > std::atomic as{ s }; > auto ts = as.load(); > VERIFY( !compare_struct(s, ts) ); // padding cleared on construction > as.exchange(s); > auto es = as.load(); > VERIFY( compare_struct(ts, es) ); // padding cleared on exchange > > How is it supposed to pass exactly? AFAICS you have no control on the padding > bits of ts or es and, indeed, at -O2 the loads are scalarized: > > __buf$c_81 = MEM[(struct S *)&__buf].c; > __buf$s_59 = MEM[(struct S *)&__buf].s; > __buf ={v} {CLOBBER(eol)}; > ts.c = __buf$c_81; > ts.s = __buf$s_59; > [...] > __buf$c_100 = MEM[(struct S *)&__buf].c; > __buf$s_35 = MEM[(struct S *)&__buf].s; > __buf ={v} {CLOBBER(eol)}; > es.c = __buf$c_100; > es.s = __buf$s_35; > _66 = MEM [(char * {ref-all})]; > _101 = MEM [(char * {ref-all})]; > if (_66 != _101) > goto ; [0.04%] > else > goto ; [99.96%] > > so the result of the 4-byte comparison is random. This should be fixed now. I rewrote the test to check the padding byte directly, instead of inspecting a copy of it which might not preserve the padding bits.
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
> Do those loads still get scalarized at -O0? Presumably not at the GIMPLE level, but possibly at the RTL level. -- Eric Botcazou
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
On Mon, 31 Oct 2022 at 17:05, Jonathan Wakely wrote: > > On Mon, 31 Oct 2022 at 17:03, Eric Botcazou wrote: > > > > > I suppose we could use memcmp on the as variable itself, to inspect > > > the actual stored padding rather than the returned copy of it. > > > > Yes, that's probably the only safe stance when optimization is enabled. > > > Strictly speaking, it's not safe, because it's undefined to use memcmp > on an object of a non-trivial type. But it should work. Do those loads still get scalarized at -O0?
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
On Mon, 31 Oct 2022 at 17:03, Eric Botcazou wrote: > > > I suppose we could use memcmp on the as variable itself, to inspect > > the actual stored padding rather than the returned copy of it. > > Yes, that's probably the only safe stance when optimization is enabled. Strictly speaking, it's not safe, because it's undefined to use memcmp on an object of a non-trivial type. But it should work.
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
> I suppose we could use memcmp on the as variable itself, to inspect > the actual stored padding rather than the returned copy of it. Yes, that's probably the only safe stance when optimization is enabled. -- Eric Botcazou
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
On Mon, 31 Oct 2022 at 15:34, Eric Botcazou wrote: > > > The test was only failing for me with -m32 (and not -m64), so I didn't > > notice until now. That probably means we should make the test fail more > > reliably if the padding isn't being cleared. > > The tests fail randomly for me on SPARC64/Linux: > > FAIL: 29_atomics/atomic/compare_exchange_padding.cc execution test > FAIL: 29_atomics/atomic_ref/compare_exchange_padding.cc execution test > > /home/ebotcazou/src/libstdc++-v3/testsuite/29_atomics/atomic_ref/ > compare_exchange_padding.cc:34: int main(): Assertion 'compare_struct(ts, es)' > failed. > FAIL: 29_atomics/atomic_ref/compare_exchange_padding.cc execution test > > std::atomic as{ s }; > auto ts = as.load(); > VERIFY( !compare_struct(s, ts) ); // padding cleared on construction > as.exchange(s); > auto es = as.load(); > VERIFY( compare_struct(ts, es) ); // padding cleared on exchange > > How is it supposed to pass exactly? AFAICS you have no control on the padding > bits of ts or es and, indeed, at -O2 the loads are scalarized: > > __buf$c_81 = MEM[(struct S *)&__buf].c; > __buf$s_59 = MEM[(struct S *)&__buf].s; > __buf ={v} {CLOBBER(eol)}; > ts.c = __buf$c_81; > ts.s = __buf$s_59; > [...] > __buf$c_100 = MEM[(struct S *)&__buf].c; > __buf$s_35 = MEM[(struct S *)&__buf].s; > __buf ={v} {CLOBBER(eol)}; > es.c = __buf$c_100; > es.s = __buf$s_35; > _66 = MEM [(char * {ref-all})]; > _101 = MEM [(char * {ref-all})]; > if (_66 != _101) > goto ; [0.04%] > else > goto ; [99.96%] > > so the result of the 4-byte comparison is random. I suppose we could use memcmp on the as variable itself, to inspect the actual stored padding rather than the returned copy of it.
Re: [committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
> The test was only failing for me with -m32 (and not -m64), so I didn't > notice until now. That probably means we should make the test fail more > reliably if the padding isn't being cleared. The tests fail randomly for me on SPARC64/Linux: FAIL: 29_atomics/atomic/compare_exchange_padding.cc execution test FAIL: 29_atomics/atomic_ref/compare_exchange_padding.cc execution test /home/ebotcazou/src/libstdc++-v3/testsuite/29_atomics/atomic_ref/ compare_exchange_padding.cc:34: int main(): Assertion 'compare_struct(ts, es)' failed. FAIL: 29_atomics/atomic_ref/compare_exchange_padding.cc execution test std::atomic as{ s }; auto ts = as.load(); VERIFY( !compare_struct(s, ts) ); // padding cleared on construction as.exchange(s); auto es = as.load(); VERIFY( compare_struct(ts, es) ); // padding cleared on exchange How is it supposed to pass exactly? AFAICS you have no control on the padding bits of ts or es and, indeed, at -O2 the loads are scalarized: __buf$c_81 = MEM[(struct S *)&__buf].c; __buf$s_59 = MEM[(struct S *)&__buf].s; __buf ={v} {CLOBBER(eol)}; ts.c = __buf$c_81; ts.s = __buf$s_59; [...] __buf$c_100 = MEM[(struct S *)&__buf].c; __buf$s_35 = MEM[(struct S *)&__buf].s; __buf ={v} {CLOBBER(eol)}; es.c = __buf$c_100; es.s = __buf$s_35; _66 = MEM [(char * {ref-all})]; _101 = MEM [(char * {ref-all})]; if (_66 != _101) goto ; [0.04%] else goto ; [99.96%] so the result of the 4-byte comparison is random. -- Eric Botcazou
[committed] libstdc++: Fix compare_exchange_padding.cc test for std::atomic_ref
Tested x86_64-linux, pushed to trunk. The test was only failing for me with -m32 (and not -m64), so I didn't notice until now. That probably means we should make the test fail more reliably if the padding isn't being cleared. -- >8 -- This test was written assuming that std::atomic_ref clears its target's padding on construction, but that could introduce data races. Change the test to store a value after construction and check that its padding is cleared by the store. libstdc++-v3/ChangeLog: * testsuite/29_atomics/atomic_ref/compare_exchange_padding.cc: Store value with non-zero padding bits after construction. --- .../29_atomics/atomic_ref/compare_exchange_padding.cc | 11 ++- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/compare_exchange_padding.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/compare_exchange_padding.cc index 1b1a12a..e9f8a4bdf2a 100644 --- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/compare_exchange_padding.cc +++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/compare_exchange_padding.cc @@ -20,14 +20,15 @@ int main () { S s; - fill_struct(s); - s.c = 'a'; - s.s = 42; - S ss{ s }; + fill_struct(ss); + ss.c = 'a'; + ss.s = 42; + std::atomic_ref as{ s }; + as.store(ss); auto ts = as.load(); - VERIFY( !compare_struct(ss, ts) ); // padding cleared on construction + VERIFY( !compare_struct(ss, ts) ); // padding cleared on store as.exchange(ss); auto es = as.load(); VERIFY( compare_struct(ts, es) ); // padding cleared on exchange -- 2.37.3