diff options
author | Richard Henderson <rth@redhat.com> | 2011-11-17 11:29:04 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2011-11-17 11:29:04 -0800 |
commit | c39169c82c278bff88da0fcb05516420fbcf808a (patch) | |
tree | c5fe338ba828667922ef001c6df7a932a78412e6 /gcc/optabs.c | |
parent | cfb9952179d2ea470461a0ea3ab64c53a9d27fb8 (diff) | |
download | gcc-c39169c82c278bff88da0fcb05516420fbcf808a.zip gcc-c39169c82c278bff88da0fcb05516420fbcf808a.tar.gz gcc-c39169c82c278bff88da0fcb05516420fbcf808a.tar.bz2 |
Unify implementations of __builtin_mem_*_fence and __sync_synchronize.
* builtins.c (expand_builtin_mem_thread_fence): Remove.
(expand_builtin_mem_signal_fence): Remove.
(expand_builtin_atomic_thread_fence): Use expand_mem_thread_fence.
(expand_builtin_sync_synchronize): Likewise.
(expand_builtin_atomic_signal_fence): Use expand_mem_signal_fence.
* optabs.c (expand_asm_memory_barrier): Split out from
expand_builtin_mem_signal_fence.
(expand_mem_thread_fence): New, a combination of code from
expand_builtin_mem_thread_fence and expand_builtin_sync_synchronize.
(expand_mem_signal_fence): Moved and renamed from
expand_builtin_mem_signal_fence.
(expand_atomic_exchange): Use expand_mem_thread_fence.
(expand_atomic_load, expand_atomic_store): Likewise.
* expr.h, optabs.h: Update decls.
From-SVN: r181451
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r-- | gcc/optabs.c | 84 |
1 files changed, 77 insertions, 7 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index 171756b..2468efd 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -7378,7 +7378,7 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model, if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_RELEASE || model == MEMMODEL_ACQ_REL) - expand_builtin_mem_thread_fence (model); + expand_mem_thread_fence (model); create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); @@ -7403,7 +7403,7 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model, if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_RELEASE || model == MEMMODEL_ACQ_REL) - expand_builtin_mem_thread_fence (model); + expand_mem_thread_fence (model); addr = convert_memory_address (ptr_mode, XEXP (mem, 0)); return emit_library_call_value (libfunc, target, LCT_NORMAL, @@ -7556,6 +7556,76 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval, return true; } +/* Generate asm volatile("" : : : "memory") as the memory barrier. */ + +static void +expand_asm_memory_barrier (void) +{ + rtx asm_op, clob; + + asm_op = gen_rtx_ASM_OPERANDS (VOIDmode, empty_string, empty_string, 0, + rtvec_alloc (0), rtvec_alloc (0), + rtvec_alloc (0), UNKNOWN_LOCATION); + MEM_VOLATILE_P (asm_op) = 1; + + clob = gen_rtx_SCRATCH (VOIDmode); + clob = gen_rtx_MEM (BLKmode, clob); + clob = gen_rtx_CLOBBER (VOIDmode, clob); + + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, asm_op, clob))); +} + +/* This routine will either emit the mem_thread_fence pattern or issue a + sync_synchronize to generate a fence for memory model MEMMODEL. */ + +#ifndef HAVE_mem_thread_fence +# define HAVE_mem_thread_fence 0 +# define gen_mem_thread_fence(x) (gcc_unreachable (), NULL_RTX) +#endif +#ifndef HAVE_memory_barrier +# define HAVE_memory_barrier 0 +# define gen_memory_barrier() (gcc_unreachable (), NULL_RTX) +#endif + +void +expand_mem_thread_fence (enum memmodel model) +{ + if (HAVE_mem_thread_fence) + emit_insn (gen_mem_thread_fence (GEN_INT (model))); + else if (model != MEMMODEL_RELAXED) + { + if (HAVE_memory_barrier) + emit_insn (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 + sync_synchronize to generate a fence for memory model MEMMODEL. */ + +#ifndef HAVE_mem_signal_fence +# define HAVE_mem_signal_fence 0 +# define gen_mem_signal_fence(x) (gcc_unreachable (), NULL_RTX) +#endif + +void +expand_mem_signal_fence (enum memmodel model) +{ + if (HAVE_mem_signal_fence) + emit_insn (gen_mem_signal_fence (GEN_INT (model))); + else if (model != MEMMODEL_RELAXED) + { + /* By default targets are coherent between a thread and the signal + handler running on the same thread. Thus this really becomes a + compiler barrier, in that stores must not be sunk past + (or raised above) a given point. */ + expand_asm_memory_barrier (); + } +} + /* This function expands the atomic load operation: return the atomically loaded value in MEM. @@ -7598,13 +7668,13 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model) target = gen_reg_rtx (mode); /* Emit the appropriate barrier before the load. */ - expand_builtin_mem_thread_fence (model); + expand_mem_thread_fence (model); emit_move_insn (target, mem); /* For SEQ_CST, also emit a barrier after the load. */ if (model == MEMMODEL_SEQ_CST) - expand_builtin_mem_thread_fence (model); + expand_mem_thread_fence (model); return target; } @@ -7645,7 +7715,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) { /* lock_release is only a release barrier. */ if (model == MEMMODEL_SEQ_CST) - expand_builtin_mem_thread_fence (model); + expand_mem_thread_fence (model); return const0_rtx; } } @@ -7665,13 +7735,13 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) /* If there is no mem_store, default to a move with barriers */ if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_RELEASE) - expand_builtin_mem_thread_fence (model); + expand_mem_thread_fence (model); emit_move_insn (mem, val); /* For SEQ_CST, also emit a barrier after the load. */ if (model == MEMMODEL_SEQ_CST) - expand_builtin_mem_thread_fence (model); + expand_mem_thread_fence (model); return const0_rtx; } |