https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68868
Bug ID: 68868 Summary: atomic_init emits an unnecessary fence Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- This is similar but not the same as as bug 68622. The following test case that uses atomic_init() and shows that while libstdc++ handles the C++ case efficiently, C does not and emits an unnecessary fence: #if __cplusplus # include <atomic> using std::atomic_int; using std::atomic_init; #else # include <stdatomic.h> #endif typedef atomic_int AI; void foo (AI *ai) { atomic_init (ai, 123); } Gcc (in C mode) emits the following with -O2 on x86_64: foo: movl $123, (%rdi) mfence ret G++, on the other hand, and Clang in both modes, emit the following efficient code at -O2: _Z3fooPSt6atomicIiE: movl $123, (%rdi) ret The C code is worse because the C <stdatomic.h> header doesn't distinguish initialization from assignment and implements the atomic_init() macro as plain assignment: #define atomic_init(PTR, VAL) \ do \ { \ *(PTR) = (VAL); \ } \ while (0) Defining atomic_init() as in the otherwise untested patch below gets rid of the unnecessary fence: --- ginclude/stdatomic.h (revision 231532) +++ ginclude/stdatomic.h (working copy) @@ -77,13 +77,13 @@ #define ATOMIC_VAR_INIT(VALUE) (VALUE) -#define atomic_init(PTR, VAL) \ - do \ - { \ - *(PTR) = (VAL); \ - } \ - while (0) +/* Initialize an atomic object pointed to by PTR with VALUE. */ +#define atomic_init(PTR, VALUE) __extension__ ({ \ + __typeof__ (VALUE) __tmp = (VALUE); \ + __atomic_store ((PTR), &__tmp, __ATOMIC_RELAXED); \ + }) + #define kill_dependency(Y) \ __extension__ \ ({ \