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
This commit is contained in:
parent
cfb9952179
commit
c39169c82c
5 changed files with 103 additions and 94 deletions
|
@ -1,3 +1,20 @@
|
||||||
|
2011-11-17 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2011-11-17 Bin Cheng <bin.cheng@arm.com>
|
2011-11-17 Bin Cheng <bin.cheng@arm.com>
|
||||||
|
|
||||||
PR rtl-optimization/50663
|
PR rtl-optimization/50663
|
||||||
|
|
|
@ -5672,23 +5672,6 @@ expand_builtin_atomic_is_lock_free (tree exp)
|
||||||
return NULL_RTX;
|
return NULL_RTX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
|
||||||
|
|
||||||
void
|
|
||||||
expand_builtin_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)
|
|
||||||
expand_builtin_sync_synchronize ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expand the __atomic_thread_fence intrinsic:
|
/* Expand the __atomic_thread_fence intrinsic:
|
||||||
void __atomic_thread_fence (enum memmodel)
|
void __atomic_thread_fence (enum memmodel)
|
||||||
EXP is the CALL_EXPR. */
|
EXP is the CALL_EXPR. */
|
||||||
|
@ -5696,46 +5679,8 @@ expand_builtin_mem_thread_fence (enum memmodel model)
|
||||||
static void
|
static void
|
||||||
expand_builtin_atomic_thread_fence (tree exp)
|
expand_builtin_atomic_thread_fence (tree exp)
|
||||||
{
|
{
|
||||||
enum memmodel model;
|
enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
|
||||||
|
expand_mem_thread_fence (model);
|
||||||
model = get_memmodel (CALL_EXPR_ARG (exp, 0));
|
|
||||||
expand_builtin_mem_thread_fence (model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
|
|
||||||
static void
|
|
||||||
expand_builtin_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)
|
|
||||||
{
|
|
||||||
rtx asm_op, clob;
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
/* Generate asm volatile("" : : : "memory") as the memory barrier. */
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand the __atomic_signal_fence intrinsic:
|
/* Expand the __atomic_signal_fence intrinsic:
|
||||||
|
@ -5745,10 +5690,8 @@ expand_builtin_mem_signal_fence (enum memmodel model)
|
||||||
static void
|
static void
|
||||||
expand_builtin_atomic_signal_fence (tree exp)
|
expand_builtin_atomic_signal_fence (tree exp)
|
||||||
{
|
{
|
||||||
enum memmodel model;
|
enum memmodel model = get_memmodel (CALL_EXPR_ARG (exp, 0));
|
||||||
|
expand_mem_signal_fence (model);
|
||||||
model = get_memmodel (CALL_EXPR_ARG (exp, 0));
|
|
||||||
expand_builtin_mem_signal_fence (model);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expand the __sync_synchronize intrinsic. */
|
/* Expand the __sync_synchronize intrinsic. */
|
||||||
|
@ -5756,31 +5699,7 @@ expand_builtin_atomic_signal_fence (tree exp)
|
||||||
static void
|
static void
|
||||||
expand_builtin_sync_synchronize (void)
|
expand_builtin_sync_synchronize (void)
|
||||||
{
|
{
|
||||||
gimple x;
|
expand_mem_thread_fence (MEMMODEL_SEQ_CST);
|
||||||
VEC (tree, gc) *v_clobbers;
|
|
||||||
|
|
||||||
#ifdef HAVE_memory_barrier
|
|
||||||
if (HAVE_memory_barrier)
|
|
||||||
{
|
|
||||||
emit_insn (gen_memory_barrier ());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (synchronize_libfunc != NULL_RTX)
|
|
||||||
{
|
|
||||||
emit_library_call (synchronize_libfunc, LCT_NORMAL, VOIDmode, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If no explicit memory barrier instruction is available, create an
|
|
||||||
empty asm stmt with a memory clobber. */
|
|
||||||
v_clobbers = VEC_alloc (tree, gc, 1);
|
|
||||||
VEC_quick_push (tree, v_clobbers,
|
|
||||||
tree_cons (NULL, build_string (6, "memory"), NULL));
|
|
||||||
x = gimple_build_asm_vec ("", NULL, NULL, v_clobbers, NULL);
|
|
||||||
gimple_asm_set_volatile (x, true);
|
|
||||||
expand_asm_stmt (x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,6 @@ extern void expand_builtin_setjmp_receiver (rtx);
|
||||||
extern rtx expand_builtin_saveregs (void);
|
extern rtx expand_builtin_saveregs (void);
|
||||||
extern void expand_builtin_trap (void);
|
extern void expand_builtin_trap (void);
|
||||||
extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
|
extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
|
||||||
extern void expand_builtin_mem_thread_fence (enum memmodel);
|
|
||||||
|
|
||||||
/* Functions from expr.c: */
|
/* Functions from expr.c: */
|
||||||
|
|
||||||
|
|
84
gcc/optabs.c
84
gcc/optabs.c
|
@ -7378,7 +7378,7 @@ expand_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model,
|
||||||
if (model == MEMMODEL_SEQ_CST
|
if (model == MEMMODEL_SEQ_CST
|
||||||
|| model == MEMMODEL_RELEASE
|
|| model == MEMMODEL_RELEASE
|
||||||
|| model == MEMMODEL_ACQ_REL)
|
|| model == MEMMODEL_ACQ_REL)
|
||||||
expand_builtin_mem_thread_fence (model);
|
expand_mem_thread_fence (model);
|
||||||
|
|
||||||
create_output_operand (&ops[0], target, mode);
|
create_output_operand (&ops[0], target, mode);
|
||||||
create_fixed_operand (&ops[1], mem);
|
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
|
if (model == MEMMODEL_SEQ_CST
|
||||||
|| model == MEMMODEL_RELEASE
|
|| model == MEMMODEL_RELEASE
|
||||||
|| model == MEMMODEL_ACQ_REL)
|
|| model == MEMMODEL_ACQ_REL)
|
||||||
expand_builtin_mem_thread_fence (model);
|
expand_mem_thread_fence (model);
|
||||||
|
|
||||||
addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
|
addr = convert_memory_address (ptr_mode, XEXP (mem, 0));
|
||||||
return emit_library_call_value (libfunc, target, LCT_NORMAL,
|
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;
|
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:
|
/* This function expands the atomic load operation:
|
||||||
return the atomically loaded value in MEM.
|
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);
|
target = gen_reg_rtx (mode);
|
||||||
|
|
||||||
/* Emit the appropriate barrier before the load. */
|
/* Emit the appropriate barrier before the load. */
|
||||||
expand_builtin_mem_thread_fence (model);
|
expand_mem_thread_fence (model);
|
||||||
|
|
||||||
emit_move_insn (target, mem);
|
emit_move_insn (target, mem);
|
||||||
|
|
||||||
/* For SEQ_CST, also emit a barrier after the load. */
|
/* For SEQ_CST, also emit a barrier after the load. */
|
||||||
if (model == MEMMODEL_SEQ_CST)
|
if (model == MEMMODEL_SEQ_CST)
|
||||||
expand_builtin_mem_thread_fence (model);
|
expand_mem_thread_fence (model);
|
||||||
|
|
||||||
return target;
|
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. */
|
/* lock_release is only a release barrier. */
|
||||||
if (model == MEMMODEL_SEQ_CST)
|
if (model == MEMMODEL_SEQ_CST)
|
||||||
expand_builtin_mem_thread_fence (model);
|
expand_mem_thread_fence (model);
|
||||||
return const0_rtx;
|
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 there is no mem_store, default to a move with barriers */
|
||||||
if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_RELEASE)
|
if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_RELEASE)
|
||||||
expand_builtin_mem_thread_fence (model);
|
expand_mem_thread_fence (model);
|
||||||
|
|
||||||
emit_move_insn (mem, val);
|
emit_move_insn (mem, val);
|
||||||
|
|
||||||
/* For SEQ_CST, also emit a barrier after the load. */
|
/* For SEQ_CST, also emit a barrier after the load. */
|
||||||
if (model == MEMMODEL_SEQ_CST)
|
if (model == MEMMODEL_SEQ_CST)
|
||||||
expand_builtin_mem_thread_fence (model);
|
expand_mem_thread_fence (model);
|
||||||
|
|
||||||
return const0_rtx;
|
return const0_rtx;
|
||||||
}
|
}
|
||||||
|
|
|
@ -978,6 +978,10 @@ extern bool can_atomic_exchange_p (enum machine_mode, bool);
|
||||||
extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
|
extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
|
||||||
enum memmodel, enum memmodel);
|
enum memmodel, enum memmodel);
|
||||||
|
|
||||||
|
/* Generate memory barriers. */
|
||||||
|
extern void expand_mem_thread_fence (enum memmodel);
|
||||||
|
extern void expand_mem_signal_fence (enum memmodel);
|
||||||
|
|
||||||
/* Check whether an operation represented by the code CODE is a
|
/* Check whether an operation represented by the code CODE is a
|
||||||
convert operation that is supported by the target platform in
|
convert operation that is supported by the target platform in
|
||||||
vector form */
|
vector form */
|
||||||
|
|
Loading…
Add table
Reference in a new issue