re PR target/54087 (__atomic_fetch_add does not use xadd instruction)

2012-10-01  Andrew MacLeod  <amacleod@redhat.com>

	PR target/54087
	* optabs.c (expand_atomic_fetch_op_no_fallback): New.  Factored code
	from expand_atomic_fetch_op.
	(expand_atomic_fetch_op):  Try atomic_{add|sub} operations in terms of
	the other one if direct opcode fails.
	* testsuite/gcc.dg/pr54087.c:  New testcase for atomic_sub -> 
	atomic_add when atomic_sub fails.

From-SVN: r191929
This commit is contained in:
Andrew MacLeod 2012-10-01 15:50:09 +00:00 committed by Andrew Macleod
parent 992103ad69
commit cd8b6dc554
4 changed files with 94 additions and 4 deletions

View File

@ -1,3 +1,11 @@
2012-10-01 Andrew MacLeod <amacleod@redhat.com>
PR target/54087
* optabs.c (expand_atomic_fetch_op_no_fallback): New. Factored code
from expand_atomic_fetch_op.
(expand_atomic_fetch_op): Try atomic_{add|sub} operations in terms of
the other one if direct opcode fails.
2012-10-01 Uros Bizjak <ubizjak@gmail.com>
PR rtl-optimization/54457

View File

@ -7733,10 +7733,15 @@ maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem,
CODE is the operation being performed (OP)
MEMMODEL is the memory model variant to use.
AFTER is true to return the result of the operation (OP_fetch).
AFTER is false to return the value before the operation (fetch_OP). */
rtx
expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
enum memmodel model, bool after)
AFTER is false to return the value before the operation (fetch_OP).
This function will *only* generate instructions if there is a direct
optab. No compare and swap loops or libcalls will be generated. */
static rtx
expand_atomic_fetch_op_no_fallback (rtx target, rtx mem, rtx val,
enum rtx_code code, enum memmodel model,
bool after)
{
enum machine_mode mode = GET_MODE (mem);
struct atomic_op_functions optab;
@ -7809,13 +7814,66 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
}
}
/* No direct opcode can be generated. */
return NULL_RTX;
}
/* This function expands an atomic fetch_OP or OP_fetch operation:
TARGET is an option place to stick the return value. const0_rtx indicates
the result is unused.
atomically fetch MEM, perform the operation with VAL and return it to MEM.
CODE is the operation being performed (OP)
MEMMODEL is the memory model variant to use.
AFTER is true to return the result of the operation (OP_fetch).
AFTER is false to return the value before the operation (fetch_OP). */
rtx
expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
enum memmodel model, bool after)
{
enum machine_mode mode = GET_MODE (mem);
rtx result;
bool unused_result = (target == const0_rtx);
result = expand_atomic_fetch_op_no_fallback (target, mem, val, code, model,
after);
if (result)
return result;
/* Add/sub can be implemented by doing the reverse operation with -(val). */
if (code == PLUS || code == MINUS)
{
rtx tmp;
enum rtx_code reverse = (code == PLUS ? MINUS : PLUS);
start_sequence ();
tmp = expand_simple_unop (mode, NEG, val, NULL_RTX, true);
result = expand_atomic_fetch_op_no_fallback (target, mem, tmp, reverse,
model, after);
if (result)
{
/* PLUS worked so emit the insns and return. */
tmp = get_insns ();
end_sequence ();
emit_insn (tmp);
return result;
}
/* PLUS did not work, so throw away the negation code and continue. */
end_sequence ();
}
/* Try the __sync libcalls only if we can't do compare-and-swap inline. */
if (!can_compare_and_swap_p (mode, false))
{
rtx libfunc;
bool fixup = false;
enum rtx_code orig_code = code;
struct atomic_op_functions optab;
get_atomic_op_for_code (&optab, code);
libfunc = optab_libfunc (after ? optab.fetch_after
: optab.fetch_before, mode);
if (libfunc == NULL

View File

@ -1,3 +1,9 @@
2012-10-01 Andrew MacLeod <amacleod@redhat.com>
PR target/54087
* gcc.dg/pr54087.c: New testcase for atomic_sub -> atomic_add when
atomic_sub fails.
2012-10-01 Uros Bizjak <ubizjak@gmail.com>
PR rtl-optimization/54457

View File

@ -0,0 +1,18 @@
/* PR54087. Verify __atomic_sub (val) uses __atomic_add (-val) if there is no
atomic_aub. */
/* { dg-require-effective-target sync_int_long } */
/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
/* { dg-final { scan-assembler-times "xadd" 2 } } */
int a;
int f1(int p)
{
return __atomic_sub_fetch(&a, p, __ATOMIC_SEQ_CST) == 0;
}
int f2(int p)
{
return __atomic_fetch_sub(&a, p, __ATOMIC_SEQ_CST) - p == 0;
}