I can't answer in general, but I can come up with an example where a plain atomic does not behave as volatile: link to Compiler Explorer.
You see how the three functions simple
, volatile
and atomic
compile down to the exact same assembly on aarch64
. However, in main
, volatile
is the only call that is not optimized away by the compiler. In other words, if you want the compiler to know your store/load has side effects, atomic is not enough. So it's not a matter of what assembly the actual load/store compiles down to, it's about what optimizations the compiler is allowed to do.