https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105011
Bug ID: 105011 Summary: [nvptx] FAIL: gcc.dg/atomic/stdatomic-flag-2.c -O1 execution test Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: vries at gcc dot gnu.org Target Milestone: --- On a quadro k2000 with driver 470.103.01 I'm running into this cluster of FAILs: ... FAIL: gcc.dg/atomic/stdatomic-flag-2.c -O1 execution test FAIL: gcc.dg/atomic/stdatomic-flag-2.c -O3 -g execution test FAIL: gcc.dg/atomic/stdatomic-flag.c -O3 -g execution test ... Minimizing the first FAIL, I end up with: ... #include <stdatomic.h> extern void abort (void); atomic_flag a = ATOMIC_FLAG_INIT; int main () { int b; if ((atomic_flag_test_and_set) (&a)) abort (); return 0; } ... The atomic access is done by libatomic, using a 64-bit cas loop. If we print the address of a, we have: ... &a: 0000000700700200 ... so the pointer is already 64-bit aligned. If we print the 64-bit value of *(unsigned long long *)&a before and after the test-and-set, we have: ... a: 0000000000024f00 a: 0000000000024f01 ... so that looks all-right as well. At first glance, the problem is in libatomic, tas_n.c: ... wval = (UWORD)__GCC_ATOMIC_TEST_AND_SET_TRUEVAL << shift; woldval = __atomic_load_n (wptr, __ATOMIC_RELAXED); do { t = woldval | wval; } while (!atomic_compare_exchange_w (wptr, &woldval, t, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED)); post_barrier (smodel); return woldval != 0; ... What is returned is woldval != 0, but that tests the entire word, not just the byte we're interested in. It should probably do something like: ... return (woldval & wval) != 0; ...