Improve atomic store implementation on hppa-linux.

2021-12-27  John David Anglin  <danglin@gcc.gnu.org>

gcc/ChangeLog:

	* config/pa/pa-protos.h: Delete
	pa_maybe_emit_compare_and_swap_exchange_loop() declaration.
	* config/pa/pa.c (pa_expand_compare_and_swap_loop): Delete.
	(pa_maybe_emit_compare_and_swap_exchange_loop): Delete.
	* config/pa/pa.md (atomic_storeq): Use __sync_lock_test_and_set
	instead of pa_maybe_emit_compare_and_swap_exchange_loop.
	(atomic_storehi, atomic_storesi, atomic_storedi): Likewise.
This commit is contained in:
John David Anglin 2021-12-27 17:56:19 +00:00
parent 916ec36d0a
commit ea8b564055
3 changed files with 24 additions and 93 deletions

View File

@ -73,7 +73,6 @@ extern rtx pa_return_addr_rtx (int, rtx);
extern int pa_insn_refs_are_delayed (rtx_insn *);
extern rtx pa_get_deferred_plabel (rtx);
extern rtx pa_maybe_emit_compare_and_swap_exchange_loop (rtx, rtx, rtx);
#endif /* RTX_CODE */
extern int pa_and_mask_p (unsigned HOST_WIDE_INT);

View File

@ -11023,82 +11023,6 @@ pa_output_addr_diff_vec (rtx lab, rtx body)
fputs ("\t.end_brtab\n", asm_out_file);
}
/* This is a helper function for the other atomic operations. This function
emits a loop that contains SEQ that iterates until a compare-and-swap
operation at the end succeeds. MEM is the memory to be modified. SEQ is
a set of instructions that takes a value from OLD_REG as an input and
produces a value in NEW_REG as an output. Before SEQ, OLD_REG will be
set to the current contents of MEM. After SEQ, a compare-and-swap will
attempt to update MEM with NEW_REG. The function returns true when the
loop was generated successfully. */
static bool
pa_expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
{
machine_mode mode = GET_MODE (mem);
rtx_code_label *label;
rtx cmp_reg, success, oldval;
/* The loop we want to generate looks like
cmp_reg = mem;
label:
old_reg = cmp_reg;
seq;
(success, cmp_reg) = compare-and-swap(mem, old_reg, new_reg)
if (success)
goto label;
Note that we only do the plain load from memory once. Subsequent
iterations use the value loaded by the compare-and-swap pattern. */
label = gen_label_rtx ();
cmp_reg = gen_reg_rtx (mode);
emit_move_insn (cmp_reg, mem);
emit_label (label);
emit_move_insn (old_reg, cmp_reg);
if (seq)
emit_insn (seq);
success = NULL_RTX;
oldval = cmp_reg;
if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg,
new_reg, false, MEMMODEL_SYNC_SEQ_CST,
MEMMODEL_RELAXED))
return false;
if (oldval != cmp_reg)
emit_move_insn (cmp_reg, oldval);
/* Mark this jump predicted not taken. */
emit_cmp_and_jump_insns (success, const0_rtx, EQ, const0_rtx,
GET_MODE (success), 1, label,
profile_probability::guessed_never ());
return true;
}
/* This function tries to implement an atomic exchange operation using a
compare_and_swap loop. VAL is written to *MEM. The previous contents of
*MEM are returned, using TARGET if possible. No memory model is required
since a compare_and_swap loop is seq-cst. */
rtx
pa_maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val)
{
machine_mode mode = GET_MODE (mem);
if (can_compare_and_swap_p (mode, true))
{
if (!target || !register_operand (target, mode))
target = gen_reg_rtx (mode);
if (pa_expand_compare_and_swap_loop (mem, target, val, NULL_RTX))
return target;
}
return NULL_RTX;
}
/* Implement TARGET_CALLEE_COPIES. The callee is responsible for copying
arguments passed by hidden reference in the 32-bit HP runtime. Users
can override this behavior for better compatibility with openmp at the

View File

@ -10366,10 +10366,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
{
if (TARGET_SYNC_LIBCALL)
{
rtx mem = operands[0];
rtx val = operands[1];
if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
DONE;
rtx libfunc = init_one_libfunc ("__sync_lock_test_and_set_1");
emit_library_call (libfunc, LCT_NORMAL, VOIDmode,
XEXP (operands[0], 0), Pmode,
operands[1], QImode);
DONE;
}
FAIL;
})
@ -10384,10 +10386,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
{
if (TARGET_SYNC_LIBCALL)
{
rtx mem = operands[0];
rtx val = operands[1];
if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
DONE;
rtx libfunc = init_one_libfunc ("__sync_lock_test_and_set_2");
emit_library_call (libfunc, LCT_NORMAL, VOIDmode,
XEXP (operands[0], 0), Pmode,
operands[1], HImode);
DONE;
}
FAIL;
})
@ -10402,10 +10406,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
{
if (TARGET_SYNC_LIBCALL)
{
rtx mem = operands[0];
rtx val = operands[1];
if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
DONE;
rtx libfunc = init_one_libfunc ("__sync_lock_test_and_set_4");
emit_library_call (libfunc, LCT_NORMAL, VOIDmode,
XEXP (operands[0], 0), Pmode,
operands[1], SImode);
DONE;
}
FAIL;
})
@ -10453,10 +10459,12 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
if (TARGET_SYNC_LIBCALL)
{
rtx mem = operands[0];
rtx val = operands[1];
if (pa_maybe_emit_compare_and_swap_exchange_loop (NULL_RTX, mem, val))
DONE;
rtx libfunc = init_one_libfunc ("__sync_lock_test_and_set_8");
emit_library_call (libfunc, LCT_NORMAL, VOIDmode,
XEXP (operands[0], 0), Pmode,
operands[1], DImode);
DONE;
}
if (TARGET_64BIT || TARGET_SOFT_FLOAT)