public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [cxx-mem-model]  __sync_mem builtin support patch 2/3 - code
@ 2011-07-27  5:31 Andrew MacLeod
  2011-07-27 16:14 ` Richard Henderson
  0 siblings, 1 reply; 4+ messages in thread
From: Andrew MacLeod @ 2011-07-27  5:31 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Henderson, Aldy Hernandez

[-- Attachment #1: Type: text/plain, Size: 1278 bytes --]

This is the main patch which implements all the code for the new 
__sync_mem routines which take a memory model as a parameter.

I used the previously approved and checked in __sync_mem_exchange 
routine as the model and added all the rest. The only difference is I'm 
not adding the x86 patterns yet. I decided to implement just the generic 
routines first so that we will know they all pass the tests on their 
own. Then we'll get the target specific patterns for x86, ppc, arm and 
whatever else people are worried about seperately..

Once these are in place, the c++ atomic.h wrappers can be changed to use 
them as and we'll finally have C++0x support.

A couple of caveats.

  * __sync_mem_compare_exchange has the skeleton in place, but not the 
guts.  There are some issues that rth and I will work out later, I just 
don't want to hold up the rest of the patch for that. Right now it will 
fail the compare_exchange tests.

  * I will revisit exactly where synchronization fences need to be 
issued for each of these routines later as well. This is a first cut and 
again I want to get the code into the codebase so other things can get 
started. Fine tuning can be made later.

Bootstraps on x86-64-unknown-linux-gnu and causes no new regression.

Ok for the branch?


[-- Attachment #2: code.patch --]
[-- Type: text/plain, Size: 53593 bytes --]



	* expr.h (expand_sync_mem_exchange): Change parameter order.
	(expand_sync_mem_*): New prototypes.
	* optabs.h (DOI_sync_mem_*): Add new optable enums.
	(sync_mem_*_optab): Add new #defines for table entries.
	* genopinit.c (const optabs[]): Add direct optab handlers.
	* optabs.c (expand_sync_mem_exchange): Change parameter order, and use
	mem_thread_fence if it exists.
	(expand_sync_mem_compare_exchange, expand_sync_mem_load,
	expand_sync_mem_store, expand_sync_mem_fetch_op): New. Expand
	__sync_mem functions which handle multiple integral types.
	* builtins.c (maybe_convert_modes): New. Factor out common code for
	ensuring an integer argument is in the proper mode.
	(expand_builtin_sync_operation, expand_builtin_compare_and_swap,
	expand_builtin_sync_lock_test_and_set): Use maybe_convert_modes.
	(expand_builtin_sync_lock_release): Relocate higher in the file.
	(get_memmodel): Don't assume the memmodel is the 3rd argument.
	(expand_builtin_sync_mem_exchange): Change error check and use
	maybe_convert_modes.
	(expand_builtin_sync_mem_compare_exchange): New.
	(expand_builtin_sync_mem_load, expand_builtin_sync_mem_store): New.
	(expand_builtin_sync_mem_fetch_op): New.
	(expand_builtin_sync_mem_flag_test_and_set): New.
	(expand_builtin_sync_mem_flag_clear): New.
	(expand_builtin_sync_mem_thread_fence): New.
	(expand_builtin_sync_mem_signal_fence): New.
	(expand_builtin): Handle BUILT_IN_SYNC_MEM_* types.
	* c-family/c-common.c (resolve_overloaded_builtin): Handle
	BUILT_IN_SYNC_MEM_* types.
	* builtin-types.def (BT_FN_I{1,2,4,8,16}_VPTR_INT): New builtin type.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT): New builtin types.
	(BT_FN_VOID_VPTR_I{1,2,4,8,16}_INT: New builtin type.
	(BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_INT_INT): New builtin type.
	* fortran/types.def (BT_FN_VOID_INT): New type.
	(BT_FN_I{1,2,4,8,16}_VPTR_INT): New builtin type.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT): New builtin types.
	(BT_FN_VOID_VPTR_I{1,2,4,8,16}_INT: New builtin type.
	(BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_INT_INT): New builtin type.
	* sync-builtins.def (BUILT_IN_SYNC_MEM_*): New sync builtins.

Index: expr.h
===================================================================
*** expr.h	(revision 175331)
--- expr.h	(working copy)
*************** rtx expand_bool_compare_and_swap (rtx, r
*** 217,223 ****
  rtx expand_sync_operation (rtx, rtx, enum rtx_code);
  rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
  rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
! rtx expand_sync_mem_exchange (enum memmodel, rtx, rtx, rtx);
  \f
  /* Functions from expmed.c:  */
  
--- 217,234 ----
  rtx expand_sync_operation (rtx, rtx, enum rtx_code);
  rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
  rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
! 
! rtx expand_sync_mem_exchange (rtx, rtx, rtx, enum memmodel);
! rtx expand_sync_mem_compare_exchange (rtx, rtx, rtx, rtx, enum memmodel, 
! 				      enum memmodel);
! rtx expand_sync_mem_load (rtx, rtx, enum memmodel);
! void expand_sync_mem_store (rtx, rtx, enum memmodel);
! rtx expand_sync_mem_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel);
! rtx expand_sync_mem_flag_test_and_set (rtx, rtx, enum memmodel);
! void expand_sync_mem_flag_clear (rtx, enum memmodel);
! void expand_sync_mem_thread_fence (enum memmodel);
! void expand_sync_mem_signal_fence (enum memmodel);
! 
  \f
  /* Functions from expmed.c:  */
  
Index: optabs.h
===================================================================
*** optabs.h	(revision 175331)
--- optabs.h	(working copy)
*************** enum direct_optab_index
*** 679,684 ****
--- 679,696 ----
  
    /* Atomic operations with C++0x memory model parameters. */
    DOI_sync_mem_exchange,
+   DOI_sync_mem_compare_exchange,
+   DOI_sync_mem_load,
+   DOI_sync_mem_store,
+   DOI_sync_mem_fetch_add,
+   DOI_sync_mem_fetch_sub,
+   DOI_sync_mem_fetch_and,
+   DOI_sync_mem_fetch_xor,
+   DOI_sync_mem_fetch_or,
+   DOI_sync_mem_flag_test_and_set,
+   DOI_sync_mem_flag_clear,
+   DOI_sync_mem_thread_fence,
+   DOI_sync_mem_signal_fence,
  
    DOI_MAX
  };
*************** typedef struct direct_optab_d *direct_op
*** 730,735 ****
--- 742,771 ----
  
  #define sync_mem_exchange_optab \
    (&direct_optab_table[(int) DOI_sync_mem_exchange])
+ #define sync_mem_compare_exchange_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_compare_exchange])
+ #define sync_mem_load_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_load])
+ #define sync_mem_store_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_store])
+ #define sync_mem_fetch_add_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_add])
+ #define sync_mem_fetch_sub_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_sub])
+ #define sync_mem_fetch_and_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_and])
+ #define sync_mem_fetch_xor_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_xor])
+ #define sync_mem_fetch_or_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_or])
+ #define sync_mem_flag_test_and_set_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_flag_test_and_set])
+ #define sync_mem_flag_clear_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_flag_clear])
+ #define sync_mem_thread_fence_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_thread_fence])
+ #define sync_mem_signal_fence_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_signal_fence])
  \f
  /* Target-dependent globals.  */
  struct target_optabs {
Index: genopinit.c
===================================================================
*** genopinit.c	(revision 175331)
--- genopinit.c	(working copy)
*************** static const char * const optabs[] =
*** 242,247 ****
--- 242,255 ----
    "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 (sync_mem_exchange_optab, $A, CODE_FOR_$(sync_mem_exchange$I$a$))",
+   "set_direct_optab_handler (sync_mem_compare_exchange_optab, $A, CODE_FOR_$(sync_mem_compare_exchange$I$a$))",
+   "set_direct_optab_handler (sync_mem_load_optab, $A, CODE_FOR_$(sync_mem_load$I$a$))",
+   "set_direct_optab_handler (sync_mem_store_optab, $A, CODE_FOR_$(sync_mem_store$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_add_optab, $A, CODE_FOR_$(sync_mem_fetch_add$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_sub_optab, $A, CODE_FOR_$(sync_mem_fetch_sub$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_and_optab, $A, CODE_FOR_$(sync_mem_fetch_and$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_xor_optab, $A, CODE_FOR_$(sync_mem_fetch_xor$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_or_optab, $A, CODE_FOR_$(sync_mem_fetch_or$I$a$))",
    "set_optab_handler (vec_set_optab, $A, CODE_FOR_$(vec_set$a$))",
    "set_optab_handler (vec_extract_optab, $A, CODE_FOR_$(vec_extract$a$))",
    "set_optab_handler (vec_extract_even_optab, $A, CODE_FOR_$(vec_extract_even$a$))",
Index: optabs.c
===================================================================
*** optabs.c	(revision 175331)
--- optabs.c	(working copy)
*************** expand_sync_lock_test_and_set (rtx mem, 
*** 7064,7070 ****
     TARGET is an option place to stick the return value.  */
  
  rtx
! expand_sync_mem_exchange (enum memmodel model, rtx mem, rtx val, rtx target)
  {
    enum machine_mode mode = GET_MODE (mem);
    enum insn_code icode;
--- 7064,7070 ----
     TARGET is an option place to stick the return value.  */
  
  rtx
! expand_sync_mem_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
  {
    enum machine_mode mode = GET_MODE (mem);
    enum insn_code icode;
*************** expand_sync_mem_exchange (enum memmodel 
*** 7092,7101 ****
--- 7092,7343 ----
    icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
    if ((icode != CODE_FOR_nothing) && (model == MEMMODEL_SEQ_CST || 
  				     model == MEMMODEL_ACQ_REL))
+ #ifdef HAVE_sync_mem_thread_fence
+     emit_mem_thread_fence (model);
+ #else
      expand_builtin_sync_synchronize ();
+ #endif
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
+ 
+ /* This function expands the atomic compare exchange operation:
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ rtx
+ expand_sync_mem_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 (sync_mem_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.  */
+ 
+ #ifdef HAVE_sync_mem_thread_fence
+     emit_mem_thread_fence (success);
+ #else
+     expand_builtin_sync_synchronize ();
+ #endif
+   
+   /* 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; */
+ 
+ #ifdef HAVE_sync_mem_thread_fence
+     emit_mem_thread_fence (success);
+ #else
+     expand_builtin_sync_synchronize ();
+ #endif
+ 
+   return target;
+ #endif
+ }
+ 
+ 
+ /* This function expands the atomic load operation:
+    return the atomically loaded value in MEM.
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ rtx
+ expand_sync_mem_load (rtx target, rtx mem, enum memmodel model)
+ {
+   enum machine_mode mode = GET_MODE (mem);
+   enum insn_code icode;
+ 
+   /* If the target supports the load directly, great.  */
+   icode = direct_optab_handler (sync_mem_load_optab, mode);
+   if (icode != CODE_FOR_nothing)
+     {
+       struct expand_operand ops[3];
+ 
+       create_output_operand (&ops[0], target, mode);
+       create_fixed_operand (&ops[1], mem);
+       create_integer_operand (&ops[2], model);
+       if (maybe_expand_insn (icode, 3, ops))
+ 	return ops[0].value;
+     }
+ 
+   /* If there is no load, default to a move with barriers. */
+   if (target == const0_rtx)
+     target = gen_reg_rtx (mode);
+ 
+   /* Emit the appropriate barrier before the load.  */
+ #ifdef HAVE_sync_mem_thread_fence
+   emit_mem_thread_fence (model);
+ #else
+   if (model != MEMMODEL_RELAXED)
+     expand_builtin_sync_synchronize ();
+ #endif
+ 
+   emit_move_insn (target, mem);
+ 
+   /* For SEQ_CST, also emit a barrier after the load.  */
+   if (model == MEMMODEL_SEQ_CST)
+ #ifdef HAVE_sync_mem_thread_fence
+     emit_mem_thread_fence (model);
+ #else
+     expand_builtin_sync_synchronize ();
+ #endif
+ 
+   return target;
+ }
+ 
+ /* This function expands the atomic load operation:
+    return the atomically loaded value in MEM.
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ void
+ expand_sync_mem_store (rtx mem, rtx val, enum memmodel model)
+ {
+   enum machine_mode mode = GET_MODE (mem);
+   enum insn_code icode;
+ 
+   /* If the target supports the store directly, great.  */
+   icode = direct_optab_handler (sync_mem_store_optab, mode);
+   if (icode != CODE_FOR_nothing)
+     {
+       struct expand_operand ops[3];
+ 
+       create_output_operand (&ops[0], mem, mode);
+       create_fixed_operand (&ops[1], val);
+       create_integer_operand (&ops[2], model);
+       if (maybe_expand_insn (icode, 3, ops))
+ 	return;
+     }
+ 
+   /* If there is no mem_store, default to a move with barriers */
+ 
+   if (model == MEMMODEL_SEQ_CST)
+ #ifdef HAVE_sync_mem_thread_fence
+     emit_mem_thread_fence (model);
+ #else
+     expand_builtin_sync_synchronize ();
+ #endif
+ 
+   emit_move_insn (mem, val);
+ 
+   /* For SEQ_CST, also emit a barrier after the load.  */
+ #ifdef HAVE_sync_mem_thread_fence
+   emit_mem_thread_fence (model);
+ #else
+   if (model != MEMMODEL_RELAXED)
+     expand_builtin_sync_synchronize ();
+ #endif
+ }
+ 
+ /* This function expands an atomic fetch_OP operation:
+    CODE is the operation to be performed.
+    atomically fetch MEM, perform the operation with VAL and return it to MEM.
+    return the previous value of MEM.
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ rtx
+ expand_sync_mem_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
+ 			  enum memmodel model)
+ {
+   enum machine_mode mode = GET_MODE (mem);
+   enum insn_code icode;
+ 
+   switch (code)
+     {
+       case PLUS:
+         icode = direct_optab_handler (sync_mem_fetch_add_optab, mode);
+         break;
+       case MINUS:
+         icode = direct_optab_handler (sync_mem_fetch_sub_optab, mode);
+         break;
+       case AND:
+         icode = direct_optab_handler (sync_mem_fetch_and_optab, mode);
+         break;
+       case XOR:
+         icode = direct_optab_handler (sync_mem_fetch_xor_optab, mode);
+         break;
+       case IOR:
+         icode = direct_optab_handler (sync_mem_fetch_or_optab, mode);
+         break;
+       default:
+         icode = CODE_FOR_nothing;
+     }
+ 
+   /* If the target supports the operation directly, great.  */
+   if (icode != CODE_FOR_nothing)
+     {
+       struct expand_operand ops[4];
+ 
+       create_output_operand (&ops[0], target, mode);
+       create_fixed_operand (&ops[1], mem);
+       /* VAL may have been promoted to a wider mode.  Shrink it if so.  */
+       create_convert_operand_to (&ops[2], val, mode, true);
+       create_integer_operand (&ops[3], model);
+       if (maybe_expand_insn (icode, 4, ops))
+ 	return ops[0].value;
+     }
+ 
+ #ifdef HAVE_sync_mem_thread_fence
+     emit_mem_thread_fence (model);
+ #else
+     if (model != MEMMODEL_RELAXED)
+       expand_builtin_sync_synchronize ();
+ #endif
+ 
+    target = expand_sync_fetch_operation (mem, val, code, false, target);
+ 
+ #ifdef HAVE_sync_mem_thread_fence
+     emit_mem_thread_fence (model);
+ #else
+     if (model != MEMMODEL_RELAXED)
+       expand_builtin_sync_synchronize ();
+ #endif
+   return target;
+ }
+ 
+ 
  \f
  /* Return true if OPERAND is suitable for operand number OPNO of
     instruction ICODE.  */
Index: builtins.c
===================================================================
*** builtins.c	(revision 175331)
--- builtins.c	(working copy)
*************** get_builtin_sync_mem (tree loc, enum mac
*** 5057,5062 ****
--- 5057,5084 ----
    return mem;
  }
  
+ /* Make sure an argument is in the right mode.
+    EXP is the tree argument. 
+    MODE is the mode it should be in.  */
+ 
+ static rtx
+ maybe_convert_modes (tree exp, enum machine_mode mode)
+ {
+   rtx val;
+   enum machine_mode old_mode;
+ 
+   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
+   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
+      of CONST_INTs, where we know the old_mode only from the call argument.  */
+ 
+   old_mode = GET_MODE (val);
+   if (old_mode == VOIDmode)
+     old_mode = TYPE_MODE (TREE_TYPE (exp));
+   val = convert_modes (mode, old_mode, val, 1);
+   return val;
+ }
+ 
+ 
  /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
     EXP is the CALL_EXPR.  CODE is the rtx code
     that corresponds to the arithmetic or logical operation from the name;
*************** expand_builtin_sync_operation (enum mach
*** 5071,5077 ****
  			       rtx target, bool ignore)
  {
    rtx val, mem;
-   enum machine_mode old_mode;
    location_t loc = EXPR_LOCATION (exp);
  
    if (code == NOT && warn_sync_nand)
--- 5093,5098 ----
*************** expand_builtin_sync_operation (enum mach
*** 5118,5131 ****
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
!   val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   val = convert_modes (mode, old_mode, val, 1);
  
    if (ignore)
      return expand_sync_operation (mem, val, code);
--- 5139,5145 ----
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = maybe_convert_modes (CALL_EXPR_ARG (exp, 1), mode);
  
    if (ignore)
      return expand_sync_operation (mem, val, code);
*************** expand_builtin_compare_and_swap (enum ma
*** 5143,5171 ****
  				 bool is_bool, rtx target)
  {
    rtx old_val, new_val, mem;
-   enum machine_mode old_mode;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
! 
!   old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
! 			 mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (old_val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   old_val = convert_modes (mode, old_mode, old_val, 1);
! 
!   new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
! 			 mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (new_val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
!   new_val = convert_modes (mode, old_mode, new_val, 1);
  
    if (is_bool)
      return expand_bool_compare_and_swap (mem, old_val, new_val, target);
--- 5157,5167 ----
  				 bool is_bool, rtx target)
  {
    rtx old_val, new_val, mem;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   old_val = maybe_convert_modes (CALL_EXPR_ARG (exp, 1), mode);
!   new_val = maybe_convert_modes (CALL_EXPR_ARG (exp, 2), mode);
  
    if (is_bool)
      return expand_bool_compare_and_swap (mem, old_val, new_val, target);
*************** expand_builtin_sync_lock_test_and_set (e
*** 5184,5204 ****
  				  rtx target)
  {
    rtx val, mem;
-   enum machine_mode old_mode;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   val = convert_modes (mode, old_mode, val, 1);
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
  
  /* Given an integer representing an ``enum memmodel'', verify its
     correctness and return the memory model enum.  */
  
--- 5180,5221 ----
  				  rtx target)
  {
    rtx val, mem;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = maybe_convert_modes (CALL_EXPR_ARG (exp, 1), mode);
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
  
+ /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
+ 
+ static void
+ expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
+ {
+   struct expand_operand ops[2];
+   enum insn_code icode;
+   rtx mem;
+ 
+   /* Expand the operands.  */
+   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
+ 
+   /* If there is an explicit operation in the md file, use it.  */
+   icode = direct_optab_handler (sync_lock_release_optab, mode);
+   if (icode != CODE_FOR_nothing)
+     {
+       create_fixed_operand (&ops[0], mem);
+       create_input_operand (&ops[1], const0_rtx, mode);
+       if (maybe_expand_insn (icode, 2, ops))
+ 	return;
+     }
+ 
+   /* Otherwise we can implement this operation by emitting a barrier
+      followed by a store of zero.  */
+   expand_builtin_sync_synchronize ();
+   emit_move_insn (mem, const0_rtx);
+ }
+ 
  /* Given an integer representing an ``enum memmodel'', verify its
     correctness and return the memory model enum.  */
  
*************** get_memmodel (tree exp)
*** 5209,5230 ****
  
    if (TREE_CODE (exp) != INTEGER_CST)
      {
!       error ("third argument to builtin is an invalid memory model");
!       return MEMMODEL_SEQ_CST;
      }
    op = expand_normal (exp);
    if (INTVAL (op) < 0 || INTVAL (op) >= MEMMODEL_LAST)
      {
!       error ("third argument to builtin is an invalid memory model");
!       return MEMMODEL_SEQ_CST;
      }
    return (enum memmodel) INTVAL (op);
  }
  
  /* Expand the __sync_mem_exchange intrinsic:
! 
!    	TYPE __sync_mem_exchange (TYPE *to, TYPE from, enum memmodel)
! 
     EXP is the CALL_EXPR.
     TARGET is an optional place for us to store the results.  */
  
--- 5226,5245 ----
  
    if (TREE_CODE (exp) != INTEGER_CST)
      {
!       error ("invalid memory model argument to builtin");
!       return MEMMODEL_RELAXED;
      }
    op = expand_normal (exp);
    if (INTVAL (op) < 0 || INTVAL (op) >= MEMMODEL_LAST)
      {
!       error ("invalid memory model argument to builtin");
!       return MEMMODEL_RELAXED;
      }
    return (enum memmodel) INTVAL (op);
  }
  
  /* Expand the __sync_mem_exchange intrinsic:
!    	TYPE __sync_mem_exchange (TYPE *object, TYPE desired, enum memmodel)
     EXP is the CALL_EXPR.
     TARGET is an optional place for us to store the results.  */
  
*************** static rtx
*** 5232,5246 ****
  expand_builtin_sync_mem_exchange (enum machine_mode mode, tree exp, rtx target)
  {
    rtx val, mem;
-   enum machine_mode old_mode;
    enum memmodel model;
  
    model = get_memmodel (CALL_EXPR_ARG (exp, 2));
!   if (model != MEMMODEL_RELAXED
!       && model != MEMMODEL_SEQ_CST
!       && model != MEMMODEL_ACQ_REL
!       && model != MEMMODEL_RELEASE
!       && model != MEMMODEL_ACQUIRE)
      {
        error ("invalid memory model for %<__sync_mem_exchange%>");
        return NULL_RTX;
--- 5247,5256 ----
  expand_builtin_sync_mem_exchange (enum machine_mode mode, tree exp, rtx target)
  {
    rtx val, mem;
    enum memmodel model;
  
    model = get_memmodel (CALL_EXPR_ARG (exp, 2));
!   if (model == MEMMODEL_CONSUME)
      {
        error ("invalid memory model for %<__sync_mem_exchange%>");
        return NULL_RTX;
*************** expand_builtin_sync_mem_exchange (enum m
*** 5248,5262 ****
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   val = convert_modes (mode, old_mode, val, 1);
  
!   return expand_sync_mem_exchange (model, mem, val, target);
  }
  
  /* Expand the __sync_synchronize intrinsic.  */
--- 5258,5461 ----
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = maybe_convert_modes (CALL_EXPR_ARG (exp, 1), mode);
! 
!   return expand_sync_mem_exchange (target, mem, val, model);
! }
! 
! /* Expand the __sync_mem_compare_exchange intrinsic:
!    	bool __sync_mem_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_sync_mem_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)
!     {
!       error ("invalid failure memory model for %<__sync_mem_compare_exchange%>");
!       return NULL_RTX;
!     }
! 
!   if (failure > success)
!     {
!       error ("failure memory model cannot be stronger than success memory model for %<__sync_mem_compare_exchange%>");
!       return NULL_RTX;
!     }
!   
!   /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
!   expect = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, ptr_mode, 
! 			EXPAND_NORMAL);
!   expect = convert_memory_address (Pmode, expect);
! 
!   desired = maybe_convert_modes (CALL_EXPR_ARG (exp, 2), mode);
! 
!   return expand_sync_mem_compare_exchange (target, mem, expect, desired, 
! 					   success, failure);
! }
! 
! /* Expand the __sync_mem_load intrinsic:
!    	TYPE __sync_mem_load (TYPE *object, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.  */
! 
! static rtx
! expand_builtin_sync_mem_load (enum machine_mode mode, tree exp, rtx target)
! {
!   rtx mem;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
!   if (model == MEMMODEL_RELEASE
!       || model == MEMMODEL_ACQ_REL)
!     {
!       error ("invalid memory model for %<__sync_mem_load%>");
!       return NULL_RTX;
!     }
! 
!   /* Expand the operand.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
!   return expand_sync_mem_load (target, mem, model);
! }
! 
! 
! /* Expand the __sync_mem_store intrinsic:
!    	void __sync_mem_store (TYPE *object, TYPE desired, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.  */
! 
! static void
! expand_builtin_sync_mem_store (enum machine_mode mode, tree exp)
! {
!   rtx mem, val;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
!   if (model != MEMMODEL_RELAXED
!       && model != MEMMODEL_SEQ_CST
!       && model != MEMMODEL_RELEASE)
!     {
!       error ("invalid memory model for %<__sync_mem_store%>");
!       return;
!     }
! 
!   /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = maybe_convert_modes (CALL_EXPR_ARG (exp, 1), mode);
! 
!   expand_sync_mem_store (mem, val, model);
! }
! 
! /* Expand the __sync_mem_fetch_XXX intrinsic:
!    	TYPE __sync_mem_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.
!    CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR. */
! 
! static rtx
! expand_builtin_sync_mem_fetch_op (enum machine_mode mode, tree exp, rtx target,
! 				  enum rtx_code code)
! {
!   rtx val, mem;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
! 
!   /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = maybe_convert_modes (CALL_EXPR_ARG (exp, 1), mode);
! 
!   return expand_sync_mem_fetch_op (target, mem, val, code, model);
! }
! 
! /* Expand the __sync_mem_flag_test_and_set intrinsic:
!    	bool __sync_mem_flag_test_and_set (char *object, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.  */
! 
! static rtx
! expand_builtin_sync_mem_flag_test_and_set (tree exp, rtx target)
! {
!   rtx mem;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
!   /* sync_lock_test_and_set is an acquire barrier, so a barrier may be needed
!      before.  */
! 
!   if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_ACQ_REL
!       || model == MEMMODEL_RELEASE)
!     expand_builtin_sync_synchronize ();
! 
!   /* Expand the operand.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), QImode);
! 
!   return expand_sync_lock_test_and_set (mem, const1_rtx, target);
! }
! 
! /* Expand the __sync_mem_flag_clear intrinsic:
!    	void __sync_mem_flag_clear (char *object, enum memmodel)
!    EXP is the CALL_EXPR.  */
! 
! static void
! expand_builtin_sync_mem_flag_clear (tree exp)
! {
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
! 
!   if (model == MEMMODEL_ACQUIRE || model == MEMMODEL_ACQ_REL)
!     {
!       error ("invalid memory model for %<__sync_mem_flag_clear%>");
!       return;
!     }
! 
!   expand_builtin_sync_lock_release (QImode, exp);
  
!   /* sync_lock_release is a release barrier, so we may need a seq-cst 
!      barrier afterwards.  */
!   if (model == MEMMODEL_SEQ_CST)
!     expand_builtin_sync_synchronize ();
! }
! 
! /* Expand the __sync_mem_thread_fence intrinsic:
!    	void __sync_mem_thread_fence (enum memmodel)
!    EXP is the CALL_EXPR.  */
! 
! static void
! expand_builtin_sync_mem_thread_fence (tree exp)
! {
!   enum memmodel model;
!   
!   model = get_memmodel (CALL_EXPR_ARG (exp, 0));
!   if (model != MEMMODEL_RELAXED)
!     expand_builtin_sync_synchronize ();
! }
! 
! /* Expand the __sync_mem_signal_fence intrinsic:
!    	void __sync_mem_signal_fence (enum memmodel)
!    EXP is the CALL_EXPR.  */
! 
! static void
! expand_builtin_sync_mem_signal_fence (tree exp)
! {
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 0));
!   if (model != MEMMODEL_RELAXED)
!    expand_builtin_sync_synchronize ();
  }
  
  /* Expand the __sync_synchronize intrinsic.  */
*************** expand_builtin_sync_synchronize (void)
*** 5291,5323 ****
    expand_asm_stmt (x);
  }
  
- /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
- 
- static void
- expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
- {
-   struct expand_operand ops[2];
-   enum insn_code icode;
-   rtx mem;
- 
-   /* Expand the operands.  */
-   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
- 
-   /* If there is an explicit operation in the md file, use it.  */
-   icode = direct_optab_handler (sync_lock_release_optab, mode);
-   if (icode != CODE_FOR_nothing)
-     {
-       create_fixed_operand (&ops[0], mem);
-       create_input_operand (&ops[1], const0_rtx, mode);
-       if (maybe_expand_insn (icode, 2, ops))
- 	return;
-     }
- 
-   /* Otherwise we can implement this operation by emitting a barrier
-      followed by a store of zero.  */
-   expand_builtin_sync_synchronize ();
-   emit_move_insn (mem, const0_rtx);
- }
  \f
  /* Expand an expression EXP that calls a built-in function,
     with result going to TARGET if that's convenient
--- 5490,5495 ----
*************** expand_builtin (tree exp, rtx target, rt
*** 6077,6093 ****
  	return target;
        break;
  
-     case BUILT_IN_SYNC_MEM_EXCHANGE_1:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_2:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_4:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_8:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_16:
-       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_EXCHANGE_1);
-       target = expand_builtin_sync_mem_exchange (mode, exp, target);
-       if (target)
- 	return target;
-       break;
- 
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
--- 6249,6254 ----
*************** expand_builtin (tree exp, rtx target, rt
*** 6112,6117 ****
--- 6273,6394 ----
        expand_builtin_sync_synchronize ();
        return const0_rtx;
  
+     case BUILT_IN_SYNC_MEM_EXCHANGE_1:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_2:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_4:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_8:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_EXCHANGE_1);
+       target = expand_builtin_sync_mem_exchange (mode, exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_1:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_2:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_4:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_8:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_16:
+       mode = 
+ 	  get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_1);
+       target = expand_builtin_sync_mem_compare_exchange (mode, exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_LOAD_1:
+     case BUILT_IN_SYNC_MEM_LOAD_2:
+     case BUILT_IN_SYNC_MEM_LOAD_4:
+     case BUILT_IN_SYNC_MEM_LOAD_8:
+     case BUILT_IN_SYNC_MEM_LOAD_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_LOAD_1);
+       target = expand_builtin_sync_mem_load (mode, exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_STORE_1:
+     case BUILT_IN_SYNC_MEM_STORE_2:
+     case BUILT_IN_SYNC_MEM_STORE_4:
+     case BUILT_IN_SYNC_MEM_STORE_8:
+     case BUILT_IN_SYNC_MEM_STORE_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_STORE_1);
+       expand_builtin_sync_mem_store (mode, exp);
+       return const0_rtx;
+ 
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_1:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_2:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_4:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_8:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_ADD_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, PLUS);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_1:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_2:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_4:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_8:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_SUB_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, MINUS);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_AND_1:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_2:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_4:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_8:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_AND_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, AND);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_1:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_2:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_4:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_8:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_XOR_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, XOR);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_OR_1:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_2:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_4:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_8:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_OR_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, IOR);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FLAG_TEST_AND_SET:
+       target = expand_builtin_sync_mem_flag_test_and_set (exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_FLAG_CLEAR:
+       expand_builtin_sync_mem_flag_clear (exp);
+       return const0_rtx;
+ 
+     case BUILT_IN_SYNC_MEM_THREAD_FENCE:
+       expand_builtin_sync_mem_thread_fence (exp);
+       return const0_rtx;
+ 
+     case BUILT_IN_SYNC_MEM_SIGNAL_FENCE:
+       expand_builtin_sync_mem_signal_fence (exp);
+       return const0_rtx;
+ 
      case BUILT_IN_OBJECT_SIZE:
        return expand_builtin_object_size (exp);
  
Index: c-family/c-common.c
===================================================================
*** c-family/c-common.c	(revision 175331)
--- c-family/c-common.c	(working copy)
*************** resolve_overloaded_builtin (location_t l
*** 9061,9066 ****
--- 9061,9074 ----
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_N:
      case BUILT_IN_SYNC_LOCK_RELEASE_N:
      case BUILT_IN_SYNC_MEM_EXCHANGE_N:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_N:
+     case BUILT_IN_SYNC_MEM_LOAD_N:
+     case BUILT_IN_SYNC_MEM_STORE_N:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_N:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_N:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_N:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_N:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_N:
        {
  	int n = sync_resolve_size (function, params);
  	tree new_function, first_param, result;
*************** resolve_overloaded_builtin (location_t l
*** 9075,9081 ****
  	first_param = VEC_index (tree, params, 0);
  	result = build_function_call_vec (loc, new_function, params, NULL);
  	if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
! 	    && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N)
  	  result = sync_resolve_return (first_param, result);
  
  	return result;
--- 9083,9090 ----
  	first_param = VEC_index (tree, params, 0);
  	result = build_function_call_vec (loc, new_function, params, NULL);
  	if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
! 	    && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N
! 	    && orig_code != BUILT_IN_SYNC_MEM_STORE_N)
  	  result = sync_resolve_return (first_param, result);
  
  	return result;
Index: builtin-types.def
===================================================================
*** builtin-types.def	(revision 175331)
--- builtin-types.def	(working copy)
*************** DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_LONGPTR_
*** 315,320 ****
--- 315,327 ----
  		     BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
  DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
  		     BT_BOOL, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_INT, BT_I1, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_INT, BT_I2, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_INT, BT_I4, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_INT, BT_I8, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_INT, BT_I16, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_INT, BT_VOID, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_VPTR_INT, BT_BOOL, BT_VOLATILE_PTR, BT_INT)
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_IN
*** 388,393 ****
--- 395,406 ----
  DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_INT, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_INT, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_INT, BT_I16, BT_VOLATILE_PTR, BT_I16, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I1_INT, BT_VOID, BT_VOLATILE_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT)
+ 
  
  DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
  		     BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
*************** DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_IN
*** 414,419 ****
--- 427,443 ----
  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,
Index: fortran/types.def
===================================================================
*** fortran/types.def	(revision 175331)
--- fortran/types.def	(working copy)
*************** DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, 
*** 85,90 ****
--- 85,92 ----
  DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
  DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
+ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_INT, BT_VOID, BT_INT)
+ 
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
  
*************** DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_I4, B
*** 98,103 ****
--- 100,113 ----
  DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_I8, BT_I8, BT_VOLATILE_PTR, BT_I8)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_I16, BT_I16, BT_VOLATILE_PTR, BT_I16)
  DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTR, BT_VOID, BT_PTR, BT_PTR)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_INT, BT_I1, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_INT, BT_I2, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_INT, BT_I4, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_INT, BT_I8, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_INT, BT_I16, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_INT, BT_VOID, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_VPTR_INT, BT_BOOL, BT_VOLATILE_PTR, BT_INT)
+ 
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_
*** 119,131 ****
  		     BT_I16, BT_I16)
  DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
                       BT_PTR, BT_UINT)
- 
  DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_INT, BT_I1, BT_VOLATILE_PTR, BT_I1, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_INT, BT_I2, BT_VOLATILE_PTR, BT_I2, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_INT, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_INT, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_INT, BT_I16, BT_VOLATILE_PTR, BT_I16, BT_INT)
! 
  
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
--- 129,144 ----
  		     BT_I16, BT_I16)
  DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
                       BT_PTR, BT_UINT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_INT, BT_I1, BT_VOLATILE_PTR, BT_I1, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_INT, BT_I2, BT_VOLATILE_PTR, BT_I2, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_INT, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_INT, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_INT, BT_I16, BT_VOLATILE_PTR, BT_I16, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I1_INT, BT_VOID, BT_VOLATILE_PTR, BT_I1, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT)
  
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
*************** DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD
*** 135,140 ****
--- 148,163 ----
  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,
Index: sync-builtins.def
===================================================================
*** sync-builtins.def	(revision 175331)
--- sync-builtins.def	(working copy)
*************** DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_EXCH
*** 277,279 ****
--- 277,452 ----
  DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_EXCHANGE_16,
  		  "__sync_mem_exchange_16",
  		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_N,
+ 		  "__sync_mem_load",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_1,
+ 		  "__sync_mem_load_1",
+ 		  BT_FN_I1_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_2,
+ 		  "__sync_mem_load_2",
+ 		  BT_FN_I2_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_4,
+ 		  "__sync_mem_load_4",
+ 		  BT_FN_I4_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_8,
+ 		  "__sync_mem_load_8",
+ 		  BT_FN_I8_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_16,
+ 		  "__sync_mem_load_16",
+ 		  BT_FN_I16_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_N,
+ 		  "__sync_mem_compare_exchange",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_1,
+ 		  "__sync_mem_compare_exchange_1",
+ 		  BT_FN_BOOL_VPTR_PTR_I1_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_2,
+ 		  "__sync_mem_compare_exchange_2",
+ 		  BT_FN_BOOL_VPTR_PTR_I2_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_4,
+ 		  "__sync_mem_compare_exchange_4",
+ 		  BT_FN_BOOL_VPTR_PTR_I4_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_8,
+ 		  "__sync_mem_compare_exchange_8",
+ 		  BT_FN_BOOL_VPTR_PTR_I8_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_16,
+ 		  "__sync_mem_compare_exchange_16",
+ 		  BT_FN_BOOL_VPTR_PTR_I16_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_N,
+ 		  "__sync_mem_store",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_1,
+ 		  "__sync_mem_store_1",
+ 		  BT_FN_VOID_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_2,
+ 		  "__sync_mem_store_2",
+ 		  BT_FN_VOID_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_4,
+ 		  "__sync_mem_store_4",
+ 		  BT_FN_VOID_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_8,
+ 		  "__sync_mem_store_8",
+ 		  BT_FN_VOID_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_16,
+ 		  "__sync_mem_store_16",
+ 		  BT_FN_VOID_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_N,
+ 		  "__sync_mem_fetch_add",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_1,
+ 		  "__sync_mem_fetch_add_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_2,
+ 		  "__sync_mem_fetch_add_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_4,
+ 		  "__sync_mem_fetch_add_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_8,
+ 		  "__sync_mem_fetch_add_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_16,
+ 		  "__sync_mem_fetch_add_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_N,
+ 		  "__sync_mem_fetch_sub",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_1,
+ 		  "__sync_mem_fetch_sub_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_2,
+ 		  "__sync_mem_fetch_sub_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_4,
+ 		  "__sync_mem_fetch_sub_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_8,
+ 		  "__sync_mem_fetch_sub_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_16,
+ 		  "__sync_mem_fetch_sub_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_N,
+ 		  "__sync_mem_fetch_and",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_1,
+ 		  "__sync_mem_fetch_and_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_2,
+ 		  "__sync_mem_fetch_and_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_4,
+ 		  "__sync_mem_fetch_and_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_8,
+ 		  "__sync_mem_fetch_and_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_16,
+ 		  "__sync_mem_fetch_and_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_N,
+ 		  "__sync_mem_fetch_xor",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_1,
+ 		  "__sync_mem_fetch_xor_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_2,
+ 		  "__sync_mem_fetch_xor_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_4,
+ 		  "__sync_mem_fetch_xor_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_8,
+ 		  "__sync_mem_fetch_xor_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_16,
+ 		  "__sync_mem_fetch_xor_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_N,
+ 		  "__sync_mem_fetch_or",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_1,
+ 		  "__sync_mem_fetch_or_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_2,
+ 		  "__sync_mem_fetch_or_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_4,
+ 		  "__sync_mem_fetch_or_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_8,
+ 		  "__sync_mem_fetch_or_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_16,
+ 		  "__sync_mem_fetch_or_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FLAG_TEST_AND_SET,
+ 		  "__sync_mem_flag_test_and_set",
+ 		  BT_FN_BOOL_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FLAG_CLEAR,
+ 		  "__sync_mem_flag_clear",
+ 		  BT_FN_VOID_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_THREAD_FENCE,
+ 		  "__sync_mem_thread_fence",
+ 		  BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_SIGNAL_FENCE,
+ 		  "__sync_mem_signal_fence",
+ 		  BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+ 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [cxx-mem-model]  __sync_mem builtin support patch 2/3 - code
  2011-07-27  5:31 [cxx-mem-model] __sync_mem builtin support patch 2/3 - code Andrew MacLeod
@ 2011-07-27 16:14 ` Richard Henderson
  2011-07-27 18:50   ` Andrew MacLeod
  0 siblings, 1 reply; 4+ messages in thread
From: Richard Henderson @ 2011-07-27 16:14 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, Aldy Hernandez

On 07/26/2011 06:20 PM, Andrew MacLeod wrote:
> * __sync_mem_compare_exchange has the skeleton in place, but not the
> guts.  There are some issues that rth and I will work out later, I
> just don't want to hold up the rest of the patch for that. Right now
> it will fail the compare_exchange tests.

Please disable the relevant tests too.

>     if ((icode != CODE_FOR_nothing) && (model == MEMMODEL_SEQ_CST || 
>   				     model == MEMMODEL_ACQ_REL))
> + #ifdef HAVE_sync_mem_thread_fence
> +     emit_mem_thread_fence (model);
> + #else
>       expand_builtin_sync_synchronize ();
> + #endif

Coding style requires braces here.  Yes, only one of the two
functions are called, but that's not immediately obvious to
the eye.

Lots of other instances in your new code.

That said, why wouldn't emit_mem_thread_fence always exist
and generate the expand_builtin_sync_synchronize as needed?

> + #ifdef HAVE_sync_mem_thread_fence
> +     emit_mem_thread_fence (model);
> + #else
> +     if (model != MEMMODEL_RELAXED)
> +       expand_builtin_sync_synchronize ();
> + #endif
> + 
> +    target = expand_sync_fetch_operation (mem, val, code, false, target);
> + 
> + #ifdef HAVE_sync_mem_thread_fence
> +     emit_mem_thread_fence (model);
> + #else
> +     if (model != MEMMODEL_RELAXED)
> +       expand_builtin_sync_synchronize ();
> + #endif
> +   return target;

Over-zealous with your pattern.  The sync_fetch_op is a
full barrier.  You don't need the extra stuff.

> + static rtx
> + maybe_convert_modes (tree exp, enum machine_mode mode)

I think a better name might be expand_expr_force_mode.


Otherwise it looks ok.


r~

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [cxx-mem-model]  __sync_mem builtin support patch 2/3 - code
  2011-07-27 16:14 ` Richard Henderson
