Commit 5e5ccf0d by Alexander Monakov Committed by Alexander Monakov

optabs: ensure mem_thread_fence is a compiler barrier

	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
parent bf498b07
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> 2017-08-27 Uros Bizjak <ubizjak@gmail.com>
PR target/81995 PR target/81995
......
...@@ -7044,14 +7044,20 @@ If these patterns are not defined, attempts will be made to use ...@@ -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 counterparts. If none of these are available a compare-and-swap
loop will be used. loop will be used.
@cindex @code{mem_thread_fence@var{mode}} instruction pattern @cindex @code{mem_thread_fence} instruction pattern
@item @samp{mem_thread_fence@var{mode}} @item @samp{mem_thread_fence}
This pattern emits code required to implement a thread fence with This pattern emits code required to implement a thread fence with
memory model semantics. Operand 0 is the memory model to be used. memory model semantics. Operand 0 is the memory model to be used.
If this pattern is not specified, all memory models except For the @code{__ATOMIC_RELAXED} model no instructions need to be issued
@code{__ATOMIC_RELAXED} will result in issuing a @code{sync_synchronize} and this expansion is not invoked.
barrier pattern.
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 @cindex @code{mem_signal_fence@var{mode}} instruction pattern
@item @samp{mem_signal_fence@var{mode}} @item @samp{mem_signal_fence@var{mode}}
......
...@@ -6297,17 +6297,19 @@ expand_asm_memory_barrier (void) ...@@ -6297,17 +6297,19 @@ expand_asm_memory_barrier (void)
void void
expand_mem_thread_fence (enum memmodel model) expand_mem_thread_fence (enum memmodel model)
{ {
if (is_mm_relaxed (model))
return;
if (targetm.have_mem_thread_fence ()) 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_mem_thread_fence (GEN_INT (model)));
emit_insn (targetm.gen_memory_barrier ()); expand_asm_memory_barrier ();
else if (synchronize_libfunc != NULL_RTX)
emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
else
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 /* This routine will either emit the mem_signal_fence pattern or issue a
......
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> 2017-08-27 Uros Bizjak <ubizjak@gmail.com>
PR target/81995 PR target/81995
......
/* { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment