Here's the last of the missing intrinsics. compare_exchange is
slightly different than the others since it doesn't map directly to an
rtl pattern. Its format is :
bool __atomic_compare_exchange (T* mem, T* expected, T desired, bool
weak, memory_order success, memory_order failure)
note that the expected parameter is a pointer as well. In the case
where false is returned, the value of expected is updated.
Instead of providing a complex rtl pattern to try to match this, instead
all that is required is to provide a compare_and_swap routine, which
this builtin will then add some wrapper code around to match the
required functionality.
there are 2 rtl patterns it looks for,
atomic_compare_and_swap_weak and
atomic_compare_and_swap_strong
both are of the form
QImode atomicCAS (mem(O), current_val(O), expected(I), desired(I),
memorymodel(const int))
When neither of these patterns are present, the implementation defaults
to using __sync_val_compare_and_swap to provide the implementation.
New tests have been added as well.
Bootstraps and no new regressions on x86_64-unknown-linux-gnu
so a bit of different rtl hacking around in there for me... does
everything look OK? it seems to work :-) Actual pattern
implementation and debugging will happen later when we actually write
custom patterns for all these rather than defaulting to the current
seq-cst patterns.
Andrew
* optabs.h (direct_optab_index): Replace DOI_atomic_compare_exchange
with DOI_atomic_compare_and_swap_{strong,weak}.
(direct_op): Add DOI_atomic_compare_and_swap_{strong,weak}.
* genopinit.c: Set atomic_compare_and_swap_{strong,weak}_optab.
* expr.h (expand_atomic_compare_exchange): Add parameter.
* builtins.c (builtin_atomic_compare_exchange): Add weak parameter
and verify it is a compile time constant.
* optabs.c (expand_atomic_compare_exchange): Look for the presence of
atomic_compare_and_swap_{strong,weak} patterns, otherwise use
__sync_val_compare_and_swap.
* builtin-types.def (BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_BOOL_INT_INT):
Add the bool parameter.
* sync-builtins.def (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_*): Use new
prototype.
* c-family/c-common.c (resolve_overloaded_builtin): Don't try to
process a return value with an error mark.
* fortran/types.def (BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_BOOL_INT_INT):
Add the bool parameter.
* testsuite/gcc.dg/atomic-invalid.c: Add compare_exchange failures.
* testsuite/gcc.dg/atomic-compare-exchange-{1-5}.c: New tests.
Index: optabs.h
===================================================================
*** optabs.h (revision 180092)
--- optabs.h (working copy)
*************** enum direct_optab_index
*** 690,696 ****
/* Atomic operations with memory model parameters. */
DOI_atomic_exchange,
! DOI_atomic_compare_exchange,
DOI_atomic_load,
DOI_atomic_store,
DOI_atomic_add_fetch,
--- 690,697 ----
/* Atomic operations with memory model parameters. */
DOI_atomic_exchange,
! DOI_atomic_compare_and_swap_strong,
! DOI_atomic_compare_and_swap_weak,
DOI_atomic_load,
DOI_atomic_store,
DOI_atomic_add_fetch,
*************** typedef struct direct_optab_d *direct_op
*** 765,772 ****
#define atomic_exchange_optab \
(&direct_optab_table[(int) DOI_atomic_exchange])
! #define atomic_compare_exchange_optab \
! (&direct_optab_table[(int) DOI_atomic_compare_exchange])
#define atomic_load_optab \
(&direct_optab_table[(int) DOI_atomic_load])
#define atomic_store_optab \
--- 766,775 ----
#define atomic_exchange_optab \
(&direct_optab_table[(int) DOI_atomic_exchange])
! #define atomic_compare_and_swap_strong_optab \
! (&direct_optab_table[(int) DOI_atomic_compare_and_swap_strong])
! #define atomic_compare_and_swap_weak_optab \
! (&direct_optab_table[(int) DOI_atomic_compare_and_swap_weak])
#define atomic_load_optab \
(&direct_optab_table[(int) DOI_atomic_load])
#define atomic_store_optab \
Index: genopinit.c
===================================================================
*** genopinit.c (revision 180092)
--- genopinit.c (working copy)
*************** static const char * const optabs[] =
*** 244,250 ****
"set_direct_optab_handler (sync_lock_test_and_set_optab, $A,
CODE_FOR_$(sync_lock_test_and_set$I$a$))",
"set_direct_optab_handler (sync_lock_release_optab, $A,
CODE_FOR_$(sync_lock_release$I$a$))",
"set_direct_optab_handler (atomic_exchange_optab, $A,
CODE_FOR_$(atomic_exchange$I$a$))",
! "set_direct_optab_handler (atomic_compare_exchange_optab, $A,
CODE_FOR_$(atomic_compare_exchange$I$a$))",
"set_direct_optab_handler (atomic_load_optab, $A,
CODE_FOR_$(atomic_load$I$a$))",
"set_direct_optab_handler (atomic_store_optab, $A,
CODE_FOR_$(atomic_store$I$a$))",
"set_direct_optab_handler (atomic_add_fetch_optab, $A,
CODE_FOR_$(atomic_add_fetch$I$a$))",
--- 244,251 ----
"set_direct_optab_handler (sync_lock_test_and_set_optab, $A,
CODE_FOR_$(sync_lock_test_and_set$I$a$))",
"set_direct_optab_handler (sync_lock_release_optab, $A,
CODE_FOR_$(sync_lock_release$I$a$))",
"set_direct_optab_handler (atomic_exchange_optab, $A,
CODE_FOR_$(atomic_exchange$I$a$))",
! "set_direct_optab_handler (atomic_compare_and_swap_strong_optab, $A,
CODE_FOR_$(atomic_compare_and_swap_strong$I$a$))",
! "set_direct_optab_handler (atomic_compare_and_swap_weak_optab, $A,
CODE_FOR_$(atomic_compare_and_swap_weak$I$a$))",
"set_direct_optab_handler (atomic_load_optab, $A,
CODE_FOR_$(atomic_load$I$a$))",
"set_direct_optab_handler (atomic_store_optab, $A,
CODE_FOR_$(atomic_store$I$a$))",
"set_direct_optab_handler (atomic_add_fetch_optab, $A,
CODE_FOR_$(atomic_add_fetch$I$a$))",
Index: expr.h
===================================================================
*** expr.h (revision 180092)
--- expr.h (working copy)
*************** rtx expand_sync_operation (rtx, rtx, enu
*** 218,224 ****
rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
! rtx expand_atomic_compare_exchange (rtx, rtx, rtx, rtx, enum memmodel,
enum memmodel);
rtx expand_atomic_load (rtx, rtx, enum memmodel);
rtx expand_atomic_store (rtx, rtx, enum memmodel);
--- 218,224 ----
rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
! rtx expand_atomic_compare_exchange (rtx, rtx, rtx, rtx, rtx, enum memmodel,
enum memmodel);
rtx expand_atomic_load (rtx, rtx, enum memmodel);
rtx expand_atomic_store (rtx, rtx, enum memmodel);
Index: builtins.c
===================================================================
*** builtins.c (revision 180092)
--- builtins.c (working copy)
*************** static rtx
*** 5292,5302 ****
expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
rtx target)
{
! rtx expect, desired, mem;
enum memmodel success, failure;
! success = get_memmodel (CALL_EXPR_ARG (exp, 3));
! failure = get_memmodel (CALL_EXPR_ARG (exp, 4));
if (failure == MEMMODEL_RELEASE || failure == MEMMODEL_ACQ_REL)
{
--- 5292,5302 ----
expand_builtin_atomic_compare_exchange (enum machine_mode mode, tree exp,
rtx target)
{
! rtx expect, desired, mem, weak;
enum memmodel success, failure;
! success = get_memmodel (CALL_EXPR_ARG (exp, 4));
! failure = get_memmodel (CALL_EXPR_ARG (exp, 5));
if (failure == MEMMODEL_RELEASE || failure == MEMMODEL_ACQ_REL)
{
*************** expand_builtin_atomic_compare_exchange (
*** 5319,5326 ****
desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
! return expand_atomic_compare_exchange (target, mem, expect, desired,
! success, failure);
}
/* Expand the __atomic_load intrinsic:
--- 5319,5335 ----
desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
! weak = expand_expr (CALL_EXPR_ARG (exp, 3), NULL_RTX, ptr_mode,
! EXPAND_NORMAL);
!
! if (weak != const0_rtx && weak != const1_rtx)
! {
! error ("strong/weak parameter must be 0 or 1 for
%<__atomic_compare_exchange%>");
! return NULL_RTX;
! }
!
! return expand_atomic_compare_exchange (target, mem, expect, desired, weak,
! success, failure);
}
/* Expand the __atomic_load intrinsic:
Index: optabs.c
===================================================================
*** optabs.c (revision 180092)
--- optabs.c (working copy)
*************** expand_atomic_exchange (rtx target, rtx
*** 7035,7095 ****
rtx
expand_atomic_compare_exchange (rtx target, rtx mem, rtx expected,
! rtx desired, enum memmodel success,
! enum memmodel failure)
{
enum machine_mode mode = GET_MODE (mem);
! enum insn_code icode;
! /* If the target supports the exchange directly, great. */
! icode = direct_optab_handler (atomic_compare_exchange_optab, mode);
if (icode != CODE_FOR_nothing)
{
! struct expand_operand ops[6];
create_output_operand (&ops[0], target, QImode);
create_output_operand (&ops[1], mem, mode);
! /* VAL may have been promoted to a wider mode. Shrink it if so. */
! create_convert_operand_to (&ops[2], expected, mode, true);
! create_convert_operand_to (&ops[3], desired, mode, true);
! create_integer_operand (&ops[4], success);
! create_integer_operand (&ops[5], failure);
! if (maybe_expand_insn (icode, 6, ops))
! return ops[0].value;
! }
! /* Instead try the instruction with a compare_ swap instruction and
! barriers assuming success (which must be the strongest model). */
icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
if (icode == CODE_FOR_nothing)
return NULL_RTX;
- return NULL_RTX;
-
- #if 0
-
- /* We're punting on implementing compare_exchange to get everything else
- checked in, then we'll come back and implement this, as well as provide
- the weak and strong variations. */
-
- expand_builtin_mem_thread_fence (model);
-
- /* Load '*expected into a register for the compare and swap */
-
/* Issue the compare and swap */
! /* cmp = expand_CAS (mem, expected, desired, target, &result); */
!
! /* If (cmp) target = cmp; return true if success. */
! /* else { *expected = result; target = !cmp } */
! /* Otherwise, copy old value into expected and return false; */
! expand_builtin_mem_thread_fence (model);
!
! return target;
! #endif
}
--- 7035,7124 ----
rtx
expand_atomic_compare_exchange (rtx target, rtx mem, rtx expected,
! rtx desired, rtx weak, enum memmodel success,
! enum memmodel failure)
{
enum machine_mode mode = GET_MODE (mem);
! enum insn_code icode = CODE_FOR_nothing;
! rtx expected_val, CAS_val;
!
! /* Load '*expected into a register for the compare and swap */
! expected_val = gen_reg_rtx (mode);
! emit_move_insn (expected_val, gen_rtx_MEM (mode, expected));
! if (weak == const1_rtx)
! icode = direct_optab_handler (atomic_compare_and_swap_weak_optab, mode);
!
! /* If there is no weak pattern, fall back to the strong pattern. */
! if (icode == CODE_FOR_nothing)
! icode = direct_optab_handler (atomic_compare_and_swap_strong_optab, mode);
!
if (icode != CODE_FOR_nothing)
{
! struct expand_operand ops[7];
! rtx current_val = gen_reg_rtx (mode);
! rtx done_label = gen_label_rtx ();
! rtx true_label;
!
! /* If success is not relaxed or release, an acquire barrier of some
! sort will be required after the CAS. Otherwise we can shorten the
! code somewhat by jumping right to the end. */
! if (success != MEMMODEL_RELAXED && success != MEMMODEL_RELEASE)
! true_label = gen_label_rtx ();
! else
! true_label = done_label;
+ /* Emit the compare_and_swap. */
create_output_operand (&ops[0], target, QImode);
create_output_operand (&ops[1], mem, mode);
! create_output_operand (&ops[2], current_val, mode);
! create_convert_operand_to (&ops[3], expected_val, mode, true);
! create_convert_operand_to (&ops[4], desired, mode, true);
! create_integer_operand (&ops[5], success);
! expand_insn (icode, 6, ops);
!
! emit_cmp_and_jump_insns (ops[0].value, const0_rtx, NE, const0_rtx,
! QImode, 1, true_label);
!
! /* if not successful copy expected_val into *expected and issue the
! failure fence. */
! emit_move_insn (gen_rtx_MEM (mode, expected), current_val);
! expand_builtin_mem_thread_fence (failure);
!
! /* If no success fence is required, we're done. Otherwise jump around
the
! code for TRUE and emitthe fence. */
! if (true_label != done_label)
! {
! emit_jump_insn (gen_jump (done_label));
!
! emit_label (true_label);
! if (success != MEMMODEL_RELAXED && success != MEMMODEL_RELEASE)
! expand_builtin_mem_thread_fence (success);
! }
!
! emit_label (done_label);
! /* Return success/failure. */
! return ops[0].value;
! }
+ /* Otherwise fall back to the original __sync_val_compare_and_swap which is
+ always seq-cst. */
icode = direct_optab_handler (sync_compare_and_swap_optab, mode);
if (icode == CODE_FOR_nothing)
return NULL_RTX;
/* Issue the compare and swap */
! CAS_val = expand_val_compare_and_swap_1 (mem, expected_val, desired,
NULL_RTX,
! icode);
! /* Always store the result back into 'expected'. If the result is true, its
! an extra store, but makes the flow better. */
! emit_move_insn (gen_rtx_MEM (mode, expected), CAS_val);
! return emit_store_flag_force (target, EQ, CAS_val, expected_val,
! VOIDmode, 1, 1);
}
Index: builtin-types.def
===================================================================
*** builtin-types.def (revision 180092)
--- builtin-types.def (working copy)
*************** DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_IN
*** 437,453 ****
DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
BT_BOOL, BT_LONG, BT_LONG, BT_LONG,
BT_PTR_LONG, BT_PTR_LONG)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I1_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I2_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I4_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I8_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I16_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_INT, BT_INT)
-
DEF_FUNCTION_TYPE_6 (BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG,
BT_INT, BT_STRING, BT_SIZE, BT_INT, BT_SIZE,
--- 437,442 ----
*************** DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PT
*** 461,466 ****
--- 450,471 ----
DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
+ BT_INT)
+
DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
Index: sync-builtins.def
===================================================================
*** sync-builtins.def (revision 180092)
--- sync-builtins.def (working copy)
*************** DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPAR
*** 302,320 ****
BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1,
"__atomic_compare_exchange_1",
! BT_FN_BOOL_VPTR_PTR_I1_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2,
"__atomic_compare_exchange_2",
! BT_FN_BOOL_VPTR_PTR_I2_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
"__atomic_compare_exchange_4",
! BT_FN_BOOL_VPTR_PTR_I4_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
"__atomic_compare_exchange_8",
! BT_FN_BOOL_VPTR_PTR_I8_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16,
"__atomic_compare_exchange_16",
! BT_FN_BOOL_VPTR_PTR_I16_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_N,
"__atomic_store",
--- 302,320 ----
BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1,
"__atomic_compare_exchange_1",
! BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2,
"__atomic_compare_exchange_2",
! BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
"__atomic_compare_exchange_4",
! BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
"__atomic_compare_exchange_8",
! BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16,
"__atomic_compare_exchange_16",
! BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_N,
"__atomic_store",
Index: c-family/c-common.c
===================================================================
*** c-family/c-common.c (revision 180092)
--- c-family/c-common.c (working copy)
*************** resolve_overloaded_builtin (location_t l
*** 9197,9202 ****
--- 9197,9204 ----
first_param = VEC_index (tree, params, 0);
result = build_function_call_vec (loc, new_function, params, NULL);
+ if (result == error_mark_node)
+ return result;
if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
&& orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N
&& orig_code != BUILT_IN_ATOMIC_STORE_N)
Index: fortran/types.def
===================================================================
*** fortran/types.def (revision 180092)
--- fortran/types.def (working copy)
*************** DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD
*** 158,173 ****
DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
BT_BOOL, BT_LONG, BT_LONG, BT_LONG,
BT_PTR_LONG, BT_PTR_LONG)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I1_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I2_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I4_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I8_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_INT, BT_INT)
- DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I16_INT_INT,
- BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_INT, BT_INT)
DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
BT_BOOL, BT_LONG, BT_LONG, BT_LONG, BT_LONG,
--- 158,163 ----
*************** DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PT
*** 178,183 ****
--- 168,188 ----
DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
+ BT_INT)
+ DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
+ BT_INT)
DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
Index: testsuite/gcc.dg/atomic-invalid.c
===================================================================
*** testsuite/gcc.dg/atomic-invalid.c (revision 180092)
--- testsuite/gcc.dg/atomic-invalid.c (working copy)
***************
*** 5,15 ****
#include <stddef.h>
! int i;
size_t s;
main ()
{
__atomic_exchange (&i, 1, __ATOMIC_CONSUME); /* { dg-error "invalid memory
model" } */
__atomic_load (&i, __ATOMIC_RELEASE); /* { dg-error "invalid memory model"
} */
--- 5,20 ----
#include <stddef.h>
! int i, e, b;
size_t s;
main ()
{
+ __atomic_compare_exchange (&i, &e, 1, 0, __ATOMIC_RELAXED,
__ATOMIC_SEQ_CST); /* { dg-error "failure memory model cannot be stronger" } */
+ __atomic_compare_exchange (&i, &e, 1, 0, __ATOMIC_SEQ_CST,
__ATOMIC_RELEASE); /* { dg-error "invalid failure memory" } */
+ __atomic_compare_exchange (&i, &e, 1, 1, __ATOMIC_SEQ_CST,
__ATOMIC_ACQ_REL); /* { dg-error "invalid failure memory" } */
+ __atomic_compare_exchange (&i, &e, 1, b, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST); /* { dg-error "strong/weak parameter" } */
+
__atomic_exchange (&i, 1, __ATOMIC_CONSUME); /* { dg-error "invalid memory
model" } */
__atomic_load (&i, __ATOMIC_RELEASE); /* { dg-error "invalid memory model"
} */
Index: testsuite/gcc.dg/atomic-compare-exchange-1.c
===================================================================
*** testsuite/gcc.dg/atomic-compare-exchange-1.c (revision 0)
--- testsuite/gcc.dg/atomic-compare-exchange-1.c (revision 0)
***************
*** 0 ****
--- 1,51 ----
+ /* Test __atomic routines for existence and proper execution on 1 byte
+ values with each valid memory model. */
+ /* { dg-do run } */
+ /* { dg-require-effective-target sync_char_short } */
+
+ /* Test the execution of the __atomic_compare_exchange builtin for a char. */
+
+ extern void abort(void);
+
+ char v = 0;
+ char expected = 0;
+ char max = ~0;
+ char desired = ~0;
+
+ #define STRONG 0
+ #define WEAK 1
+
+ main ()
+ {
+
+ if (!__atomic_compare_exchange (&v, &expected, max, STRONG ,
__ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, 0, STRONG ,
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, desired, WEAK,
__ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, desired, STRONG ,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+ }
Index: testsuite/gcc.dg/atomic-compare-exchange-2.c
===================================================================
*** testsuite/gcc.dg/atomic-compare-exchange-2.c (revision 0)
--- testsuite/gcc.dg/atomic-compare-exchange-2.c (revision 0)
***************
*** 0 ****
--- 1,51 ----
+ /* Test __atomic routines for existence and proper execution on 2 byte
+ values with each valid memory model. */
+ /* { dg-do run } */
+ /* { dg-require-effective-target sync_char_short } */
+
+ /* Test the execution of the __atomic_compare_exchange builtin for a short.
*/
+
+ extern void abort(void);
+
+ short v = 0;
+ short expected = 0;
+ short max = ~0;
+ short desired = ~0;
+
+ #define STRONG 0
+ #define WEAK 1
+
+ main ()
+ {
+
+ if (!__atomic_compare_exchange (&v, &expected, max, STRONG ,
__ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, 0, STRONG ,
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, desired, WEAK,
__ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, desired, STRONG ,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+ }
Index: testsuite/gcc.dg/atomic-compare-exchange-3.c
===================================================================
*** testsuite/gcc.dg/atomic-compare-exchange-3.c (revision 0)
--- testsuite/gcc.dg/atomic-compare-exchange-3.c (revision 0)
***************
*** 0 ****
--- 1,51 ----
+ /* Test __atomic routines for existence and proper execution on 4 byte
+ values with each valid memory model. */
+ /* { dg-do run } */
+ /* { dg-require-effective-target sync_int_long } */
+
+ /* Test the execution of the __atomic_compare_exchange builtin for an int. */
+
+ extern void abort(void);
+
+ int v = 0;
+ int expected = 0;
+ int max = ~0;
+ int desired = ~0;
+
+ #define STRONG 0
+ #define WEAK 1
+
+ main ()
+ {
+
+ if (!__atomic_compare_exchange (&v, &expected, max, STRONG ,
__ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, 0, STRONG ,
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, desired, WEAK,
__ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, desired, STRONG ,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+ }
Index: testsuite/gcc.dg/atomic-compare-exchange-4.c
===================================================================
*** testsuite/gcc.dg/atomic-compare-exchange-4.c (revision 0)
--- testsuite/gcc.dg/atomic-compare-exchange-4.c (revision 0)
***************
*** 0 ****
--- 1,52 ----
+ /* Test __atomic routines for existence and proper execution on 8 byte
+ values with each valid memory model. */
+ /* { dg-do run } */
+ /* { dg-require-effective-target sync_long_long } */
+ /* { dg-options "" } */
+
+ /* Test the execution of __atomic_compare_exchange builtin for a long_long.
*/
+
+ extern void abort(void);
+
+ long long v = 0;
+ long long expected = 0;
+ long long max = ~0;
+ long long desired = ~0;
+
+ #define STRONG 0
+ #define WEAK 1
+
+ main ()
+ {
+
+ if (!__atomic_compare_exchange (&v, &expected, max, STRONG ,
__ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, 0, STRONG ,
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, desired, WEAK,
__ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, desired, STRONG ,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+ }
Index: testsuite/gcc.dg/atomic-compare-exchange-5.c
===================================================================
*** testsuite/gcc.dg/atomic-compare-exchange-5.c (revision 0)
--- testsuite/gcc.dg/atomic-compare-exchange-5.c (revision 0)
***************
*** 0 ****
--- 1,52 ----
+ /* Test __atomic routines for existence and proper execution on 16 byte
+ values with each valid memory model. */
+ /* { dg-do run } */
+ /* { dg-require-effective-target sync_int_128 } */
+ /* { dg-options "-mcx16" { target { x86_64-*-* } } } */
+
+ /* Test the execution of __atomic_compare_exchange builtin for an int_128. */
+
+ extern void abort(void);
+
+ __int128_t v = 0;
+ __int128_t expected = 0;
+ __int128_t max = ~0;
+ __int128_t desired = ~0;
+
+ #define STRONG 0
+ #define WEAK 1
+
+ main ()
+ {
+
+ if (!__atomic_compare_exchange (&v, &expected, max, STRONG ,
__ATOMIC_RELAXED, __ATOMIC_RELAXED))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
+ abort ();
+ if (expected != max)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, 0, STRONG ,
__ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != max)
+ abort ();
+ if (v != 0)
+ abort ();
+
+ if (__atomic_compare_exchange (&v, &expected, desired, WEAK,
__ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
+ abort ();
+ if (expected != 0)
+ abort ();
+
+ if (!__atomic_compare_exchange (&v, &expected, desired, STRONG ,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
+ abort ();
+ if (expected != 0)
+ abort ();
+ if (v != max)
+ abort ();
+
+ return 0;
+ }