@ 2011-07-27 18:50   ` Andrew MacLeod
  2011-07-27 21:40     ` Richard Henderson
  0 siblings, 1 reply; 4+ messages in thread
From: Andrew MacLeod @ 2011-07-27 18:50 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, Aldy Hernandez

[-- Attachment #1: Type: text/plain, Size: 1322 bytes --]

On 07/27/2011 12:03 PM, Richard Henderson wrote:
> Please disable the relevant tests too.
sure.

>>      if ((icode != CODE_FOR_nothing)&&  (model == MEMMODEL_SEQ_CST ||
>>    				     model == MEMMODEL_ACQ_REL))
>> + #ifdef HAVE_sync_mem_thread_fence
>> +     emit_mem_thread_fence (model);
>> + #else
>>        expand_builtin_sync_synchronize ();
>> + #endif
> Coding style requires braces here.  Yes, only one of the two
> functions are called, but that's not immediately obvious to
> the eye.
>
> Lots of other instances in your new code.
>
> That said, why wouldn't emit_mem_thread_fence always exist
> and generate the expand_builtin_sync_synchronize as needed?

Done after a chat with you sorting it out.. I added an 
expand_builtin_mem_thread_fence() routine which does just this, much 
cleaner :-)

I also noticed that all the expand_builtin_sync_mem_ flag and fence 
routines (4 in total) were all not quite correct. none of them would 
actually use a pattern if it was defined, so I changed them a bit to do 
that.  They were basically the set which did not have a TYPE modifier, 
so didnt have entries in the direct_optab table, so were missing out.

