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__                                        \
   ({                                           \

Reply via email to