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;
+ }

Reply via email to