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

Reply via email to