Commit 6ff336b4 by Andrew MacLeod Committed by Andrew Macleod

optabs.c (get_atomic_op_for_code): Fill in optab table at runtime so…

optabs.c (get_atomic_op_for_code): Fill in optab table at runtime so SWITCHABLE_TARGET can change the valuies...



2011-11-07  Andrew MacLeod  <amacleod@redhat.com>

	* optabs.c (get_atomic_op_for_code): Fill in optab table at runtime so
	SWITCHABLE_TARGET can change the valuies during compilation.
	(expand_atomic_fetch_op): handle parameter changes ripples for 
	get_atomic_op_for_code call.

From-SVN: r181112
parent 0669295b
2011-11-07 Andrew MacLeod <amacleod@redhat.com> 2011-11-07 Andrew MacLeod <amacleod@redhat.com>
* optabs.c (get_atomic_op_for_code): Fill in optab table at runtime so
SWITCHABLE_TARGET can change the values during compilation.
(expand_atomic_fetch_op): Handle parameter change ripples for
get_atomic_op_for_code call.
2011-11-07 Andrew MacLeod <amacleod@redhat.com>
* doc/extend.texi: Docuemnt behaviour change for __atomic_exchange and * doc/extend.texi: Docuemnt behaviour change for __atomic_exchange and
__atomic_store. __atomic_store.
* optabs.c (expand_atomic_exchange): Expand to __sync_lock_test_and_set * optabs.c (expand_atomic_exchange): Expand to __sync_lock_test_and_set
...@@ -7579,43 +7579,74 @@ struct atomic_op_functions ...@@ -7579,43 +7579,74 @@ struct atomic_op_functions
enum rtx_code reverse_code; enum rtx_code reverse_code;
}; };
static const struct atomic_op_functions *
get_atomic_op_for_code (enum rtx_code code)
{
static const struct atomic_op_functions add_op = {
atomic_fetch_add_optab, atomic_add_fetch_optab, atomic_add_optab,
sync_old_add_optab, sync_new_add_optab, sync_add_optab, MINUS
}, sub_op = {
atomic_fetch_sub_optab, atomic_sub_fetch_optab, atomic_sub_optab,
sync_old_sub_optab, sync_new_sub_optab, sync_sub_optab, PLUS
}, xor_op = {
atomic_fetch_xor_optab, atomic_xor_fetch_optab, atomic_xor_optab,
sync_old_xor_optab, sync_new_xor_optab, sync_xor_optab, XOR
}, and_op = {
atomic_fetch_and_optab, atomic_and_fetch_optab, atomic_and_optab,
sync_old_and_optab, sync_new_and_optab, sync_and_optab, UNKNOWN
}, nand_op = {
atomic_fetch_nand_optab, atomic_nand_fetch_optab, atomic_nand_optab,
sync_old_nand_optab, sync_new_nand_optab, sync_nand_optab, UNKNOWN
}, ior_op = {
atomic_fetch_or_optab, atomic_or_fetch_optab, atomic_or_optab,
sync_old_ior_optab, sync_new_ior_optab, sync_ior_optab, UNKNOWN
};
/* Fill in structure pointed to by OP with the various optab entries for an
operation of type CODE. */
static void
get_atomic_op_for_code (struct atomic_op_functions *op, enum rtx_code code)
{
gcc_assert (op!= NULL);
/* If SWITCHABLE_TARGET is defined, then subtargets can be switched
in the source code during compilation, and the optab entries are not
computable until runtime. Fill in the values at runtime. */
switch (code) switch (code)
{ {
case PLUS: case PLUS:
return &add_op; op->mem_fetch_before = atomic_fetch_add_optab;
op->mem_fetch_after = atomic_add_fetch_optab;
op->mem_no_result = atomic_add_optab;
op->fetch_before = sync_old_add_optab;
op->fetch_after = sync_new_add_optab;
op->no_result = sync_add_optab;
op->reverse_code = MINUS;
break;
case MINUS: case MINUS:
return &sub_op; op->mem_fetch_before = atomic_fetch_sub_optab;
op->mem_fetch_after = atomic_sub_fetch_optab;
op->mem_no_result = atomic_sub_optab;
op->fetch_before = sync_old_sub_optab;
op->fetch_after = sync_new_sub_optab;
op->no_result = sync_sub_optab;
op->reverse_code = PLUS;
break;
case XOR: case XOR:
return &xor_op; op->mem_fetch_before = atomic_fetch_xor_optab;
op->mem_fetch_after = atomic_xor_fetch_optab;
op->mem_no_result = atomic_xor_optab;
op->fetch_before = sync_old_xor_optab;
op->fetch_after = sync_new_xor_optab;
op->no_result = sync_xor_optab;
op->reverse_code = XOR;
break;
case AND: case AND:
return &and_op; op->mem_fetch_before = atomic_fetch_and_optab;
op->mem_fetch_after = atomic_and_fetch_optab;
op->mem_no_result = atomic_and_optab;
op->fetch_before = sync_old_and_optab;
op->fetch_after = sync_new_and_optab;
op->no_result = sync_and_optab;
op->reverse_code = UNKNOWN;
break;
case IOR: case IOR:
return &ior_op; op->mem_fetch_before = atomic_fetch_or_optab;
op->mem_fetch_after = atomic_or_fetch_optab;
op->mem_no_result = atomic_or_optab;
op->fetch_before = sync_old_ior_optab;
op->fetch_after = sync_new_ior_optab;
op->no_result = sync_ior_optab;
op->reverse_code = UNKNOWN;
break;
case NOT: case NOT:
return &nand_op; op->mem_fetch_before = atomic_fetch_nand_optab;
op->mem_fetch_after = atomic_nand_fetch_optab;
op->mem_no_result = atomic_nand_optab;
op->fetch_before = sync_old_nand_optab;
op->fetch_after = sync_new_nand_optab;
op->no_result = sync_nand_optab;
op->reverse_code = UNKNOWN;
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -7701,22 +7732,22 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code, ...@@ -7701,22 +7732,22 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
enum memmodel model, bool after) enum memmodel model, bool after)
{ {
enum machine_mode mode = GET_MODE (mem); enum machine_mode mode = GET_MODE (mem);
const struct atomic_op_functions *optab; struct atomic_op_functions optab;
rtx result; rtx result;
bool unused_result = (target == const0_rtx); bool unused_result = (target == const0_rtx);
optab = get_atomic_op_for_code (code); get_atomic_op_for_code (&optab, code);
/* Check for the case where the result isn't used and try those patterns. */ /* Check for the case where the result isn't used and try those patterns. */
if (unused_result) if (unused_result)
{ {
/* Try the memory model variant first. */ /* Try the memory model variant first. */
result = maybe_emit_op (optab, target, mem, val, true, model, true); result = maybe_emit_op (&optab, target, mem, val, true, model, true);
if (result) if (result)
return result; return result;
/* Next try the old style withuot a memory model. */ /* Next try the old style withuot a memory model. */
result = maybe_emit_op (optab, target, mem, val, false, model, true); result = maybe_emit_op (&optab, target, mem, val, false, model, true);
if (result) if (result)
return result; return result;
...@@ -7725,23 +7756,23 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code, ...@@ -7725,23 +7756,23 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
} }
/* Try the __atomic version. */ /* Try the __atomic version. */
result = maybe_emit_op (optab, target, mem, val, true, model, after); result = maybe_emit_op (&optab, target, mem, val, true, model, after);
if (result) if (result)
return result; return result;
/* Try the older __sync version. */ /* Try the older __sync version. */
result = maybe_emit_op (optab, target, mem, val, false, model, after); result = maybe_emit_op (&optab, target, mem, val, false, model, after);
if (result) if (result)
return result; return result;
/* If the fetch value can be calculated from the other variation of fetch, /* If the fetch value can be calculated from the other variation of fetch,
try that operation. */ try that operation. */
if (after || optab->reverse_code != UNKNOWN || target == const0_rtx) if (after || optab.reverse_code != UNKNOWN || target == const0_rtx)
{ {
/* Try the __atomic version, then the older __sync version. */ /* Try the __atomic version, then the older __sync version. */
result = maybe_emit_op (optab, target, mem, val, true, model, !after); result = maybe_emit_op (&optab, target, mem, val, true, model, !after);
if (!result) if (!result)
result = maybe_emit_op (optab, target, mem, val, false, model, !after); result = maybe_emit_op (&optab, target, mem, val, false, model, !after);
if (result) if (result)
{ {
...@@ -7752,7 +7783,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code, ...@@ -7752,7 +7783,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
/* Issue compensation code. Fetch_after == fetch_before OP val. /* Issue compensation code. Fetch_after == fetch_before OP val.
Fetch_before == after REVERSE_OP val. */ Fetch_before == after REVERSE_OP val. */
if (!after) if (!after)
code = optab->reverse_code; code = optab.reverse_code;
result = expand_simple_binop (mode, code, result, val, NULL_RTX, true, result = expand_simple_binop (mode, code, result, val, NULL_RTX, true,
OPTAB_LIB_WIDEN); OPTAB_LIB_WIDEN);
return result; return result;
......
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