Rest is done.  Patch is attached in case you want to look at the changes.

bootstraps with no regressions on x86_64-unknown-linux-gnu, no regressions.

Andrew

[-- Attachment #2: code.patch --]
[-- Type: text/plain, Size: 55447 bytes --]


	* expr.h (expand_sync_mem_exchange): Change parameter order.
	(expand_sync_mem_*): New prototypes.
	(expand_builtin_sync_synchronize): Remove prototype.
	(expand_builtin_mem_thread_fence): Add prototype.
	* optabs.h (DOI_sync_mem_*): Add new optable enums.
	(sync_mem_*_optab): Add new #defines for table entries.
	* genopinit.c (const optabs[]): Add direct optab handlers.
	* optabs.c (expand_sync_mem_exchange): Change parameter order, and use
	builtin_mem_thread_fence.
	(expand_sync_mem_compare_exchange, expand_sync_mem_load,
	expand_sync_mem_store, expand_sync_mem_fetch_op): New. Expand
	__sync_mem functions which handle multiple integral types.
	* builtins.c (expand_expr_force_mode): New. Factor out common code for
	ensuring an integer argument is in the proper mode.
	(expand_builtin_sync_operation, expand_builtin_compare_and_swap,
	expand_builtin_sync_lock_test_and_set): Use maybe_convert_modes.
	(expand_builtin_sync_lock_release): Relocate higher in the file.
	(get_memmodel): Don't assume the memmodel is the 3rd argument.
	(expand_builtin_sync_mem_exchange): Change error check and use
	maybe_convert_modes.
	(expand_builtin_sync_mem_compare_exchange): New.
	(expand_builtin_sync_mem_load, expand_builtin_sync_mem_store): New.
	(expand_builtin_sync_mem_fetch_op): New.
	(expand_builtin_sync_mem_flag_test_and_set): New.
	(expand_builtin_sync_mem_flag_clear): New.
	(expand_builtin_mem_thread_fence): New.
	(expand_builtin_sync_mem_thread_fence): New.
	(expand_builtin_mem_signal_fence): New.
	(expand_builtin_sync_mem_signal_fence): New.
	(expand_builtin): Handle BUILT_IN_SYNC_MEM_* types.
	* c-family/c-common.c (resolve_overloaded_builtin): Handle
	BUILT_IN_SYNC_MEM_* types.
	* builtin-types.def (BT_FN_I{1,2,4,8,16}_VPTR_INT): New builtin type.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT): New builtin types.
	(BT_FN_VOID_VPTR_I{1,2,4,8,16}_INT: New builtin type.
	(BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_INT_INT): New builtin type.
	* fortran/types.def (BT_FN_VOID_INT): New type.
	(BT_FN_I{1,2,4,8,16}_VPTR_INT): New builtin type.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT): New builtin types.
	(BT_FN_VOID_VPTR_I{1,2,4,8,16}_INT: New builtin type.
	(BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_INT_INT): New builtin type.
	* sync-builtins.def (BUILT_IN_SYNC_MEM_*): New sync builtins.


Index: expr.h
===================================================================
*** expr.h	(revision 175331)
--- expr.h	(working copy)
*************** rtx expand_bool_compare_and_swap (rtx, r
*** 217,223 ****
  rtx expand_sync_operation (rtx, rtx, enum rtx_code);
  rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
  rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
! rtx expand_sync_mem_exchange (enum memmodel, rtx, rtx, rtx);
  \f
  /* Functions from expmed.c:  */
  
--- 217,234 ----
  rtx expand_sync_operation (rtx, rtx, enum rtx_code);
  rtx expand_sync_fetch_operation (rtx, rtx, enum rtx_code, bool, rtx);
  rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
! 
! rtx expand_sync_mem_exchange (rtx, rtx, rtx, enum memmodel);
! rtx expand_sync_mem_compare_exchange (rtx, rtx, rtx, rtx, enum memmodel, 
! 				      enum memmodel);
! rtx expand_sync_mem_load (rtx, rtx, enum memmodel);
! void expand_sync_mem_store (rtx, rtx, enum memmodel);
! rtx expand_sync_mem_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel);
! rtx expand_sync_mem_flag_test_and_set (rtx, rtx, enum memmodel);
! void expand_sync_mem_flag_clear (rtx, enum memmodel);
! void expand_sync_mem_thread_fence (enum memmodel);
! void expand_sync_mem_signal_fence (enum memmodel);
! 
  \f
  /* Functions from expmed.c:  */
  
*************** extern void expand_builtin_setjmp_receiv
*** 249,255 ****
  extern rtx expand_builtin_saveregs (void);
  extern void expand_builtin_trap (void);
  extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
! extern void expand_builtin_sync_synchronize (void);
  \f
  /* Functions from expr.c:  */
  
--- 260,266 ----
  extern rtx expand_builtin_saveregs (void);
  extern void expand_builtin_trap (void);
  extern rtx builtin_strncpy_read_str (void *, HOST_WIDE_INT, enum machine_mode);
! extern void expand_builtin_mem_thread_fence (enum memmodel);
  \f
  /* Functions from expr.c:  */
  
Index: optabs.h
===================================================================
*** optabs.h	(revision 175331)
--- optabs.h	(working copy)
*************** enum direct_optab_index
*** 679,684 ****
--- 679,696 ----
  
    /* Atomic operations with C++0x memory model parameters. */
    DOI_sync_mem_exchange,
+   DOI_sync_mem_compare_exchange,
+   DOI_sync_mem_load,
+   DOI_sync_mem_store,
+   DOI_sync_mem_fetch_add,
+   DOI_sync_mem_fetch_sub,
+   DOI_sync_mem_fetch_and,
+   DOI_sync_mem_fetch_xor,
+   DOI_sync_mem_fetch_or,
+   DOI_sync_mem_flag_test_and_set,
+   DOI_sync_mem_flag_clear,
+   DOI_sync_mem_thread_fence,
+   DOI_sync_mem_signal_fence,
  
    DOI_MAX
  };
