OK, here's the updated patch.
I also made the changes to the C++ include files to use
__atomic_compare_exchange in the header file.
I think I covered everything that was mentioned previously...
Bootstraps and no new regressions on x86_64-unknown-linux-gnu.
Andrew
* optabs.h (direct_optab_index): Replace DOI_atomic_compare_exchange
with DOI_atomic_compare_and_swap.
(direct_op): Add DOI_atomic_compare_and_swap.
* genopinit.c: Set atomic_compare_and_swap_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): Use atomic_compare_and_swap
if present, 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.
* libstdc++-v3/include/bits/atomic_2.h: Use __atomic_compare_exchange.
* 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: gcc/optabs.h
===================================================================
*** gcc/optabs.h (revision 180092)
--- gcc/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,696 ----
/* Atomic operations with memory model parameters. */
DOI_atomic_exchange,
! DOI_atomic_compare_and_swap,
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 \
--- 765,772 ----
#define atomic_exchange_optab \
(&direct_optab_table[(int) DOI_atomic_exchange])
! #define atomic_compare_and_swap_optab \
! (&direct_optab_table[(int) DOI_atomic_compare_and_swap])
#define atomic_load_optab \
(&direct_optab_table[(int) DOI_atomic_load])
#define atomic_store_optab \
Index: gcc/genopinit.c
===================================================================
*** gcc/genopinit.c (revision 180092)
--- gcc/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,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_and_swap_optab, $A,
CODE_FOR_$(atomic_compare_and_swap$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: gcc/expr.h
===================================================================
*** gcc/expr.h (revision 180092)
--- gcc/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: gcc/builtins.c
===================================================================
*** gcc/builtins.c (revision 180092)
--- gcc/builtins.c (working copy)
*************** expand_builtin_atomic_exchange (enum mac
*** 5283,5302 ****
/* Expand the __atomic_compare_exchange intrinsic:
bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
! TYPE desired, enum memmodel success,
! enum memmodel failure)
EXP is the CALL_EXPR.
TARGET is an optional place for us to store the results. */
static rtx
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)
{
--- 5283,5303 ----
/* Expand the __atomic_compare_exchange intrinsic:
bool __atomic_compare_exchange (TYPE *object, TYPE *expect,
! TYPE desired, BOOL weak,
! enum memmodel success,
! enum memmodel failure)
EXP is the CALL_EXPR.
TARGET is an optional place for us to store the results. */
static rtx
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:
--- 5320,5330 ----
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);
!
! return expand_atomic_compare_exchange (target, mem, expect, desired, weak,
! success, failure);
}
/* Expand the __atomic_load intrinsic:
Index: gcc/optabs.c
===================================================================
*** gcc/optabs.c (revision 180092)
--- gcc/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,7104 ----
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));
! icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
!
if (icode != CODE_FOR_nothing)
{
! struct expand_operand ops[8];
! rtx original_val = gen_reg_rtx (mode);
! enum machine_mode target_mode;
! int is_weak;
! target_mode = insn_data[icode].operand[0].mode;
+ /* Either WEAK is explcitly 1, or assume strong to be safe. */
+ is_weak = (weak == const1_rtx);
! if (target == NULL_RTX || target == const0_rtx
! || GET_MODE (target) != target_mode)
! target = gen_reg_rtx (target_mode);
! /* Emit the compare_and_swap. */
! create_output_operand (&ops[0], target, target_mode);
! create_output_operand (&ops[1], original_val, mode);
! create_fixed_operand (&ops[2], mem);
! create_convert_operand_to (&ops[3], expected_val, mode, true);
! create_convert_operand_to (&ops[4], desired, mode, true);
! create_integer_operand (&ops[5], is_weak);
! create_integer_operand (&ops[6], success);
! create_integer_operand (&ops[7], failure);
! expand_insn (icode, 8, ops);
! /* Store *expected = original_val */
! emit_move_insn (gen_rtx_MEM (mode, expected), original_val);
! /* 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: gcc/builtin-types.def
===================================================================
*** gcc/builtin-types.def (revision 180092)
--- gcc/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: gcc/sync-builtins.def
===================================================================
*** gcc/sync-builtins.def (revision 180092)
--- gcc/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: gcc/c-family/c-common.c
===================================================================
*** gcc/c-family/c-common.c (revision 180092)
--- gcc/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: libstdc++-v3/include/bits/atomic_2.h
===================================================================
*** libstdc++-v3/include/bits/atomic_2.h (revision 180092)
--- libstdc++-v3/include/bits/atomic_2.h (working copy)
*************** namespace __atomic2
*** 289,301 ****
bool
compare_exchange_weak(__int_type& __i1, __int_type __i2,
memory_order __m1, memory_order __m2) noexcept
! { return compare_exchange_strong(__i1, __i2, __m1, __m2); }
bool
compare_exchange_weak(__int_type& __i1, __int_type __i2,
memory_order __m1,
memory_order __m2) volatile noexcept
! { return compare_exchange_strong(__i1, __i2, __m1, __m2); }
bool
compare_exchange_weak(__int_type& __i1, __int_type __i2,
--- 289,313 ----
bool
compare_exchange_weak(__int_type& __i1, __int_type __i2,
memory_order __m1, memory_order __m2) noexcept
! {
! __glibcxx_assert(__m2 != memory_order_release);
! __glibcxx_assert(__m2 != memory_order_acq_rel);
! __glibcxx_assert(__m2 <= __m1);
!
! return __atomic_compare_exchange (&_M_i, &__i1, __i2, 1, __m1, __m2);
! }
bool
compare_exchange_weak(__int_type& __i1, __int_type __i2,
memory_order __m1,
memory_order __m2) volatile noexcept
! {
! __glibcxx_assert(__m2 != memory_order_release);
! __glibcxx_assert(__m2 != memory_order_acq_rel);
! __glibcxx_assert(__m2 <= __m1);
!
! return __atomic_compare_exchange (&_M_i, &__i1, __i2, 1, __m1, __m2);
! }
bool
compare_exchange_weak(__int_type& __i1, __int_type __i2,
*************** namespace __atomic2
*** 321,333 ****
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! __int_type __i1o = __i1;
! // Compare_and_swap is a full barrier already.
! __int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2);
!
! // Assume extra stores (of same value) allowed in true case.
! __i1 = __i1n;
! return __i1o == __i1n;
}
bool
--- 333,339 ----
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! return __atomic_compare_exchange (&_M_i, &__i1, __i2, 0, __m1, __m2);
}
bool
*************** namespace __atomic2
*** 339,351 ****
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! __int_type __i1o = __i1;
! // Compare_and_swap is a full barrier already.
! __int_type __i1n = __sync_val_compare_and_swap(&_M_i, __i1o, __i2);
!
! // Assume extra stores (of same value) allowed in true case.
! __i1 = __i1n;
! return __i1o == __i1n;
}
bool
--- 345,351 ----
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! return __atomic_compare_exchange (&_M_i, &__i1, __i2, 0, __m1, __m2);
}
bool
*************** namespace __atomic2
*** 575,587 ****
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! __pointer_type __p1o = __p1;
! // Compare_and_swap is a full barrier already.
! __pointer_type __p1n = __sync_val_compare_and_swap(&_M_p, __p1o, __p2);
!
! // Assume extra stores (of same value) allowed in true case.
! __p1 = __p1n;
! return __p1o == __p1n;
}
bool
--- 575,581 ----
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! return __atomic_compare_exchange (&_M_p, &__p1, __p2, 0, __m1, __m2);
}
bool
*************** namespace __atomic2
*** 593,605 ****
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! __pointer_type __p1o = __p1;
! // Compare_and_swap is a full barrier already.
! __pointer_type __p1n = __sync_val_compare_and_swap(&_M_p, __p1o, __p2);
!
! // Assume extra stores (of same value) allowed in true case.
! __p1 = __p1n;
! return __p1o == __p1n;
}
__pointer_type
--- 587,593 ----
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
! return __atomic_compare_exchange (&_M_p, &__p1, __p2, 0, __m1, __m2);
}
__pointer_type
Index: gcc/fortran/types.def
===================================================================
*** gcc/fortran/types.def (revision 180092)
--- gcc/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: gcc/testsuite/gcc.dg/atomic-invalid.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-invalid.c (revision 180092)
--- gcc/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,19 ----
#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_exchange (&i, 1, __ATOMIC_CONSUME); /* { dg-error "invalid memory
model" } */
__atomic_load (&i, __ATOMIC_RELEASE); /* { dg-error "invalid memory model"
} */
Index: gcc/testsuite/gcc.dg/atomic-compare-exchange-1.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-compare-exchange-1.c (revision 0)
--- gcc/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: gcc/testsuite/gcc.dg/atomic-compare-exchange-2.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-compare-exchange-2.c (revision 0)
--- gcc/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: gcc/testsuite/gcc.dg/atomic-compare-exchange-3.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-compare-exchange-3.c (revision 0)
--- gcc/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: gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-compare-exchange-4.c (revision 0)
--- gcc/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: gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-compare-exchange-5.c (revision 0)
--- gcc/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;
+ }