optabs: ensure mem_thread_fence is a compiler barrier
authorAlexander Monakov <amonakov@ispras.ru>
Mon, 28 Aug 2017 10:58:45 +0000 (13:58 +0300)
committerAlexander Monakov <amonakov@gcc.gnu.org>
Mon, 28 Aug 2017 10:58:45 +0000 (13:58 +0300)
PR target/80640
* doc/md.texi (mem_thread_fence): Remove mention of mode.  Rewrite.
* optabs.c (expand_mem_thread_fence): Emit a compiler barrier when
using targetm.gen_mem_thread_fence.
testsuite/
* gcc.dg/atomic/pr80640.c: New testcase.

From-SVN: r251377

gcc/ChangeLog
gcc/doc/md.texi
gcc/optabs.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/atomic/pr80640.c [new file with mode: 0644]

index b1070d9cbf91eb567aa5f1c54652ddb610695543..c79a0e856d5e12cb8846fe689b06b2c1c924f9bc 100644 (file)
@@ -1,3 +1,10 @@
+2017-08-28  Alexander Monakov  <amonakov@ispras.ru>
+
+       PR target/80640
+       * doc/md.texi (mem_thread_fence): Remove mention of mode.  Rewrite.
+       * optabs.c (expand_mem_thread_fence): Emit a compiler barrier when
+       using targetm.gen_mem_thread_fence.
+
 2017-08-27  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/81995
index ea959208c98b3f3852600548f5fedc46a93e8bd3..64a137ecad04238c4f3dd20e28c44c315b0610dc 100644 (file)
@@ -7044,14 +7044,20 @@ If these patterns are not defined, attempts will be made to use
 counterparts.  If none of these are available a compare-and-swap
 loop will be used.
 
-@cindex @code{mem_thread_fence@var{mode}} instruction pattern
-@item @samp{mem_thread_fence@var{mode}}
+@cindex @code{mem_thread_fence} instruction pattern
+@item @samp{mem_thread_fence}
 This pattern emits code required to implement a thread fence with
 memory model semantics.  Operand 0 is the memory model to be used.
 
-If this pattern is not specified, all memory models except
-@code{__ATOMIC_RELAXED} will result in issuing a @code{sync_synchronize}
-barrier pattern.
+For the @code{__ATOMIC_RELAXED} model no instructions need to be issued
+and this expansion is not invoked.
+
+The compiler always emits a compiler memory barrier regardless of what
+expanding this pattern produced.
+
+If this pattern is not defined, the compiler falls back to expanding the
+@code{memory_barrier} pattern, then to emitting @code{__sync_synchronize}
+library call, and finally to just placing a compiler memory barrier.
 
 @cindex @code{mem_signal_fence@var{mode}} instruction pattern
 @item @samp{mem_signal_fence@var{mode}}
index a9900657a586ea23b8bee000fdf277639510ccc8..71b74dd5feb579d74ad5f5a8fa1900c66160794b 100644 (file)
@@ -6297,17 +6297,19 @@ expand_asm_memory_barrier (void)
 void
 expand_mem_thread_fence (enum memmodel model)
 {
+  if (is_mm_relaxed (model))
+    return;
   if (targetm.have_mem_thread_fence ())
-    emit_insn (targetm.gen_mem_thread_fence (GEN_INT (model)));
-  else if (!is_mm_relaxed (model))
     {
-      if (targetm.have_memory_barrier ())
-       emit_insn (targetm.gen_memory_barrier ());
-      else if (synchronize_libfunc != NULL_RTX)
-       emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
-      else
-       expand_asm_memory_barrier ();
+      emit_insn (targetm.gen_mem_thread_fence (GEN_INT (model)));
+      expand_asm_memory_barrier ();
     }
+  else if (targetm.have_memory_barrier ())
+    emit_insn (targetm.gen_memory_barrier ());
+  else if (synchronize_libfunc != NULL_RTX)
+    emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
+  else
+    expand_asm_memory_barrier ();
 }
 
 /* This routine will either emit the mem_signal_fence pattern or issue a 
index d4bcd429ab74ebc4c3d2c9aeb1b33a8e7f938c10..a3687c49e3dc5b5146255c683ba999a91e34b9ab 100644 (file)
@@ -1,3 +1,8 @@
+2017-08-28  Alexander Monakov  <amonakov@ispras.ru>
+
+       PR target/80640
+       * gcc.dg/atomic/pr80640.c: New testcase.
+
 2017-08-27  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/81995
diff --git a/gcc/testsuite/gcc.dg/atomic/pr80640.c b/gcc/testsuite/gcc.dg/atomic/pr80640.c
new file mode 100644 (file)
index 0000000..fd17978
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-pthread" } */
+/* { dg-require-effective-target pthread } */
+
+#include <pthread.h>
+
+static volatile int sem1;
+static volatile int sem2;
+
+static void *f(void *va)
+{
+  void **p = va;
+  if (*p) return *p;
+  sem1 = 1;
+  while (!sem2);
+  __atomic_thread_fence(__ATOMIC_ACQUIRE);
+  // GCC used to RTL-CSE this and the first load, causing 0 to be returned
+  return *p;
+}
+
+int main()
+{
+  void *p = 0;
+  pthread_t thr;
+  if (pthread_create(&thr, 0, f, &p))
+    return 2;
+  while (!sem1);
+  __atomic_thread_fence(__ATOMIC_ACQUIRE);
+  p = &p;
+  __atomic_thread_fence(__ATOMIC_RELEASE);
+  sem2 = 1;
+  pthread_join(thr, &p);
+  return !p;
+}