*************** typedef struct direct_optab_d *direct_op
*** 730,735 ****
--- 742,771 ----
  
  #define sync_mem_exchange_optab \
    (&direct_optab_table[(int) DOI_sync_mem_exchange])
+ #define sync_mem_compare_exchange_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_compare_exchange])
+ #define sync_mem_load_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_load])
+ #define sync_mem_store_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_store])
+ #define sync_mem_fetch_add_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_add])
+ #define sync_mem_fetch_sub_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_sub])
+ #define sync_mem_fetch_and_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_and])
+ #define sync_mem_fetch_xor_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_xor])
+ #define sync_mem_fetch_or_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_fetch_or])
+ #define sync_mem_flag_test_and_set_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_flag_test_and_set])
+ #define sync_mem_flag_clear_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_flag_clear])
+ #define sync_mem_thread_fence_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_thread_fence])
+ #define sync_mem_signal_fence_optab \
+   (&direct_optab_table[(int) DOI_sync_mem_signal_fence])
  \f
  /* Target-dependent globals.  */
  struct target_optabs {
Index: genopinit.c
===================================================================
*** genopinit.c	(revision 175331)
--- genopinit.c	(working copy)
*************** static const char * const optabs[] =
*** 242,247 ****
--- 242,255 ----
    "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 (sync_mem_exchange_optab, $A, CODE_FOR_$(sync_mem_exchange$I$a$))",
+   "set_direct_optab_handler (sync_mem_compare_exchange_optab, $A, CODE_FOR_$(sync_mem_compare_exchange$I$a$))",
+   "set_direct_optab_handler (sync_mem_load_optab, $A, CODE_FOR_$(sync_mem_load$I$a$))",
+   "set_direct_optab_handler (sync_mem_store_optab, $A, CODE_FOR_$(sync_mem_store$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_add_optab, $A, CODE_FOR_$(sync_mem_fetch_add$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_sub_optab, $A, CODE_FOR_$(sync_mem_fetch_sub$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_and_optab, $A, CODE_FOR_$(sync_mem_fetch_and$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_xor_optab, $A, CODE_FOR_$(sync_mem_fetch_xor$I$a$))",
+   "set_direct_optab_handler (sync_mem_fetch_or_optab, $A, CODE_FOR_$(sync_mem_fetch_or$I$a$))",
    "set_optab_handler (vec_set_optab, $A, CODE_FOR_$(vec_set$a$))",
    "set_optab_handler (vec_extract_optab, $A, CODE_FOR_$(vec_extract$a$))",
    "set_optab_handler (vec_extract_even_optab, $A, CODE_FOR_$(vec_extract_even$a$))",
Index: optabs.c
===================================================================
*** optabs.c	(revision 175331)
--- optabs.c	(working copy)
*************** expand_sync_lock_test_and_set (rtx mem, 
*** 7064,7070 ****
     TARGET is an option place to stick the return value.  */
  
  rtx
! expand_sync_mem_exchange (enum memmodel model, rtx mem, rtx val, rtx target)
  {
    enum machine_mode mode = GET_MODE (mem);
    enum insn_code icode;
--- 7064,7070 ----
     TARGET is an option place to stick the return value.  */
  
  rtx
! expand_sync_mem_exchange (rtx target, rtx mem, rtx val, enum memmodel model)
  {
    enum machine_mode mode = GET_MODE (mem);
    enum insn_code icode;
*************** expand_sync_mem_exchange (enum memmodel 
*** 7092,7101 ****
    icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
    if ((icode != CODE_FOR_nothing) && (model == MEMMODEL_SEQ_CST || 
  				     model == MEMMODEL_ACQ_REL))
!     expand_builtin_sync_synchronize ();
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
  \f
  /* Return true if OPERAND is suitable for operand number OPNO of
     instruction ICODE.  */
--- 7092,7301 ----
    icode = direct_optab_handler (sync_lock_test_and_set_optab, mode);
    if ((icode != CODE_FOR_nothing) && (model == MEMMODEL_SEQ_CST || 
  				     model == MEMMODEL_ACQ_REL))
!     expand_builtin_mem_thread_fence (model);
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
+ 
+ /* This function expands the atomic compare exchange operation:
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ rtx
+ expand_sync_mem_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 (sync_mem_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
+ }
+ 
+ 
+ /* This function expands the atomic load operation:
+    return the atomically loaded value in MEM.
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ rtx
+ expand_sync_mem_load (rtx target, rtx mem, enum memmodel model)
+ {
+   enum machine_mode mode = GET_MODE (mem);
+   enum insn_code icode;
+ 
+   /* If the target supports the load directly, great.  */
+   icode = direct_optab_handler (sync_mem_load_optab, mode);
+   if (icode != CODE_FOR_nothing)
+     {
+       struct expand_operand ops[3];
+ 
+       create_output_operand (&ops[0], target, mode);
+       create_fixed_operand (&ops[1], mem);
+       create_integer_operand (&ops[2], model);
+       if (maybe_expand_insn (icode, 3, ops))
+ 	return ops[0].value;
+     }
+ 
+   /* If there is no load, default to a move with barriers. */
+   if (target == const0_rtx)
+     target = gen_reg_rtx (mode);
+ 
+   /* Emit the appropriate barrier before the load.  */
+   expand_builtin_mem_thread_fence (model);
+ 
+   emit_move_insn (target, mem);
+ 
+   /* For SEQ_CST, also emit a barrier after the load.  */
+   if (model == MEMMODEL_SEQ_CST)
+     expand_builtin_mem_thread_fence (model);
+ 
+   return target;
+ }
+ 
+ /* This function expands the atomic load operation:
+    return the atomically loaded value in MEM.
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ void
+ expand_sync_mem_store (rtx mem, rtx val, enum memmodel model)
+ {
+   enum machine_mode mode = GET_MODE (mem);
+   enum insn_code icode;
+ 
+   /* If the target supports the store directly, great.  */
+   icode = direct_optab_handler (sync_mem_store_optab, mode);
+   if (icode != CODE_FOR_nothing)
+     {
+       struct expand_operand ops[3];
+ 
+       create_output_operand (&ops[0], mem, mode);
+       create_fixed_operand (&ops[1], val);
+       create_integer_operand (&ops[2], model);
+       if (maybe_expand_insn (icode, 3, ops))
+ 	return;
+     }
+ 
+   /* If there is no mem_store, default to a move with barriers */
+ 
+   if (model == MEMMODEL_SEQ_CST)
+     expand_builtin_mem_thread_fence (model);
+ 
+   emit_move_insn (mem, val);
+ 
+   /* For SEQ_CST, also emit a barrier after the load.  */
+   expand_builtin_mem_thread_fence (model);
+ }
+ 
+ /* This function expands an atomic fetch_OP operation:
+    CODE is the operation to be performed.
+    atomically fetch MEM, perform the operation with VAL and return it to MEM.
+    return the previous value of MEM.
+ 
+    MEMMODEL is the memory model variant to use.
+    TARGET is an option place to stick the return value.  */
+ 
+ rtx
+ expand_sync_mem_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code,
+ 			  enum memmodel model)
+ {
+   enum machine_mode mode = GET_MODE (mem);
+   enum insn_code icode;
+ 
+   switch (code)
+     {
+       case PLUS:
+         icode = direct_optab_handler (sync_mem_fetch_add_optab, mode);
+         break;
+       case MINUS:
+         icode = direct_optab_handler (sync_mem_fetch_sub_optab, mode);
+         break;
+       case AND:
+         icode = direct_optab_handler (sync_mem_fetch_and_optab, mode);
+         break;
+       case XOR:
+         icode = direct_optab_handler (sync_mem_fetch_xor_optab, mode);
+         break;
+       case IOR:
+         icode = direct_optab_handler (sync_mem_fetch_or_optab, mode);
+         break;
+       default:
+         icode = CODE_FOR_nothing;
+     }
+ 
+   /* If the target supports the operation directly, great.  */
+   if (icode != CODE_FOR_nothing)
+     {
+       struct expand_operand ops[4];
+ 
+       create_output_operand (&ops[0], target, mode);
+       create_fixed_operand (&ops[1], mem);
+       /* VAL may have been promoted to a wider mode.  Shrink it if so.  */
+       create_convert_operand_to (&ops[2], val, mode, true);
+       create_integer_operand (&ops[3], model);
+       if (maybe_expand_insn (icode, 4, ops))
+ 	return ops[0].value;
+     }
+ 
+    /* fetch_* operations are full barriers, so need nothign else.  */
+    target = expand_sync_fetch_operation (mem, val, code, false, target);
+ 
+   return target;
+ }
+ 
+ 
  \f
  /* Return true if OPERAND is suitable for operand number OPNO of
     instruction ICODE.  */
Index: builtins.c
===================================================================
*** builtins.c	(revision 175331)
--- builtins.c	(working copy)
*************** static tree do_mpfr_bessel_n (tree, tree
*** 227,232 ****
--- 227,233 ----
  			      const REAL_VALUE_TYPE *, bool);
  static tree do_mpfr_remquo (tree, tree, tree);
  static tree do_mpfr_lgamma_r (tree, tree, tree);
+ static void expand_builtin_sync_synchronize (void);
  
  /* Return true if NAME starts with __builtin_ or __sync_.  */
  
*************** get_builtin_sync_mem (tree loc, enum mac
*** 5057,5062 ****
--- 5058,5085 ----
    return mem;
  }
  
+ /* Make sure an argument is in the right mode.
+    EXP is the tree argument. 
+    MODE is the mode it should be in.  */
+ 
+ static rtx
+ expand_expr_force_mode (tree exp, enum machine_mode mode)
+ {
+   rtx val;
+   enum machine_mode old_mode;
+ 
+   val = expand_expr (exp, NULL_RTX, mode, EXPAND_NORMAL);
+   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
+      of CONST_INTs, where we know the old_mode only from the call argument.  */
+ 
+   old_mode = GET_MODE (val);
+   if (old_mode == VOIDmode)
+     old_mode = TYPE_MODE (TREE_TYPE (exp));
+   val = convert_modes (mode, old_mode, val, 1);
+   return val;
+ }
+ 
+ 
  /* Expand the __sync_xxx_and_fetch and __sync_fetch_and_xxx intrinsics.
     EXP is the CALL_EXPR.  CODE is the rtx code
     that corresponds to the arithmetic or logical operation from the name;
*************** expand_builtin_sync_operation (enum mach
*** 5071,5077 ****
  			       rtx target, bool ignore)
  {
    rtx val, mem;
-   enum machine_mode old_mode;
    location_t loc = EXPR_LOCATION (exp);
  
    if (code == NOT && warn_sync_nand)
--- 5094,5099 ----
*************** expand_builtin_sync_operation (enum mach
*** 5118,5131 ****
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
!   val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   val = convert_modes (mode, old_mode, val, 1);
  
    if (ignore)
      return expand_sync_operation (mem, val, code);
--- 5140,5146 ----
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
    if (ignore)
      return expand_sync_operation (mem, val, code);
*************** expand_builtin_compare_and_swap (enum ma
*** 5143,5171 ****
  				 bool is_bool, rtx target)
  {
    rtx old_val, new_val, mem;
-   enum machine_mode old_mode;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
! 
!   old_val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX,
! 			 mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (old_val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   old_val = convert_modes (mode, old_mode, old_val, 1);
! 
!   new_val = expand_expr (CALL_EXPR_ARG (exp, 2), NULL_RTX,
! 			 mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (new_val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 2)));
!   new_val = convert_modes (mode, old_mode, new_val, 1);
  
    if (is_bool)
      return expand_bool_compare_and_swap (mem, old_val, new_val, target);
--- 5158,5168 ----
  				 bool is_bool, rtx target)
  {
    rtx old_val, new_val, mem;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   old_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
!   new_val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
  
    if (is_bool)
      return expand_bool_compare_and_swap (mem, old_val, new_val, target);
*************** expand_builtin_sync_lock_test_and_set (e
*** 5184,5204 ****
  				  rtx target)
  {
    rtx val, mem;
-   enum machine_mode old_mode;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   val = convert_modes (mode, old_mode, val, 1);
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
  
  /* Given an integer representing an ``enum memmodel'', verify its
     correctness and return the memory model enum.  */
  
--- 5181,5222 ----
  				  rtx target)
  {
    rtx val, mem;
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
    return expand_sync_lock_test_and_set (mem, val, target);
  }
  
+ /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
+ 
+ static void
+ expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
+ {
+   struct expand_operand ops[2];
+   enum insn_code icode;
+   rtx mem;
+ 
+   /* Expand the operands.  */
+   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
+ 
+   /* If there is an explicit operation in the md file, use it.  */
+   icode = direct_optab_handler (sync_lock_release_optab, mode);
+   if (icode != CODE_FOR_nothing)
+     {
+       create_fixed_operand (&ops[0], mem);
+       create_input_operand (&ops[1], const0_rtx, mode);
+       if (maybe_expand_insn (icode, 2, ops))
+ 	return;
+     }
+ 
+   /* Otherwise we can implement this operation by emitting a barrier
+      followed by a store of zero.  */
+   expand_builtin_sync_synchronize ();
+   emit_move_insn (mem, const0_rtx);
+ }
+ 
  /* Given an integer representing an ``enum memmodel'', verify its
     correctness and return the memory model enum.  */
  
*************** get_memmodel (tree exp)
*** 5209,5230 ****
  
    if (TREE_CODE (exp) != INTEGER_CST)
      {
!       error ("third argument to builtin is an invalid memory model");
!       return MEMMODEL_SEQ_CST;
      }
    op = expand_normal (exp);
    if (INTVAL (op) < 0 || INTVAL (op) >= MEMMODEL_LAST)
      {
!       error ("third argument to builtin is an invalid memory model");
!       return MEMMODEL_SEQ_CST;
      }
    return (enum memmodel) INTVAL (op);
  }
  
  /* Expand the __sync_mem_exchange intrinsic:
! 
!    	TYPE __sync_mem_exchange (TYPE *to, TYPE from, enum memmodel)
! 
     EXP is the CALL_EXPR.
     TARGET is an optional place for us to store the results.  */
  
