https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128266
liu zhenyu <lzy20000419 at outlook dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |lzy20000419 at outlook dot com
--- Comment #1 from liu zhenyu <lzy20000419 at outlook dot com> ---
Confirmed on trunk; root cause below.
Reduced:
```c
#include <stdatomic.h>
volatile _Atomic int r2;
void g (void)
{
atomic_load_explicit (&r2, memory_order_relaxed);
}
```
gcc -O2 -S: trunk 17.0.0 (20261030, and godbolt trunk 20261101) emits only
`ret` for g at -O1/-O2/-O3/-Os; -O0 keeps the load. 16.2.1, 16.2.0, 15.3.0,
14.2.0 and every major back to 7.5.0 keep `movl r2(%rip), %eax`. The same
happens for `__atomic_load_n (p, __ATOMIC_RELAXED)` with `volatile int *p`.
Caused by r17-75-gf1b16d7a17bf (PR123966). In mark_stmt_if_obviously_necessary
(tree-ssa-dce.cc), the new early return for a relaxed atomic load with an
unused result comes before the gimple_has_side_effects check, which is what
used to keep this call. By cddce the call is `__atomic_load_4 (&r2, 0)` with no
LHS, so the volatility is only visible on the decl (TREE_THIS_VOLATILE) or on
the pointee type of the pointer argument. The early return also skips the
!can_delete_dead_exceptions && stmt_could_throw_p check. Both dce and cddce
delete the load.
Possible fix: only take the relaxed-load early return when the accessed
object/pointee is not volatile (and the call cannot throw or dead exceptions
may be deleted) (not tested).
Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.