--- 5227,5246 ----
  
    if (TREE_CODE (exp) != INTEGER_CST)
      {
!       error ("invalid memory model argument to builtin");
!       return MEMMODEL_RELAXED;
      }
    op = expand_normal (exp);
    if (INTVAL (op) < 0 || INTVAL (op) >= MEMMODEL_LAST)
      {
!       error ("invalid memory model argument to builtin");
!       return MEMMODEL_RELAXED;
      }
    return (enum memmodel) INTVAL (op);
  }
  
  /* Expand the __sync_mem_exchange intrinsic:
!    	TYPE __sync_mem_exchange (TYPE *object, TYPE desired, enum memmodel)
     EXP is the CALL_EXPR.
     TARGET is an optional place for us to store the results.  */
  
*************** static rtx
*** 5232,5246 ****
  expand_builtin_sync_mem_exchange (enum machine_mode mode, tree exp, rtx target)
  {
    rtx val, mem;
-   enum machine_mode old_mode;
    enum memmodel model;
  
    model = get_memmodel (CALL_EXPR_ARG (exp, 2));
!   if (model != MEMMODEL_RELAXED
!       && model != MEMMODEL_SEQ_CST
!       && model != MEMMODEL_ACQ_REL
!       && model != MEMMODEL_RELEASE
!       && model != MEMMODEL_ACQUIRE)
      {
        error ("invalid memory model for %<__sync_mem_exchange%>");
        return NULL_RTX;
--- 5248,5257 ----
  expand_builtin_sync_mem_exchange (enum machine_mode mode, tree exp, rtx target)
  {
    rtx val, mem;
    enum memmodel model;
  
    model = get_memmodel (CALL_EXPR_ARG (exp, 2));
!   if (model == MEMMODEL_CONSUME)
      {
        error ("invalid memory model for %<__sync_mem_exchange%>");
        return NULL_RTX;
*************** expand_builtin_sync_mem_exchange (enum m
*** 5248,5267 ****
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, mode, EXPAND_NORMAL);
!   /* If VAL is promoted to a wider mode, convert it back to MODE.  Take care
!      of CONST_INTs, where we know the old_mode only from the call argument.  */
!   old_mode = GET_MODE (val);
!   if (old_mode == VOIDmode)
!     old_mode = TYPE_MODE (TREE_TYPE (CALL_EXPR_ARG (exp, 1)));
!   val = convert_modes (mode, old_mode, val, 1);
  
!   return expand_sync_mem_exchange (model, mem, val, target);
  }
  
! /* Expand the __sync_synchronize intrinsic.  */
  
  void
  expand_builtin_sync_synchronize (void)
  {
    gimple x;
--- 5259,5505 ----
  
    /* Expand the operands.  */
    mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
  
!   return expand_sync_mem_exchange (target, mem, val, model);
  }
  
! /* Expand the __sync_mem_compare_exchange intrinsic:
!    	bool __sync_mem_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_sync_mem_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)
!     {
!       error ("invalid failure memory model for %<__sync_mem_compare_exchange%>");
!       return NULL_RTX;
!     }
! 
!   if (failure > success)
!     {
!       error ("failure memory model cannot be stronger than success memory model for %<__sync_mem_compare_exchange%>");
!       return NULL_RTX;
!     }
!   
!   /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
!   expect = expand_expr (CALL_EXPR_ARG (exp, 1), NULL_RTX, ptr_mode, 
! 			EXPAND_NORMAL);
!   expect = convert_memory_address (Pmode, expect);
! 
!   desired = expand_expr_force_mode (CALL_EXPR_ARG (exp, 2), mode);
! 
!   return expand_sync_mem_compare_exchange (target, mem, expect, desired, 
! 					   success, failure);
! }
! 
! /* Expand the __sync_mem_load intrinsic:
!    	TYPE __sync_mem_load (TYPE *object, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.  */
! 
! static rtx
! expand_builtin_sync_mem_load (enum machine_mode mode, tree exp, rtx target)
! {
!   rtx mem;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
!   if (model == MEMMODEL_RELEASE
!       || model == MEMMODEL_ACQ_REL)
!     {
!       error ("invalid memory model for %<__sync_mem_load%>");
!       return NULL_RTX;
!     }
! 
!   /* Expand the operand.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
! 
!   return expand_sync_mem_load (target, mem, model);
! }
! 
! 
! /* Expand the __sync_mem_store intrinsic:
!    	void __sync_mem_store (TYPE *object, TYPE desired, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.  */
! 
! static void
! expand_builtin_sync_mem_store (enum machine_mode mode, tree exp)
! {
!   rtx mem, val;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
!   if (model != MEMMODEL_RELAXED
!       && model != MEMMODEL_SEQ_CST
!       && model != MEMMODEL_RELEASE)
!     {
!       error ("invalid memory model for %<__sync_mem_store%>");
!       return;
!     }
! 
!   /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
! 
!   expand_sync_mem_store (mem, val, model);
! }
! 
! /* Expand the __sync_mem_fetch_XXX intrinsic:
!    	TYPE __sync_mem_fetch_XXX (TYPE *object, TYPE val, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.
!    CODE is the operation, PLUS, MINUS, ADD, XOR, or IOR. */
! 
! static rtx
! expand_builtin_sync_mem_fetch_op (enum machine_mode mode, tree exp, rtx target,
! 				  enum rtx_code code)
! {
!   rtx val, mem;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
! 
!   /* Expand the operands.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
!   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
! 
!   return expand_sync_mem_fetch_op (target, mem, val, code, model);
! }
! 
! /* Expand the __sync_mem_flag_test_and_set intrinsic:
!    	bool __sync_mem_flag_test_and_set (char *object, enum memmodel)
!    EXP is the CALL_EXPR.
!    TARGET is an optional place for us to store the results.  */
! 
! static rtx
! expand_builtin_sync_mem_flag_test_and_set (tree exp, rtx target)
! {
!   rtx mem;
!   enum memmodel model;
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
!   /* Expand the operand.  */
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), QImode);
! 
! #ifdef HAVE_mem_flag_test_and_set
!   return emit_insn (gen_mem_flag_test_and_set (mem, model));
! #else
!   /* sync_lock_test_and_set is an acquire barrier, so a barrier may be needed
!      before.  */
! 
!   if (model == MEMMODEL_SEQ_CST || model == MEMMODEL_ACQ_REL
!       || model == MEMMODEL_RELEASE)
!     expand_builtin_sync_synchronize ();
! 
!   return expand_sync_lock_test_and_set (mem, const1_rtx, target);
! #endif
! }
! 
! /* Expand the __sync_mem_flag_clear intrinsic:
!    	void __sync_mem_flag_clear (char *object, enum memmodel)
!    EXP is the CALL_EXPR.  */
! 
! static void
! expand_builtin_sync_mem_flag_clear (tree exp)
! {
!   enum memmodel model;
! #ifdef HAVE_mem_flag_clear
!   rtx mem;
! #endif
! 
!   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
! 
!   if (model == MEMMODEL_ACQUIRE || model == MEMMODEL_ACQ_REL)
!     {
!       error ("invalid memory model for %<__sync_mem_flag_clear%>");
!       return;
!     }
! 
! #ifdef HAVE_mem_flag_clear
!   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), QImode);
!   emit_insn (gen_mem_flag_clear (mem, model));
! #else
!   expand_builtin_sync_lock_release (QImode, exp);
! 
!   /* sync_lock_release is a release barrier, so we may need a seq-cst 
!      barrier afterwards.  */
!   if (model == MEMMODEL_SEQ_CST)
!     expand_builtin_sync_synchronize ();
! #endif 
! }
! 
! /* This routine will either emit the mem_thread_fence pattern or issue a 
!    sync_synchronize to generate a fence for memory model MEMMODEL.  */
  
  void
+ expand_builtin_mem_thread_fence (enum memmodel model)
+ {
+ #ifdef HAVE_mem_thread_fence
+   emit_insn (gen_mem_thread_fence (memmodel));
+ #else
+   if (model != MEMMODEL_RELAXED)
+     expand_builtin_sync_synchronize ();
+ #endif
+ }
+ 
+ /* Expand the __sync_mem_thread_fence intrinsic:
+    	void __sync_mem_thread_fence (enum memmodel)
+    EXP is the CALL_EXPR.  */
+ 
+ static void
+ expand_builtin_sync_mem_thread_fence (tree exp)
+ {
+   enum memmodel model;
+   
+   model = get_memmodel (CALL_EXPR_ARG (exp, 0));
+   expand_builtin_mem_thread_fence (model);
+ }
+ 
+ /* This routine will either emit the mem_signal_fence pattern or issue a 
+    sync_synchronize to generate a fence for memory model MEMMODEL.  */
+ 
+ static void
+ expand_builtin_mem_signal_fence (enum memmodel model)
+ {
+ #ifdef HAVE_mem_signal_fence
+   emit_insn (gen_mem_signal_fence (memmodel));
+ #else
+   if (model != MEMMODEL_RELAXED)
+     expand_builtin_sync_synchronize ();
+ #endif
+ }
+ 
+ /* Expand the __sync_mem_signal_fence intrinsic:
+    	void __sync_mem_signal_fence (enum memmodel)
+    EXP is the CALL_EXPR.  */
+ 
+ static void
+ expand_builtin_sync_mem_signal_fence (tree exp)
+ {
+   enum memmodel model;
+ 
+   model = get_memmodel (CALL_EXPR_ARG (exp, 0));
+   expand_builtin_mem_signal_fence (model);
+ }
+ 
+ /* Expand the __sync_synchronize intrinsic.  */
+ 
+ static void
  expand_builtin_sync_synchronize (void)
  {
    gimple x;
*************** expand_builtin_sync_synchronize (void)
*** 5291,5323 ****
    expand_asm_stmt (x);
  }
  
- /* Expand the __sync_lock_release intrinsic.  EXP is the CALL_EXPR.  */
- 
- static void
- expand_builtin_sync_lock_release (enum machine_mode mode, tree exp)
- {
-   struct expand_operand ops[2];
-   enum insn_code icode;
-   rtx mem;
- 
-   /* Expand the operands.  */
-   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
- 
-   /* If there is an explicit operation in the md file, use it.  */
-   icode = direct_optab_handler (sync_lock_release_optab, mode);
-   if (icode != CODE_FOR_nothing)
-     {
-       create_fixed_operand (&ops[0], mem);
-       create_input_operand (&ops[1], const0_rtx, mode);
-       if (maybe_expand_insn (icode, 2, ops))
- 	return;
-     }
- 
-   /* Otherwise we can implement this operation by emitting a barrier
-      followed by a store of zero.  */
-   expand_builtin_sync_synchronize ();
-   emit_move_insn (mem, const0_rtx);
- }
  \f
  /* Expand an expression EXP that calls a built-in function,
     with result going to TARGET if that's convenient
--- 5529,5534 ----
*************** expand_builtin (tree exp, rtx target, rt
*** 6077,6093 ****
  	return target;
        break;
  
-     case BUILT_IN_SYNC_MEM_EXCHANGE_1:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_2:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_4:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_8:
-     case BUILT_IN_SYNC_MEM_EXCHANGE_16:
-       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_EXCHANGE_1);
-       target = expand_builtin_sync_mem_exchange (mode, exp, target);
-       if (target)
- 	return target;
-       break;
- 
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_1:
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_2:
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_4:
--- 6288,6293 ----
*************** expand_builtin (tree exp, rtx target, rt
*** 6112,6117 ****
--- 6312,6433 ----
        expand_builtin_sync_synchronize ();
        return const0_rtx;
  
+     case BUILT_IN_SYNC_MEM_EXCHANGE_1:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_2:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_4:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_8:
+     case BUILT_IN_SYNC_MEM_EXCHANGE_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_EXCHANGE_1);
+       target = expand_builtin_sync_mem_exchange (mode, exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_1:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_2:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_4:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_8:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_16:
+       mode = 
+ 	  get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_1);
+       target = expand_builtin_sync_mem_compare_exchange (mode, exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_LOAD_1:
+     case BUILT_IN_SYNC_MEM_LOAD_2:
+     case BUILT_IN_SYNC_MEM_LOAD_4:
+     case BUILT_IN_SYNC_MEM_LOAD_8:
+     case BUILT_IN_SYNC_MEM_LOAD_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_LOAD_1);
+       target = expand_builtin_sync_mem_load (mode, exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_STORE_1:
+     case BUILT_IN_SYNC_MEM_STORE_2:
+     case BUILT_IN_SYNC_MEM_STORE_4:
+     case BUILT_IN_SYNC_MEM_STORE_8:
+     case BUILT_IN_SYNC_MEM_STORE_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_STORE_1);
+       expand_builtin_sync_mem_store (mode, exp);
+       return const0_rtx;
+ 
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_1:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_2:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_4:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_8:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_ADD_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, PLUS);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_1:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_2:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_4:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_8:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_SUB_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, MINUS);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_AND_1:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_2:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_4:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_8:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_AND_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, AND);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_1:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_2:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_4:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_8:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_XOR_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, XOR);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FETCH_OR_1:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_2:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_4:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_8:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_16:
+       mode = get_builtin_sync_mode (fcode - BUILT_IN_SYNC_MEM_FETCH_OR_1);
+       target = expand_builtin_sync_mem_fetch_op (mode, exp, target, IOR);
+       if (target)
+ 	return target;
+       break;
+  
+     case BUILT_IN_SYNC_MEM_FLAG_TEST_AND_SET:
+       target = expand_builtin_sync_mem_flag_test_and_set (exp, target);
+       if (target)
+ 	return target;
+       break;
+ 
+     case BUILT_IN_SYNC_MEM_FLAG_CLEAR:
+       expand_builtin_sync_mem_flag_clear (exp);
+       return const0_rtx;
+ 
+     case BUILT_IN_SYNC_MEM_THREAD_FENCE:
+       expand_builtin_sync_mem_thread_fence (exp);
+       return const0_rtx;
+ 
+     case BUILT_IN_SYNC_MEM_SIGNAL_FENCE:
+       expand_builtin_sync_mem_signal_fence (exp);
+       return const0_rtx;
+ 
      case BUILT_IN_OBJECT_SIZE:
        return expand_builtin_object_size (exp);
  
Index: c-family/c-common.c
===================================================================
*** c-family/c-common.c	(revision 175331)
--- c-family/c-common.c	(working copy)
*************** resolve_overloaded_builtin (location_t l
*** 9061,9066 ****
--- 9061,9074 ----
      case BUILT_IN_SYNC_LOCK_TEST_AND_SET_N:
      case BUILT_IN_SYNC_LOCK_RELEASE_N:
      case BUILT_IN_SYNC_MEM_EXCHANGE_N:
+     case BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_N:
+     case BUILT_IN_SYNC_MEM_LOAD_N:
+     case BUILT_IN_SYNC_MEM_STORE_N:
+     case BUILT_IN_SYNC_MEM_FETCH_ADD_N:
+     case BUILT_IN_SYNC_MEM_FETCH_SUB_N:
+     case BUILT_IN_SYNC_MEM_FETCH_AND_N:
+     case BUILT_IN_SYNC_MEM_FETCH_XOR_N:
+     case BUILT_IN_SYNC_MEM_FETCH_OR_N:
        {
  	int n = sync_resolve_size (function, params);
  	tree new_function, first_param, result;
*************** resolve_overloaded_builtin (location_t l
*** 9075,9081 ****
  	first_param = VEC_index (tree, params, 0);
  	result = build_function_call_vec (loc, new_function, params, NULL);
  	if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
! 	    && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N)
  	  result = sync_resolve_return (first_param, result);
  
  	return result;
--- 9083,9090 ----
  	first_param = VEC_index (tree, params, 0);
  	result = build_function_call_vec (loc, new_function, params, NULL);
  	if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
! 	    && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N
! 	    && orig_code != BUILT_IN_SYNC_MEM_STORE_N)
  	  result = sync_resolve_return (first_param, result);
  
  	return result;
Index: builtin-types.def
===================================================================
*** builtin-types.def	(revision 175331)
--- builtin-types.def	(working copy)
*************** DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_LONGPTR_
*** 315,320 ****
--- 315,327 ----
  		     BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
  DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
  		     BT_BOOL, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_INT, BT_I1, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_INT, BT_I2, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_INT, BT_I4, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_INT, BT_I8, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_INT, BT_I16, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_INT, BT_VOID, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_VPTR_INT, BT_BOOL, BT_VOLATILE_PTR, BT_INT)
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_IN
*** 388,393 ****
--- 395,406 ----
  DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_INT, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_INT, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_INT, BT_I16, BT_VOLATILE_PTR, BT_I16, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I1_INT, BT_VOID, BT_VOLATILE_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT)
+ 
  
  DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
  		     BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
*************** DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_IN
*** 414,419 ****
--- 427,443 ----
  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,
Index: fortran/types.def
===================================================================
*** fortran/types.def	(revision 175331)
--- fortran/types.def	(working copy)
*************** DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, 
*** 85,90 ****
--- 85,92 ----
  DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
  DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
+ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_INT, BT_VOID, BT_INT)
+ 
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
  
*************** DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_I4, B
*** 98,103 ****
--- 100,113 ----
  DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_I8, BT_I8, BT_VOLATILE_PTR, BT_I8)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_I16, BT_I16, BT_VOLATILE_PTR, BT_I16)
  DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTR, BT_VOID, BT_PTR, BT_PTR)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_INT, BT_I1, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_INT, BT_I2, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_INT, BT_I4, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_INT, BT_I8, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_INT, BT_I16, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_INT, BT_VOID, BT_VOLATILE_PTR, BT_INT)
+ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_VPTR_INT, BT_BOOL, BT_VOLATILE_PTR, BT_INT)
+ 
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_
*** 119,131 ****
  		     BT_I16, BT_I16)
  DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
                       BT_PTR, BT_UINT)
- 
  DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_INT, BT_I1, BT_VOLATILE_PTR, BT_I1, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_INT, BT_I2, BT_VOLATILE_PTR, BT_I2, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_INT, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_INT, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_INT, BT_I16, BT_VOLATILE_PTR, BT_I16, BT_INT)
! 
  
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
--- 129,144 ----
  		     BT_I16, BT_I16)
  DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
                       BT_PTR, BT_UINT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_INT, BT_I1, BT_VOLATILE_PTR, BT_I1, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_INT, BT_I2, BT_VOLATILE_PTR, BT_I2, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_INT, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_INT, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_INT)
  DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_INT, BT_I16, BT_VOLATILE_PTR, BT_I16, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I1_INT, BT_VOID, BT_VOLATILE_PTR, BT_I1, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT)
! DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT)
  
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
*************** DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD
*** 135,140 ****
--- 148,163 ----
  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,
Index: sync-builtins.def
===================================================================
*** sync-builtins.def	(revision 175331)
--- sync-builtins.def	(working copy)
*************** DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_EXCH
*** 277,279 ****
--- 277,452 ----
  DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_EXCHANGE_16,
  		  "__sync_mem_exchange_16",
  		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_N,
+ 		  "__sync_mem_load",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_1,
+ 		  "__sync_mem_load_1",
+ 		  BT_FN_I1_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_2,
+ 		  "__sync_mem_load_2",
+ 		  BT_FN_I2_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_4,
+ 		  "__sync_mem_load_4",
+ 		  BT_FN_I4_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_8,
+ 		  "__sync_mem_load_8",
+ 		  BT_FN_I8_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_LOAD_16,
+ 		  "__sync_mem_load_16",
+ 		  BT_FN_I16_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_N,
+ 		  "__sync_mem_compare_exchange",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_1,
+ 		  "__sync_mem_compare_exchange_1",
+ 		  BT_FN_BOOL_VPTR_PTR_I1_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_2,
+ 		  "__sync_mem_compare_exchange_2",
+ 		  BT_FN_BOOL_VPTR_PTR_I2_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_4,
+ 		  "__sync_mem_compare_exchange_4",
+ 		  BT_FN_BOOL_VPTR_PTR_I4_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_8,
+ 		  "__sync_mem_compare_exchange_8",
+ 		  BT_FN_BOOL_VPTR_PTR_I8_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_COMPARE_EXCHANGE_16,
+ 		  "__sync_mem_compare_exchange_16",
+ 		  BT_FN_BOOL_VPTR_PTR_I16_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_N,
+ 		  "__sync_mem_store",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_1,
+ 		  "__sync_mem_store_1",
+ 		  BT_FN_VOID_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_2,
+ 		  "__sync_mem_store_2",
+ 		  BT_FN_VOID_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_4,
+ 		  "__sync_mem_store_4",
+ 		  BT_FN_VOID_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_8,
+ 		  "__sync_mem_store_8",
+ 		  BT_FN_VOID_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_STORE_16,
+ 		  "__sync_mem_store_16",
+ 		  BT_FN_VOID_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_N,
+ 		  "__sync_mem_fetch_add",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_1,
+ 		  "__sync_mem_fetch_add_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_2,
+ 		  "__sync_mem_fetch_add_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_4,
+ 		  "__sync_mem_fetch_add_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_8,
+ 		  "__sync_mem_fetch_add_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_ADD_16,
+ 		  "__sync_mem_fetch_add_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_N,
+ 		  "__sync_mem_fetch_sub",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_1,
+ 		  "__sync_mem_fetch_sub_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_2,
+ 		  "__sync_mem_fetch_sub_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_4,
+ 		  "__sync_mem_fetch_sub_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_8,
+ 		  "__sync_mem_fetch_sub_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_SUB_16,
+ 		  "__sync_mem_fetch_sub_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_N,
+ 		  "__sync_mem_fetch_and",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_1,
+ 		  "__sync_mem_fetch_and_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_2,
+ 		  "__sync_mem_fetch_and_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_4,
+ 		  "__sync_mem_fetch_and_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_8,
+ 		  "__sync_mem_fetch_and_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_AND_16,
+ 		  "__sync_mem_fetch_and_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_N,
+ 		  "__sync_mem_fetch_xor",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_1,
+ 		  "__sync_mem_fetch_xor_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_2,
+ 		  "__sync_mem_fetch_xor_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_4,
+ 		  "__sync_mem_fetch_xor_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_8,
+ 		  "__sync_mem_fetch_xor_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_XOR_16,
+ 		  "__sync_mem_fetch_xor_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_N,
+ 		  "__sync_mem_fetch_or",
+ 		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_1,
+ 		  "__sync_mem_fetch_or_1",
+ 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_2,
+ 		  "__sync_mem_fetch_or_2",
+ 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_4,
+ 		  "__sync_mem_fetch_or_4",
+ 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_8,
+ 		  "__sync_mem_fetch_or_8",
+ 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FETCH_OR_16,
+ 		  "__sync_mem_fetch_or_16",
+ 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FLAG_TEST_AND_SET,
+ 		  "__sync_mem_flag_test_and_set",
+ 		  BT_FN_BOOL_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_FLAG_CLEAR,
+ 		  "__sync_mem_flag_clear",
+ 		  BT_FN_VOID_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_THREAD_FENCE,
+ 		  "__sync_mem_thread_fence",
+ 		  BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+ 
+ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_MEM_SIGNAL_FENCE,
+ 		  "__sync_mem_signal_fence",
+ 		  BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+ 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [cxx-mem-model]  __sync_mem builtin support patch 2/3 - code
  2011-07-27 18:50   ` Andrew MacLeod
@ 2011-07-27 21:40     ` Richard Henderson
  0 siblings, 0 replies; 4+ messages in thread
From: Richard Henderson @ 2011-07-27 21:40 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, Aldy Hernandez

On 07/27/2011 11:17 AM, Andrew MacLeod wrote:
> On 07/27/2011 12:03 PM, Richard Henderson wrote:
>> Please disable the relevant tests too.
> sure.
> 
>>>      if ((icode != CODE_FOR_nothing)&&  (model == MEMMODEL_SEQ_CST ||
>>>                         model == MEMMODEL_ACQ_REL))
>>> + #ifdef HAVE_sync_mem_thread_fence
>>> +     emit_mem_thread_fence (model);
>>> + #else
>>>        expand_builtin_sync_synchronize ();
>>> + #endif
>> Coding style requires braces here.  Yes, only one of the two
>> functions are called, but that's not immediately obvious to
>> the eye.
>>
>> Lots of other instances in your new code.
>>
>> That said, why wouldn't emit_mem_thread_fence always exist
>> and generate the expand_builtin_sync_synchronize as needed?
> 
> Done after a chat with you sorting it out.. I added an expand_builtin_mem_thread_fence() routine which does just this, much cleaner :-)
> 
> I also noticed that all the expand_builtin_sync_mem_ flag and fence routines (4 in total) were all not quite correct. none of them would actually use a pattern if it was defined, so I changed them a bit to do that.  They were basically the set which did not have a TYPE modifier, so didnt have entries in the direct_optab table, so were missing out.
> 
> Rest is done.  Patch is attached in case you want to look at the changes.

Looks ok.


r~

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-07-27 21:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-27  5:31 [cxx-mem-model] __sync_mem builtin support patch 2/3 - code Andrew MacLeod
2011-07-27 16:14 ` Richard Henderson
2011-07-27 18:50   ` Andrew MacLeod
2011-07-27 21:40     ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).