public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add atomic type qualifier
@ 2013-07-26 17:18 Andrew MacLeod
  2013-07-26 19:24 ` Andi Kleen
                   ` (4 more replies)
  0 siblings, 5 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-26 17:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: hp

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

This patch adds an atomic type qualifier to GCC.   It can be accessed 
via __attribute__((atomic)) or in C11 mode via the _Atomic keyword.

What it does:
  *  All the __atomic builtins now expect an atomic qualified value for 
the atomic variable.  Non-atomic values can still be passed in, but they 
are not guaranteed to work if the original type is not compatible with 
the atomic type  No fears.  At the moment, every target's atomic types 
line up with the unsigned type of the same size, so like magic, its all 
good for existing code.
  *  There is a new target hook "atomic_align_for_mode" which a target 
can use to override the default alignment when the atomic variation 
requires something different.   There may be other attributes 
eventually, but for now alignment is the only thing supported.  I 
considered size, but the effort to do that is what drove me to the 
re-architecture project :-P  At least the mechanism is now in place for 
overrides when atomic requirements aren't just the default it use to be. 
    (I introduced atomicQI_type_node, atomicHI_type_node,  
atomicSI_type_node,  atomicDI_type_node, atomicTI_type_node, ).  I 
tested this by aligning all shorts to 32 byte boundaries and 
bootstrapping/running all the tests.
  * I went through the front ends trying to treat  atomic qualifier 
mostly like a volatile, since thats is the basic behaviour one expects.  
In the backend, it sets the TREE_IS_VOLATILE bit so behaviour ought to 
be the same as before, plus they are/will be always used in 
__atomic_built-in functions.
  * I changed the libstdc++ atomic implementation so that all the atomic 
classes use __attribute__((atomic)) on their data members, ensuring that 
if anyone overrides the atomic type, it should work fine with C++ 
atomics.   It also served as a good test that I had the type set up 
properly... getting TYPE_CANONICAL() correct throughout the C++ compiler 
was, well..., lets just say painful.
* I changed 2 of the atomic test sets, one uses __attribute__((atomic)) 
to ensure the attribute compiles ok, and the other uses _Atomic and 
--std=c11 to ensure that compiles OK.

What it doesn't do:
   * It doesn't implement the C11 expression expansion into atomic 
built-ins.  ie, you can't write:
_Atomic int x;
  x = 0;
       and have the result be an atomic operation calling __atomic_store 
(&x, 0).   That will be in a  follow on patch. So none of the expression 
expansion from C11 is included yet. This just enables that.
  * It doesn't do a full set of checks when _Atomic is used in invalid 
ways.  I don't know the standard nor the front end well enough.. Im 
hoping someone else will pitch in with that eventually, assuming someone 
cares enough :-)  There are a couple of errors issued, but that is it.

This bootstraps on x86_64, and passes all the testsuites with no new 
regressions.  I didnt split it up any more than this because most of it 
is inter-related... plus this is already split out from a much larger 
set of changes :-) I did try to at least organize the ordering, all the 
long boring stuff is at the end :-)

Both front end and back end stuff in here.  I think I caught it all, but 
have a look. There is time to find any remaining issues I may have missed.

Andrew


HP, you might want to give this a try and see if you can get the 
alignment correct for the cris port finally :-)
Basically, on x86 I tried it with the following 2 snippets which aligned 
atomic short int on 256 bit boundaries, and it bootstrapped and passed 
all the test suites like that as well:

in ix86_option_override_internal():
    targetm.atomic_align_for_mode = atomic_align_override;

And then provided:

static unsigned int
atomic_align_override (enum machine_mode mode)
{
   if (mode == HImode)
     return 256;
   return 0;
}





[-- Attachment #2: attr-last.diff --]
[-- Type: text/x-patch, Size: 113418 bytes --]


	gcc
	* tree.h (struct tree_base): Add atomic_flag field.
	(TYPE_ATOMIC): New accessor macro.
	(enum cv_qualifier): Add TYPE_QUAL_ATOMIC.
	(TYPE_QUALS, TYPE_QUALS_NO_ADDR_SPACE): Add TYPE_QUAL_ATOMIC.
	(TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC): New macro.
	(enum tree_index): Add TI_ATOMIC{QHSDT}I_TYPE.
	(atomic{QHSDT}I_type_node): Add new type nodes.
	* emit-rtl.c (set_mem_attributes_minus_bitpos): Atomics are volatile.
	* function.c (assign_stack_temp_for_type): Atomics are volatile.
	* hooks.c (hook_uint_mode_0): Return 0 unit hook.
	* hooks.h (hook_uint_mode_0): Prototype.
	* target.def (atomic_align_for_mode): define hook.
	* print-tree.c (print_node): Print atomic qualifier.
	* tree-pretty-print.c (dump_generic_node): Print atomic type attribute.
	* tree.c (set_type_quals): Set TYPE_ATOMIC.
	(find_atomic_base_type): New.  Function to get atomic base from size.
	(build_qualified_type): Tweak for atomic qualifier overrides.
	(build_atomic_variant): New.  Build atomic variant node.
	(build_common_tree_nodes): Build atomic{QHSDT}I_type_node, allowing
	for override with target hook.
	* alias.c (objects_must_conflict_p): Treat atomics as volatile.
	* calls.c (expand_call): Treat atomics as volatile.

	c-family
	* c-common.h (enum rid): Add RID_ATOMIC.
	* c-common.c (struct c_common_resword c_common_r): Add "_Atomic".
	(struct attribute_spec c_common_att): Add "atomic" attribute.
	(handle_atomic_attribute): New.  Add atomic qualifier to type.
	(sync_resolve_params): Use MAIN_VARIANT as cast for the non-atomic
	parameters.
	(keyword_is_type_qualifier): Add RID_ATOMIC;
	* c-format.c (check_format_types): Add atomic as a qualifer check.
	* c-pretty-print.c (pp_c_cv_qualifiers): Handle atomic qualifier.

	c
	* c-tree.h (struct c_declspecs): Add atomic_p field.
	* c-aux-info.c (gen_type): Handle atomic qualifier.
	* c-decl.c (shadow_tag_warned): Add atomic_p to declspecs check.
	(quals_from_declspecs): Add atomic_p to declspecs check.
	(grokdeclarator): Check atomic and warn of duplicate or errors.
	(build_null_declspecs): Handle atomic_p.
	(declspecs_add_qual): Handle RID_ATOMIC.
	* c-parser.c (c_token_starts_typename): Add RID_ATOMIC.
	(c_token_is_qualifier, c_token_starts_declspecs): Add RID_ATOMIC.
	(c_parser_declspecs, c_parser_attribute_any_word): Add RID_ATOMIC.
	* c-typeck.c (build_indirect_ref): Treat atomic as volatile.
	(build_array_ref, convert_for_assignment): Treat atomic as volatile.

	objc
	* objc-act.c (objc_push_parm): Treat atomic as volatile.

	cp
	* cp-tree.h (CP_TYPE_ATOMIC_P): New macro.
	(enum cp_decl_spec): Add ds_atomic.
	* class.c (build_simple_base_path): Treat atomic as volatile.
	* cvt.c (diagnose_ref_binding): Handle atomic.
	(convert_from_reference, convert_to_void): Treat atomic as volatile.
	* decl.c (grokfndecl): Treat atomic as volatile.
	(build_ptrmemfunc_type): Set TYPE_ATOMIC.
	(grokdeclarator): handle atomic qualifier.
	* mangle.c (dump_substitution_candidates): Add atomic to the qualifier
	list.
	* parser.c (cp_parser_type_specifier): Handle RID_ATOMIC.
	(cp_parser_cv_qualifier_seq_opt): Handle RID_ATOMIC.
	(set_and_check_decl_spec_loc): Add atomic to decl_spec_names[].
	* pt.c (check_cv_quals_for_unify): Add TYPE_QUAL_ATOMIC to check.
	* rtti.c (qualifier_flags): Set atomic qualifier flag.
	* semantics.c (non_const_var_error): Check CP_TYPE_ATOMIC_P too.
	* tree.c (cp_build_qualified_type_real): Add TYPE_QUAL_ATOMIC.
	(cv_unqualified): Add TYPE_QUAL_ATOMIC to mask.
	* typeck.c (build_class_member_access_expr): Treat atomic as volatile.
	(cp_build_indirect_ref, cp_build_array_ref): Treat atomic as volatile.
	(check_return_expr, cp_type_quals): Treat atomic as volatile.
	(cv_qualified_p): Add TYPE_QUAL_ATOMIC to mask.

	libstdc++-v3
	* include/bits/atomic_base.h (struct __atomic_base): Add
	__attribute__((atomic) to member data element.
	(struct __atomic_base<_PTp*>): Add __attribute__((atomic)) to member
	data element.
	* include/std/atomic (struct atomic): Add __attribute__((atomic)) to
	member data element.

	fortran
	* types.def (BT_ATOMIC_PTR, BT_CONST_ATOMIC_PTR): New
	primitive data types for volatile atomic pointers.
	(BT_FN_VOID_APTR): Renamed from BT_FN_VOID_VPTR.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT,
	BT_FN_BOOL_SIZE_CONST_VPTR): Renamed to APTR variant.
	(BT_FN_I{1,2,4,8,16}_CONST_APTR_INT): New.
	(BT_FN_I{1,2,4,8,16}_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT,
	BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, 
	BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_BOOL_INT_INT): Renamed to APTR
	variant.

	gcc
	* builtin-types.def (BT_ATOMIC_PTR, BT_CONST_ATOMIC_PTR): New
	primitive data types for volatile atomic pointers.
	(BT_FN_VOID_APTR): Renamed from BT_FN_VOID_VPTR.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT,
	BT_FN_BOOL_SIZE_CONST_VPTR): Renamed to APTR variant.
	(BT_FN_I{1,2,4,8,16}_CONST_APTR_INT): New.
	(BT_FN_I{1,2,4,8,16}_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT,
	BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, 
	BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_BOOL_INT_INT): Renamed to APTR
	variant.
	* sync-builtins.def: Change all __atomic builtins to use the APTR
	atomic pointer variant for the first parameter instead of VPTR..

	doc
	* generic.texi (CP_TYPE_ATOMIC_P): Document.
	* tm.texi (TARGET_ATOMIC_TYPE_FOR_MODE): Define.
	* doc/tm.texi.in (TARGET_ATOMIC_TYPE_FOR_MODE): Add.

	testsuite
	* gcc.dg/atomic-exchange-{1-5}.c: Change atomic var to use
	__attribute__((atomic)).
	* gcc.dg/atomic-op-{1-5}.c: Add --std=c11 and change atomic var to
	use _Atomic keyword.






Index: gcc/tree.h
===================================================================
*** gcc/tree.h	(revision 201248)
--- gcc/tree.h	(working copy)
*************** struct GTY(()) tree_base {
*** 457,463 ****
        unsigned packed_flag : 1;
        unsigned user_align : 1;
        unsigned nameless_flag : 1;
!       unsigned spare0 : 4;
  
        unsigned spare1 : 8;
  
--- 457,464 ----
        unsigned packed_flag : 1;
        unsigned user_align : 1;
        unsigned nameless_flag : 1;
!       unsigned atomic_flag : 1;
!       unsigned spare0 : 3;
  
        unsigned spare1 : 8;
  
*************** extern enum machine_mode vector_type_mod
*** 2205,2210 ****
--- 2206,2214 ----
  /* Nonzero in a type considered volatile as a whole.  */
  #define TYPE_VOLATILE(NODE) (TYPE_CHECK (NODE)->base.volatile_flag)
  
+ /* Nonzero in a type considered atomic as a whole.  */
+ #define TYPE_ATOMIC(NODE) (TYPE_CHECK (NODE)->base.u.bits.atomic_flag)
+ 
  /* Means this type is const-qualified.  */
  #define TYPE_READONLY(NODE) (TYPE_CHECK (NODE)->base.readonly_flag)
  
*************** enum cv_qualifier
*** 2226,2232 ****
      TYPE_UNQUALIFIED   = 0x0,
      TYPE_QUAL_CONST    = 0x1,
      TYPE_QUAL_VOLATILE = 0x2,
!     TYPE_QUAL_RESTRICT = 0x4
    };
  
  /* Encode/decode the named memory support as part of the qualifier.  If more
--- 2230,2237 ----
      TYPE_UNQUALIFIED   = 0x0,
      TYPE_QUAL_CONST    = 0x1,
      TYPE_QUAL_VOLATILE = 0x2,
!     TYPE_QUAL_RESTRICT = 0x4,
!     TYPE_QUAL_ATOMIC   = 0x8
    };
  
  /* Encode/decode the named memory support as part of the qualifier.  If more
*************** enum cv_qualifier
*** 2245,2250 ****
--- 2250,2256 ----
  #define TYPE_QUALS(NODE)					\
    ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)		\
  	  | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
+ 	  | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC)		\
  	  | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)		\
  	  | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE)))))
  
*************** enum cv_qualifier
*** 2252,2259 ****
--- 2258,2273 ----
  #define TYPE_QUALS_NO_ADDR_SPACE(NODE)				\
    ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)		\
  	  | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
+ 	  | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC)		\
+ 	  | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
+ /* The same as TYPE_QUALS without the address space and atomic 
+    qualifications.  */
+ #define TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC(NODE)		\
+   ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)		\
+ 	  | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
  	  | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
  
+ 
  /* These flags are available for each language front end to use internally.  */
  #define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_0)
  #define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_1)
*************** enum tree_index
*** 4178,4183 ****
--- 4192,4203 ----
    TI_UINTDI_TYPE,
    TI_UINTTI_TYPE,
  
+   TI_ATOMICQI_TYPE,
+   TI_ATOMICHI_TYPE,
+   TI_ATOMICSI_TYPE,
+   TI_ATOMICDI_TYPE,
+   TI_ATOMICTI_TYPE,
+ 
    TI_UINT16_TYPE,
    TI_UINT32_TYPE,
    TI_UINT64_TYPE,
*************** extern GTY(()) tree global_trees[TI_MAX]
*** 4334,4339 ****
--- 4354,4365 ----
  #define unsigned_intDI_type_node	global_trees[TI_UINTDI_TYPE]
  #define unsigned_intTI_type_node	global_trees[TI_UINTTI_TYPE]
  
+ #define atomicQI_type_node	global_trees[TI_ATOMICQI_TYPE]
+ #define atomicHI_type_node	global_trees[TI_ATOMICHI_TYPE]
+ #define atomicSI_type_node	global_trees[TI_ATOMICSI_TYPE]
+ #define atomicDI_type_node	global_trees[TI_ATOMICDI_TYPE]
+ #define atomicTI_type_node	global_trees[TI_ATOMICTI_TYPE]
+ 
  #define uint16_type_node		global_trees[TI_UINT16_TYPE]
  #define uint32_type_node		global_trees[TI_UINT32_TYPE]
  #define uint64_type_node		global_trees[TI_UINT64_TYPE]
*************** extern tree build_aligned_type (tree, un
*** 5101,5106 ****
--- 5127,5135 ----
  extern tree build_distinct_type_copy (tree);
  extern tree build_variant_type_copy (tree);
  
+ /* Find an atomic base type.  */
+ extern tree find_atomic_base_type (tree, tree *);
+ 
  /* Finish up a builtin RECORD_TYPE. Give it a name and provide its
     fields. Optionally specify an alignment, and then lay it out.  */
  
Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c	(revision 201248)
--- gcc/emit-rtl.c	(working copy)
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1607,1613 ****
       front-end routine) and use it.  */
    attrs.alias = get_alias_set (t);
  
!   MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
    MEM_POINTER (ref) = POINTER_TYPE_P (type);
  
    /* Default values from pre-existing memory attributes if present.  */
--- 1607,1613 ----
       front-end routine) and use it.  */
    attrs.alias = get_alias_set (t);
  
!   MEM_VOLATILE_P (ref) |= (TYPE_VOLATILE (type) || TYPE_ATOMIC (type));
    MEM_POINTER (ref) = POINTER_TYPE_P (type);
  
    /* Default values from pre-existing memory attributes if present.  */
Index: gcc/function.c
===================================================================
*** gcc/function.c	(revision 201248)
--- gcc/function.c	(working copy)
*************** assign_stack_temp_for_type (enum machine
*** 901,907 ****
  
    /* If a type is specified, set the relevant flags.  */
    if (type != 0)
!     MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
    MEM_NOTRAP_P (slot) = 1;
  
    return slot;
--- 901,907 ----
  
    /* If a type is specified, set the relevant flags.  */
    if (type != 0)
!     MEM_VOLATILE_P (slot) = (TYPE_VOLATILE (type) || TYPE_ATOMIC (type));
    MEM_NOTRAP_P (slot) = 1;
  
    return slot;
Index: gcc/hooks.c
===================================================================
*** gcc/hooks.c	(revision 201248)
--- gcc/hooks.c	(working copy)
*************** hook_rtx_tree_int_null (tree a ATTRIBUTE
*** 352,357 ****
--- 352,364 ----
    return NULL;
  }
  
+ /* Generic hook that takes a machine mode and returns an unsigned int 0.  */
+ unsigned int
+ hook_uint_mode_0 (enum machine_mode m ATTRIBUTE_UNUSED)
+ {
+   return 0;
+ }
+ 
  /* Generic hook that takes three trees and returns the last one as is.  */
  tree
  hook_tree_tree_tree_tree_3rd_identity (tree a ATTRIBUTE_UNUSED,
Index: gcc/hooks.h
===================================================================
*** gcc/hooks.h	(revision 201248)
--- gcc/hooks.h	(working copy)
*************** extern tree hook_tree_tree_tree_tree_3rd
*** 89,94 ****
--- 89,95 ----
  extern tree hook_tree_tree_int_treep_bool_null (tree, int, tree *, bool);
  
  extern unsigned hook_uint_void_0 (void);
+ extern unsigned int hook_uint_mode_0 (enum machine_mode);
  
  extern bool default_can_output_mi_thunk_no_vcall (const_tree, HOST_WIDE_INT,
  						  HOST_WIDE_INT, const_tree);
Index: gcc/target.def
===================================================================
*** gcc/target.def	(revision 201248)
--- gcc/target.def	(working copy)
*************** DEFHOOKPOD
*** 5116,5122 ****
   @code{atomic_test_and_set} is not exactly 1, i.e. the\
   @code{bool} @code{true}.",
   unsigned char, 1)
!  
  /* Leave the boolean fields at the end.  */
  
  /* True if we can create zeroed data by switching to a BSS section
--- 5116,5133 ----
   @code{atomic_test_and_set} is not exactly 1, i.e. the\
   @code{bool} @code{true}.",
   unsigned char, 1)
! 
! /* Return a tree type representing the atomic type which maps to machine MODE.
!    This allows both alignment and size to be overridden as needed.  */
! DEFHOOK
! (atomic_align_for_mode,
! "If defined, this function returns an appropriate alignment in bits for an\
!  atomic object of machine_mode @var{mode}.  If 0 is returned then the\
!  default alignment for the specified mode is used. ",
!  unsigned int, (enum machine_mode mode),
!  hook_uint_mode_0)
! 
! 
  /* Leave the boolean fields at the end.  */
  
  /* True if we can create zeroed data by switching to a BSS section
Index: gcc/print-tree.c
===================================================================
*** gcc/print-tree.c	(revision 201248)
--- gcc/print-tree.c	(working copy)
*************** print_node (FILE *file, const char *pref
*** 304,309 ****
--- 304,311 ----
  
    if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node))
      fputs (" readonly", file);
+   if (TYPE_P (node) ? TYPE_ATOMIC (node) : TYPE_ATOMIC (node))
+     fputs (" atomic", file);
    if (!TYPE_P (node) && TREE_CONSTANT (node))
      fputs (" constant", file);
    else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
Index: gcc/tree-pretty-print.c
===================================================================
*** gcc/tree-pretty-print.c	(revision 201248)
--- gcc/tree-pretty-print.c	(working copy)
*************** dump_generic_node (pretty_printer *buffe
*** 679,684 ****
--- 679,686 ----
  	unsigned int quals = TYPE_QUALS (node);
  	enum tree_code_class tclass;
  
+ 	if (quals & TYPE_QUAL_ATOMIC)
+ 	  pp_string (buffer, "atomic ");
  	if (quals & TYPE_QUAL_CONST)
  	  pp_string (buffer, "const ");
  	else if (quals & TYPE_QUAL_VOLATILE)
*************** dump_generic_node (pretty_printer *buffe
*** 980,985 ****
--- 982,989 ----
        {
  	unsigned int quals = TYPE_QUALS (node);
  
+ 	if (quals & TYPE_QUAL_ATOMIC)
+ 	  pp_string (buffer, "atomic ");
  	if (quals & TYPE_QUAL_CONST)
  	  pp_string (buffer, "const ");
  	if (quals & TYPE_QUAL_VOLATILE)
Index: gcc/tree.c
===================================================================
*** gcc/tree.c	(revision 201248)
--- gcc/tree.c	(working copy)
*************** set_type_quals (tree type, int type_qual
*** 5937,5942 ****
--- 5937,5943 ----
    TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
    TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
    TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+   TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
    TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
  }
  
*************** check_aligned_type (const_tree cand, con
*** 5970,5975 ****
--- 5971,6027 ----
  				   TYPE_ATTRIBUTES (base)));
  }
  
+ /* This function checks to see if TYPE matches the size one of the built in 
+    atomic types, and returns that atomic type.
+    The non-atomic base type is also returned if NONATOMIC_TYPE is non-NULL.  */
+ 
+ tree
+ find_atomic_base_type (tree type, tree *nonatomic_type)
+ {
+   tree base_type, base_atomic_type;
+ 
+   if (!TYPE_P (type) || type == void_type_node)
+     return NULL_TREE;
+ 
+   HOST_WIDE_INT type_size = tree_low_cst (TYPE_SIZE (type), 1);
+   switch (type_size)
+     {
+     case 8:
+       base_atomic_type = atomicQI_type_node;
+       base_type = unsigned_intQI_type_node;
+       break;
+ 
+     case 16:
+       base_atomic_type = atomicHI_type_node;
+       base_type = unsigned_intHI_type_node;
+       break;
+ 
+     case 32:
+       base_atomic_type = atomicSI_type_node;
+       base_type = unsigned_intSI_type_node;
+       break;
+ 
+     case 64:
+       base_atomic_type = atomicDI_type_node;
+       base_type = unsigned_intDI_type_node;
+       break;
+ 
+     case 128:
+       base_atomic_type = atomicTI_type_node;
+       base_type = unsigned_intTI_type_node;
+       break;
+ 
+     default:
+       base_atomic_type = NULL_TREE;
+       base_type = NULL_TREE;
+     }
+ 
+   if (nonatomic_type)
+     *nonatomic_type = base_type;
+ 
+   return base_atomic_type;
+ }
+ 
  /* Return a version of the TYPE, qualified as indicated by the
     TYPE_QUALS, if one exists.  If no qualified version exists yet,
     return NULL_TREE.  */
*************** build_qualified_type (tree type, int typ
*** 6009,6014 ****
--- 6061,6074 ----
        t = build_variant_type_copy (type);
        set_type_quals (t, type_quals);
  
+       if (((type_quals & TYPE_QUAL_ATOMIC) == TYPE_QUAL_ATOMIC)
+ 	  && INTEGRAL_TYPE_P (type))
+ 	{
+ 	  tree atomic_base_type = find_atomic_base_type (type, NULL);
+ 	  if (atomic_base_type)
+ 	    TYPE_ALIGN (t) = TYPE_ALIGN (atomic_base_type);
+ 	}
+ 
        if (TYPE_STRUCTURAL_EQUALITY_P (type))
  	/* Propagate structural equality. */
  	SET_TYPE_STRUCTURAL_EQUALITY (t);
*************** make_or_reuse_accum_type (unsigned size,
*** 9521,9526 ****
--- 9581,9611 ----
    return make_accum_type (size, unsignedp, satp);
  }
  
+ 
+ /* Create an atomic variant node for TYPE.  This routine is called during
+    initialization of data types to create the 5 basic atomic types. The generic
+    build_variant_type function requires these to already be set up in order to
+    function properly, so cannot be called from there.  
+    if ALIGN is non-zero, then ensure alignment is overridden to this value.  */
+ 
+ static tree
+ build_atomic_variant (tree type, unsigned int align)
+ {
+   tree t;
+ 
+   /* Make sure its not already registered.  */
+   if ((t = get_qualified_type (type, TYPE_QUAL_ATOMIC)))
+     return t;
+   
+   t = build_variant_type_copy (type);
+   set_type_quals (t, TYPE_QUAL_ATOMIC);
+ 
+   if (align)
+     TYPE_ALIGN (t) = align;
+ 
+   return t;
+ }
+ 
  /* Create nodes for all integer types (and error_mark_node) using the sizes
     of C datatypes.  SIGNED_CHAR specifies whether char is signed,
     SHORT_DOUBLE specifies whether double should be of the same precision
*************** build_common_tree_nodes (bool signed_cha
*** 9603,9608 ****
--- 9688,9708 ----
    unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
    unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
  
+   /* Dont call build_qualified type for atomics.  That routine does special
+      processing for atomics, and until they are initialized its better not
+      to make that call.  
+      
+      Check to see if there is a target override for atomic types.  */
+ 
+ #define SET_ATOMIC_TYPE_NODE(TYPE, MODE, DEFAULT) 		\
+  (TYPE) = build_atomic_variant (DEFAULT, targetm.atomic_align_for_mode (MODE));
+ 
+   SET_ATOMIC_TYPE_NODE (atomicQI_type_node, QImode, unsigned_intQI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicHI_type_node, HImode, unsigned_intHI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicSI_type_node, SImode, unsigned_intSI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicDI_type_node, DImode, unsigned_intDI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicTI_type_node, TImode, unsigned_intTI_type_node);
+ 
    access_public_node = get_identifier ("public");
    access_protected_node = get_identifier ("protected");
    access_private_node = get_identifier ("private");
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 201248)
--- gcc/alias.c	(working copy)
*************** objects_must_conflict_p (tree t1, tree t
*** 487,493 ****
    /* If they are the same type, they must conflict.  */
    if (t1 == t2
        /* Likewise if both are volatile.  */
!       || (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2)))
      return 1;
  
    set1 = t1 ? get_alias_set (t1) : 0;
--- 487,494 ----
    /* If they are the same type, they must conflict.  */
    if (t1 == t2
        /* Likewise if both are volatile.  */
!       || (t1 != 0 && (TYPE_VOLATILE (t1) || TYPE_ATOMIC (t1)) 
! 	  && t2 != 0 && (TYPE_VOLATILE (t2) || TYPE_ATOMIC (t2))))
      return 1;
  
    set1 = t1 ? get_alias_set (t1) : 0;
Index: gcc/calls.c
===================================================================
*** gcc/calls.c	(revision 201248)
--- gcc/calls.c	(working copy)
*************** expand_call (tree exp, rtx target, int i
*** 2592,2597 ****
--- 2592,2598 ----
  	 optimized.  */
        || (flags & (ECF_RETURNS_TWICE | ECF_NORETURN))
        || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr)))
+       || TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (addr)))
        /* If the called function is nested in the current one, it might access
  	 some of the caller's arguments, but could clobber them beforehand if
  	 the argument areas are shared.  */
Index: gcc/c-family/c-common.h
===================================================================
*** gcc/c-family/c-common.h	(revision 201248)
--- gcc/c-family/c-common.h	(working copy)
*************** enum rid
*** 66,72 ****
    RID_UNSIGNED, RID_LONG,    RID_CONST, RID_EXTERN,
    RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
    RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
!   RID_NORETURN,
  
    /* C extensions */
    RID_COMPLEX, RID_THREAD, RID_SAT,
--- 66,72 ----
    RID_UNSIGNED, RID_LONG,    RID_CONST, RID_EXTERN,
    RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
    RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
!   RID_NORETURN, RID_ATOMIC,
  
    /* C extensions */
    RID_COMPLEX, RID_THREAD, RID_SAT,
Index: gcc/c-family/c-common.c
===================================================================
*** gcc/c-family/c-common.c	(revision 201248)
--- gcc/c-family/c-common.c	(working copy)
*************** static tree handle_unused_attribute (tre
*** 325,330 ****
--- 325,331 ----
  static tree handle_externally_visible_attribute (tree *, tree, tree, int,
  						 bool *);
  static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_atomic_attribute (tree *, tree, tree, int, bool *);
  static tree handle_transparent_union_attribute (tree *, tree, tree,
  						int, bool *);
  static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
*************** const struct c_common_resword c_common_r
*** 401,406 ****
--- 402,408 ----
  {
    { "_Alignas",		RID_ALIGNAS,   D_CONLY },
    { "_Alignof",		RID_ALIGNOF,   D_CONLY },
+   { "_Atomic",		RID_ATOMIC,    D_CONLY },
    { "_Bool",		RID_BOOL,      D_CONLY },
    { "_Complex",		RID_COMPLEX,	0 },
    { "_Imaginary",	RID_IMAGINARY, D_CONLY },
*************** const struct attribute_spec c_common_att
*** 637,642 ****
--- 639,646 ----
    /* The same comments as for noreturn attributes apply to const ones.  */
    { "const",                  0, 0, true,  false, false,
  			      handle_const_attribute, false },
+   { "atomic",		      0, 0, false, true, false,
+ 			      handle_atomic_attribute, false},
    { "transparent_union",      0, 0, false, false, false,
  			      handle_transparent_union_attribute, false },
    { "constructor",            0, 1, true,  false, false,
*************** handle_const_attribute (tree *node, tree
*** 6842,6847 ****
--- 6846,6879 ----
    return NULL_TREE;
  }
  
+ 
+ /* Handle an "atomic" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ 
+ static tree
+ handle_atomic_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ 			int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   bool ignored = true;
+   if (TYPE_P (*node) && TREE_CODE (*node) != ARRAY_TYPE)
+     {
+       tree type = *node;
+ 
+       if (!TYPE_ATOMIC (type))
+ 	{
+ 	  *node = build_qualified_type (type, TYPE_QUAL_ATOMIC);
+ 	  ignored = false;
+ 	}
+     }
+ 
+   if (ignored)
+     {
+       warning (OPT_Wattributes, "%qE attribute ignored", name);
+       *no_add_attrs = true;
+     }
+   return NULL_TREE;
+ }
+ 
  /* Handle a "transparent_union" attribute; arguments as in
     struct attribute_spec.handler.  */
  
*************** sync_resolve_params (location_t loc, tre
*** 10012,10022 ****
    unsigned int parmnum;
  
    function_args_iter_init (&iter, TREE_TYPE (function));
!   /* We've declared the implementation functions to use "volatile void *"
       as the pointer parameter, so we shouldn't get any complaints from the
       call to check_function_arguments what ever type the user used.  */
    function_args_iter_next (&iter);
    ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
  
    /* For the rest of the values, we need to cast these to FTYPE, so that we
       don't get warnings for passing pointer types, etc.  */
--- 10044,10055 ----
    unsigned int parmnum;
  
    function_args_iter_init (&iter, TREE_TYPE (function));
!   /* We've declared the implementation functions to use "atomic volatile void *"
       as the pointer parameter, so we shouldn't get any complaints from the
       call to check_function_arguments what ever type the user used.  */
    function_args_iter_next (&iter);
    ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
+   ptype = TYPE_MAIN_VARIANT (ptype);
  
    /* For the rest of the values, we need to cast these to FTYPE, so that we
       don't get warnings for passing pointer types, etc.  */
*************** keyword_is_type_qualifier (enum rid keyw
*** 11388,11393 ****
--- 11421,11427 ----
      case RID_CONST:
      case RID_VOLATILE:
      case RID_RESTRICT:
+     case RID_ATOMIC:
        return true;
      default:
        return false;
Index: gcc/c-family/c-format.c
===================================================================
*** gcc/c-family/c-format.c	(revision 201248)
--- gcc/c-family/c-format.c	(working copy)
*************** check_format_types (format_wanted_type *
*** 2374,2379 ****
--- 2374,2380 ----
  		  && pedantic
  		  && (TYPE_READONLY (cur_type)
  		      || TYPE_VOLATILE (cur_type)
+ 		      || TYPE_ATOMIC (cur_type)
  		      || TYPE_RESTRICT (cur_type)))
  		warning (OPT_Wformat_, "extra type qualifiers in format "
  			 "argument (argument %d)",
Index: gcc/c-family/c-pretty-print.c
===================================================================
*** gcc/c-family/c-pretty-print.c	(revision 201248)
--- gcc/c-family/c-pretty-print.c	(working copy)
*************** pp_c_cv_qualifiers (c_pretty_printer *pp
*** 186,193 ****
--- 186,201 ----
    if (p != NULL && (*p == '*' || *p == '&'))
      pp_c_whitespace (pp);
  
+   if (qualifiers & TYPE_QUAL_ATOMIC)
+     {
+       pp_c_ws_string (pp, func_type ? "__attribute__((atomic))" : "atomic");
+       previous = true;
+     }
+ 
    if (qualifiers & TYPE_QUAL_CONST)
      {
+       if (previous)
+         pp_c_whitespace (pp);
        pp_c_ws_string (pp, func_type ? "__attribute__((const))" : "const");
        previous = true;
      }
Index: gcc/c/c-tree.h
===================================================================
*** gcc/c/c-tree.h	(revision 201248)
--- gcc/c/c-tree.h	(working copy)
*************** struct c_declspecs {
*** 328,333 ****
--- 328,335 ----
    BOOL_BITFIELD volatile_p : 1;
    /* Whether "restrict" was specified.  */
    BOOL_BITFIELD restrict_p : 1;
+   /* Whether "_Atomic" was specified.  */
+   BOOL_BITFIELD atomic_p : 1;
    /* Whether "_Sat" was specified.  */
    BOOL_BITFIELD saturating_p : 1;
    /* Whether any alignment specifier (even with zero alignment) was
Index: gcc/c/c-aux-info.c
===================================================================
*** gcc/c/c-aux-info.c	(revision 201248)
--- gcc/c/c-aux-info.c	(working copy)
*************** gen_type (const char *ret_val, tree t, f
*** 285,290 ****
--- 285,292 ----
        switch (TREE_CODE (t))
  	{
  	case POINTER_TYPE:
+ 	  if (TYPE_ATOMIC (t))
+ 	    ret_val = concat ("atomic ", ret_val, NULL);
  	  if (TYPE_READONLY (t))
  	    ret_val = concat ("const ", ret_val, NULL);
  	  if (TYPE_VOLATILE (t))
*************** gen_type (const char *ret_val, tree t, f
*** 425,430 ****
--- 427,434 ----
  	  gcc_unreachable ();
  	}
      }
+   if (TYPE_ATOMIC (t))
+     ret_val = concat ("atomic ", ret_val, NULL);
    if (TYPE_READONLY (t))
      ret_val = concat ("const ", ret_val, NULL);
    if (TYPE_VOLATILE (t))
Index: gcc/c/c-decl.c
===================================================================
*** gcc/c/c-decl.c	(revision 201248)
--- gcc/c/c-decl.c	(working copy)
*************** shadow_tag_warned (const struct c_declsp
*** 3712,3717 ****
--- 3712,3718 ----
                     && declspecs->typespec_kind != ctsk_tagfirstref
  		   && (declspecs->const_p
  		       || declspecs->volatile_p
+ 		       || declspecs->atomic_p
  		       || declspecs->restrict_p
  		       || declspecs->address_space))
  	    {
*************** shadow_tag_warned (const struct c_declsp
*** 3801,3806 ****
--- 3802,3808 ----
  
    if (!warned && !in_system_header && (declspecs->const_p
  				       || declspecs->volatile_p
+ 				       || declspecs->atomic_p
  				       || declspecs->restrict_p
  				       || declspecs->address_space))
      {
*************** quals_from_declspecs (const struct c_dec
*** 3832,3837 ****
--- 3834,3840 ----
    int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
  	       | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
  	       | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+ 	       | (specs->atomic_p ? TYPE_QUAL_ATOMIC : 0)
  	       | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
    gcc_assert (!specs->type
  	      && !specs->decl_attr
*************** grokdeclarator (const struct c_declarato
*** 4911,4916 ****
--- 4914,4920 ----
    int constp;
    int restrictp;
    int volatilep;
+   int atomicp;
    int type_quals = TYPE_UNQUALIFIED;
    tree name = NULL_TREE;
    bool funcdef_flag = false;
*************** grokdeclarator (const struct c_declarato
*** 5065,5070 ****
--- 5069,5075 ----
    constp = declspecs->const_p + TYPE_READONLY (element_type);
    restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
    volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+   atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type);
    as1 = declspecs->address_space;
    as2 = TYPE_ADDR_SPACE (element_type);
    address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
*************** grokdeclarator (const struct c_declarato
*** 5077,5082 ****
--- 5082,5090 ----
  	pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
        if (volatilep > 1)
  	pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
+       if (atomicp > 1)
+ 	pedwarn (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
+ 
      }
  
    if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
*************** grokdeclarator (const struct c_declarato
*** 5090,5095 ****
--- 5098,5104 ----
    type_quals = ((constp ? TYPE_QUAL_CONST : 0)
  		| (restrictp ? TYPE_QUAL_RESTRICT : 0)
  		| (volatilep ? TYPE_QUAL_VOLATILE : 0)
+ 		| (atomicp ? TYPE_QUAL_ATOMIC : 0)
  		| ENCODE_QUAL_ADDR_SPACE (address_space));
  
    /* Warn about storage classes that are invalid for certain
*************** grokdeclarator (const struct c_declarato
*** 5560,5565 ****
--- 5569,5580 ----
  		array_ptr_attrs = NULL_TREE;
  		array_parm_static = 0;
  	      }
+ 
+ 	    if (atomicp)
+ 	      {
+ 		error_at (loc, "_Atomic type qualifier in array declarator");
+ 		type = error_mark_node;
+ 	      }
  	    break;
  	  }
  	case cdk_function:
*************** grokdeclarator (const struct c_declarato
*** 5651,5656 ****
--- 5666,5676 ----
  	      FOR_EACH_VEC_SAFE_ELT_REVERSE (arg_info->tags, ix, tag)
  		TYPE_CONTEXT (tag->type) = type;
  	    }
+ 	    if (atomicp)
+ 	      {
+ 		error_at (loc, "_Atomic type qualifier in function declarator");
+ 		type = error_mark_node;
+ 	      }
  	    break;
  	  }
  	case cdk_pointer:
*************** build_null_declspecs (void)
*** 8825,8830 ****
--- 8845,8851 ----
    ret->thread_p = false;
    ret->const_p = false;
    ret->volatile_p = false;
+   ret->atomic_p = false;
    ret->restrict_p = false;
    ret->saturating_p = false;
    ret->alignas_p = false;
*************** declspecs_add_qual (source_location loc,
*** 8886,8891 ****
--- 8907,8916 ----
        specs->restrict_p = true;
        specs->locations[cdw_restrict] = loc;
        break;
+     case RID_ATOMIC:
+       dupe = specs->atomic_p;
+       specs->atomic_p = true;
+       break;
      default:
        gcc_unreachable ();
      }
Index: gcc/c/c-parser.c
===================================================================
*** gcc/c/c-parser.c	(revision 201248)
--- gcc/c/c-parser.c	(working copy)
*************** c_token_starts_typename (c_token *token)
*** 489,494 ****
--- 489,495 ----
  	case RID_UNION:
  	case RID_TYPEOF:
  	case RID_CONST:
+ 	case RID_ATOMIC:
  	case RID_VOLATILE:
  	case RID_RESTRICT:
  	case RID_ATTRIBUTE:
*************** c_token_is_qualifier (c_token *token)
*** 571,576 ****
--- 572,578 ----
  	case RID_VOLATILE:
  	case RID_RESTRICT:
  	case RID_ATTRIBUTE:
+ 	case RID_ATOMIC:
  	  return true;
  	default:
  	  return false;
*************** c_token_starts_declspecs (c_token *token
*** 651,656 ****
--- 653,659 ----
  	case RID_ACCUM:
  	case RID_SAT:
  	case RID_ALIGNAS:
+ 	case RID_ATOMIC:
  	  return true;
  	default:
  	  return false;
*************** c_parser_static_assert_declaration_no_se
*** 1948,1955 ****
--- 1951,1960 ----
       restrict
       volatile
       address-space-qualifier
+      atomic
  
     (restrict is new in C99.)
+    (atomic is new in C11.)
  
     GNU extensions:
  
*************** c_parser_declspecs (c_parser *parser, st
*** 2171,2176 ****
--- 2176,2185 ----
  	  t = c_parser_typeof_specifier (parser);
  	  declspecs_add_type (loc, specs, t);
  	  break;
+ 	case RID_ATOMIC:
+ 	  if (!flag_isoc11)
+ 	    pedwarn (loc, 0, "_Atomic qualifier provided in ISO C11");
+ 	  /* Fallthru.  */
  	case RID_CONST:
  	case RID_VOLATILE:
  	case RID_RESTRICT:
*************** c_parser_attribute_any_word (c_parser *p
*** 3487,3492 ****
--- 3496,3502 ----
  	case RID_SAT:
  	case RID_TRANSACTION_ATOMIC:
  	case RID_TRANSACTION_CANCEL:
+ 	case RID_ATOMIC:
  	  ok = true;
  	  break;
  	default:
Index: gcc/c/c-typeck.c
===================================================================
*** gcc/c/c-typeck.c	(revision 201248)
--- gcc/c/c-typeck.c	(working copy)
*************** build_indirect_ref (location_t loc, tree
*** 2268,2276 ****
  	  /* A de-reference of a pointer to const is not a const.  It is valid
  	     to change it via some other pointer.  */
  	  TREE_READONLY (ref) = TYPE_READONLY (t);
! 	  TREE_SIDE_EFFECTS (ref)
! 	    = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
! 	  TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
  	  protected_set_expr_location (ref, loc);
  	  return ref;
  	}
--- 2268,2276 ----
  	  /* A de-reference of a pointer to const is not a const.  It is valid
  	     to change it via some other pointer.  */
  	  TREE_READONLY (ref) = TYPE_READONLY (t);
! 	  TREE_SIDE_EFFECTS (ref) = (TYPE_VOLATILE (t) || TYPE_ATOMIC (t)
! 				     || TREE_SIDE_EFFECTS (pointer));
! 	  TREE_THIS_VOLATILE (ref) = (TYPE_VOLATILE (t) || TYPE_ATOMIC (t));
  	  protected_set_expr_location (ref, loc);
  	  return ref;
  	}
*************** build_array_ref (location_t loc, tree ar
*** 2408,2416 ****
--- 2408,2418 ----
  	    | TREE_READONLY (array));
        TREE_SIDE_EFFECTS (rval)
  	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+ 	    | TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (array)))
  	    | TREE_SIDE_EFFECTS (array));
        TREE_THIS_VOLATILE (rval)
  	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+ 	    | TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (array)))
  	    /* This was added by rms on 16 Nov 91.
  	       It fixes  vol struct foo *a;  a->elts[1]
  	       in an inline function.
*************** convert_for_assignment (location_t locat
*** 5578,5585 ****
  	  else if (TREE_CODE (ttr) != FUNCTION_TYPE
  		   && TREE_CODE (ttl) != FUNCTION_TYPE)
  	    {
! 	      if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
! 		  & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
  		{
  		  WARN_FOR_QUALIFIERS (location, 0,
  				       G_("passing argument %d of %qE discards "
--- 5580,5589 ----
  	  else if (TREE_CODE (ttr) != FUNCTION_TYPE
  		   && TREE_CODE (ttl) != FUNCTION_TYPE)
  	    {
! 	      /* Assignments between atomic and non-atomic objects are OK since
! 	         the atomic access is always through an interface call.  */
! 	      if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
! 		  & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
  		{
  		  WARN_FOR_QUALIFIERS (location, 0,
  				       G_("passing argument %d of %qE discards "
Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c	(revision 201248)
--- gcc/objc/objc-act.c	(working copy)
*************** objc_push_parm (tree parm)
*** 8244,8249 ****
--- 8244,8250 ----
    c_apply_type_quals_to_decl
    ((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
     | (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
+    | (TYPE_ATOMIC (TREE_TYPE (parm)) ? TYPE_QUAL_ATOMIC : 0)
     | (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
  
    objc_parmlist = chainon (objc_parmlist, parm);
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h	(revision 201248)
--- gcc/cp/cp-tree.h	(working copy)
*************** enum languages { lang_c, lang_cplusplus,
*** 1293,1298 ****
--- 1293,1302 ----
  #define CP_TYPE_VOLATILE_P(NODE)			\
    ((cp_type_quals (NODE) & TYPE_QUAL_VOLATILE) != 0)
  
+ /* Nonzero if this type is atomic-qualified.  */
+ #define CP_TYPE_ATOMIC_P(NODE)				\
+   ((cp_type_quals (NODE) & TYPE_QUAL_ATOMIC) != 0)
+ 
  /* Nonzero if this type is restrict-qualified.  */
  #define CP_TYPE_RESTRICT_P(NODE)			\
    ((cp_type_quals (NODE) & TYPE_QUAL_RESTRICT) != 0)
*************** typedef enum cp_decl_spec {
*** 4758,4763 ****
--- 4762,4768 ----
    ds_const,
    ds_volatile,
    ds_restrict,
+   ds_atomic,
    ds_inline,
    ds_virtual,
    ds_explicit,
Index: gcc/cp/class.c
===================================================================
*** gcc/cp/class.c	(revision 201248)
--- gcc/cp/class.c	(working copy)
*************** build_simple_base_path (tree expr, tree
*** 542,548 ****
  	   to mark the expression itself.  */
  	if (type_quals & TYPE_QUAL_CONST)
  	  TREE_READONLY (expr) = 1;
! 	if (type_quals & TYPE_QUAL_VOLATILE)
  	  TREE_THIS_VOLATILE (expr) = 1;
  
  	return expr;
--- 542,548 ----
  	   to mark the expression itself.  */
  	if (type_quals & TYPE_QUAL_CONST)
  	  TREE_READONLY (expr) = 1;
! 	if (type_quals & (TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
  	  TREE_THIS_VOLATILE (expr) = 1;
  
  	return expr;
Index: gcc/cp/cvt.c
===================================================================
*** gcc/cp/cvt.c	(revision 201248)
--- gcc/cp/cvt.c	(working copy)
*************** diagnose_ref_binding (location_t loc, tr
*** 385,390 ****
--- 385,396 ----
        else if (CP_TYPE_VOLATILE_P (ttl))
  	msg = G_("conversion to volatile reference type %q#T "
  	         "from rvalue of type %qT");
+       else if (CP_TYPE_ATOMIC_P (ttl) && decl)
+ 	msg = G_("initialization of atomic reference type %q#T from "
+ 	         "rvalue of type %qT");
+       else if (CP_TYPE_ATOMIC_P (ttl))
+ 	msg = G_("conversion to atomic reference type %q#T "
+ 	         "from rvalue of type %qT");
        else if (decl)
  	msg = G_("initialization of non-const reference type %q#T from "
  	         "rvalue of type %qT");
*************** convert_from_reference (tree val)
*** 537,543 ****
  	  so that we get the proper error message if the result is used
  	  to assign to.  Also, &* is supposed to be a no-op.  */
        TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
!       TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
        TREE_SIDE_EFFECTS (ref)
  	= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
        val = ref;
--- 543,550 ----
  	  so that we get the proper error message if the result is used
  	  to assign to.  Also, &* is supposed to be a no-op.  */
        TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
!       TREE_THIS_VOLATILE (ref) = (CP_TYPE_VOLATILE_P (t) 
! 				  || CP_TYPE_ATOMIC_P (t));
        TREE_SIDE_EFFECTS (ref)
  	= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
        val = ref;
*************** convert_to_void (tree expr, impl_conv_vo
*** 1010,1016 ****
  	tree type = TREE_TYPE (expr);
  	int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
  			   == REFERENCE_TYPE;
! 	int is_volatile = TYPE_VOLATILE (type);
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
  	/* Can't load the value if we don't know the type.  */
--- 1017,1023 ----
  	tree type = TREE_TYPE (expr);
  	int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
  			   == REFERENCE_TYPE;
! 	int is_volatile = (TYPE_VOLATILE (type) || TYPE_ATOMIC (type));
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
  	/* Can't load the value if we don't know the type.  */
*************** convert_to_void (tree expr, impl_conv_vo
*** 1170,1176 ****
  	tree type = TREE_TYPE (expr);
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
! 	if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning))
  	  switch (implicit)
  	    {
  	      case ICV_CAST:
--- 1177,1184 ----
  	tree type = TREE_TYPE (expr);
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
! 	if ((TYPE_VOLATILE (type) || TYPE_ATOMIC (type))
! 	    && !is_complete && (complain & tf_warning))
  	  switch (implicit)
  	    {
  	      case ICV_CAST:
Index: gcc/cp/decl.c
===================================================================
*** gcc/cp/decl.c	(revision 201248)
--- gcc/cp/decl.c	(working copy)
*************** grokfndecl (tree ctype,
*** 7368,7374 ****
    for (t = parms; t; t = DECL_CHAIN (t))
      DECL_CONTEXT (t) = decl;
    /* Propagate volatile out from type to decl.  */
!   if (TYPE_VOLATILE (type))
      TREE_THIS_VOLATILE (decl) = 1;
  
    /* Setup decl according to sfk.  */
--- 7368,7374 ----
    for (t = parms; t; t = DECL_CHAIN (t))
      DECL_CONTEXT (t) = decl;
    /* Propagate volatile out from type to decl.  */
!   if (TYPE_VOLATILE (type) || TYPE_ATOMIC (type))
      TREE_THIS_VOLATILE (decl) = 1;
  
    /* Setup decl according to sfk.  */
*************** build_ptrmemfunc_type (tree type)
*** 7984,7989 ****
--- 7984,7990 ----
        TYPE_READONLY (t) = (type_quals & TYPE_QUAL_CONST) != 0;
        TYPE_VOLATILE (t) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
        TYPE_RESTRICT (t) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+       TYPE_ATOMIC (t) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
        TYPE_MAIN_VARIANT (t) = unqualified_variant;
        TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
        TYPE_NEXT_VARIANT (unqualified_variant) = t;
*************** grokdeclarator (const cp_declarator *dec
*** 9199,9204 ****
--- 9200,9207 ----
      type_quals |= TYPE_QUAL_VOLATILE;
    if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
      type_quals |= TYPE_QUAL_RESTRICT;
+   if (decl_spec_seq_has_spec_p (declspecs, ds_atomic))
+     type_quals |= TYPE_QUAL_ATOMIC;
    if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
      error ("qualifiers are not allowed on declaration of %<operator %T%>",
  	   ctor_return_type);
Index: gcc/cp/mangle.c
===================================================================
*** gcc/cp/mangle.c	(revision 201248)
--- gcc/cp/mangle.c	(working copy)
*************** dump_substitution_candidates (void)
*** 326,331 ****
--- 326,332 ----
        if (TYPE_P (el) &&
  	  (CP_TYPE_RESTRICT_P (el)
  	   || CP_TYPE_VOLATILE_P (el)
+ 	   || CP_TYPE_ATOMIC_P (el)
  	   || CP_TYPE_CONST_P (el)))
  	fprintf (stderr, "CV-");
        fprintf (stderr, "%s (%s at %p)\n",
Index: gcc/cp/parser.c
===================================================================
*** gcc/cp/parser.c	(revision 201248)
--- gcc/cp/parser.c	(working copy)
*************** cp_parser_type_specifier (cp_parser* par
*** 14090,14095 ****
--- 14090,14103 ----
  	*is_cv_qualifier = true;
        break;
  
+     case RID_ATOMIC:
+       ds = ds_atomic;
+       if (is_cv_qualifier)
+ 	*is_cv_qualifier = true;
+       if (!flag_isoc11)
+         pedwarn (token->location, 0, "_Atomic qualifier provided in ISO C11");
+       break;
+ 
      case RID_RESTRICT:
        ds = ds_restrict;
        if (is_cv_qualifier)
*************** cp_parser_cv_qualifier_seq_opt (cp_parse
*** 17341,17346 ****
--- 17349,17358 ----
  	  cv_qualifier = TYPE_QUAL_RESTRICT;
  	  break;
  
+ 	case RID_ATOMIC:
+ 	  cv_qualifier = TYPE_QUAL_ATOMIC;
+ 	  break;
+ 
  	default:
  	  cv_qualifier = TYPE_UNQUALIFIED;
  	  break;
*************** set_and_check_decl_spec_loc (cp_decl_spe
*** 23477,23482 ****
--- 23489,23495 ----
  	    "const",
  	    "volatile",
  	    "restrict",
+ 	    "atomic"
  	    "inline",
  	    "virtual",
  	    "explicit",
Index: gcc/cp/pt.c
===================================================================
*** gcc/cp/pt.c	(revision 201248)
--- gcc/cp/pt.c	(working copy)
*************** check_cv_quals_for_unify (int strict, tr
*** 16375,16381 ****
        if ((TREE_CODE (arg) == REFERENCE_TYPE
  	   || TREE_CODE (arg) == FUNCTION_TYPE
  	   || TREE_CODE (arg) == METHOD_TYPE)
! 	  && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)))
  	return 0;
  
        if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
--- 16375,16382 ----
        if ((TREE_CODE (arg) == REFERENCE_TYPE
  	   || TREE_CODE (arg) == FUNCTION_TYPE
  	   || TREE_CODE (arg) == METHOD_TYPE)
! 	  && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE 
! 			    | TYPE_QUAL_ATOMIC)))
  	return 0;
  
        if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
Index: gcc/cp/rtti.c
===================================================================
*** gcc/cp/rtti.c	(revision 201248)
--- gcc/cp/rtti.c	(working copy)
*************** qualifier_flags (tree type)
*** 808,813 ****
--- 808,815 ----
      flags |= 2;
    if (quals & TYPE_QUAL_RESTRICT)
      flags |= 4;
+   if (quals & TYPE_QUAL_ATOMIC)
+     flags |= 8;
    return flags;
  }
  
Index: gcc/cp/semantics.c
===================================================================
*** gcc/cp/semantics.c	(revision 201248)
--- gcc/cp/semantics.c	(working copy)
*************** non_const_var_error (tree r)
*** 7776,7781 ****
--- 7776,7784 ----
        else if (CP_TYPE_VOLATILE_P (type))
  	inform (DECL_SOURCE_LOCATION (r),
  		"%q#D is volatile", r);
+       else if (CP_TYPE_ATOMIC_P (type))
+ 	inform (DECL_SOURCE_LOCATION (r),
+ 		"%q#D is atomic", r);
        else if (!DECL_INITIAL (r)
  	       || !TREE_CONSTANT (DECL_INITIAL (r)))
  	inform (DECL_SOURCE_LOCATION (r),
Index: gcc/cp/tree.c
===================================================================
*** gcc/cp/tree.c	(revision 201248)
--- gcc/cp/tree.c	(working copy)
*************** cp_build_qualified_type_real (tree type,
*** 1059,1072 ****
    /* A reference or method type shall not be cv-qualified.
       [dcl.ref], [dcl.fct].  This used to be an error, but as of DR 295
       (in CD1) we always ignore extra cv-quals on functions.  */
!   if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
        && (TREE_CODE (type) == REFERENCE_TYPE
  	  || TREE_CODE (type) == FUNCTION_TYPE
  	  || TREE_CODE (type) == METHOD_TYPE))
      {
        if (TREE_CODE (type) == REFERENCE_TYPE)
! 	bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
!       type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
      }
  
    /* But preserve any function-cv-quals on a FUNCTION_TYPE.  */
--- 1059,1073 ----
    /* A reference or method type shall not be cv-qualified.
       [dcl.ref], [dcl.fct].  This used to be an error, but as of DR 295
       (in CD1) we always ignore extra cv-quals on functions.  */
!   if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC)
        && (TREE_CODE (type) == REFERENCE_TYPE
  	  || TREE_CODE (type) == FUNCTION_TYPE
  	  || TREE_CODE (type) == METHOD_TYPE))
      {
        if (TREE_CODE (type) == REFERENCE_TYPE)
! 	bad_quals |= type_quals 
! 		    & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC);
!       type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC);
      }
  
    /* But preserve any function-cv-quals on a FUNCTION_TYPE.  */
*************** cv_unqualified (tree type)
*** 1142,1148 ****
      return type;
  
    quals = cp_type_quals (type);
!   quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
    return cp_build_qualified_type (type, quals);
  }
  
--- 1143,1149 ----
      return type;
  
    quals = cp_type_quals (type);
!   quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC);
    return cp_build_qualified_type (type, quals);
  }
  
Index: gcc/cp/typeck.c
===================================================================
*** gcc/cp/typeck.c	(revision 201248)
--- gcc/cp/typeck.c	(working copy)
*************** build_class_member_access_expr (tree obj
*** 2417,2423 ****
  	 expression itself.  */
        if (type_quals & TYPE_QUAL_CONST)
  	TREE_READONLY (result) = 1;
!       if (type_quals & TYPE_QUAL_VOLATILE)
  	TREE_THIS_VOLATILE (result) = 1;
      }
    else if (BASELINK_P (member))
--- 2417,2423 ----
  	 expression itself.  */
        if (type_quals & TYPE_QUAL_CONST)
  	TREE_READONLY (result) = 1;
!       if (type_quals & (TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
  	TREE_THIS_VOLATILE (result) = 1;
      }
    else if (BASELINK_P (member))
*************** cp_build_indirect_ref (tree ptr, ref_ope
*** 2941,2947 ****
  	     so that we get the proper error message if the result is used
  	     to assign to.  Also, &* is supposed to be a no-op.  */
  	  TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! 	  TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
  	  TREE_SIDE_EFFECTS (ref)
  	    = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
  	  return ref;
--- 2941,2948 ----
  	     so that we get the proper error message if the result is used
  	     to assign to.  Also, &* is supposed to be a no-op.  */
  	  TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! 	  TREE_THIS_VOLATILE (ref) = (CP_TYPE_VOLATILE_P (t) 
! 				      || CP_TYPE_ATOMIC_P (t));
  	  TREE_SIDE_EFFECTS (ref)
  	    = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
  	  return ref;
*************** cp_build_array_ref (location_t loc, tree
*** 3126,3134 ****
        TREE_READONLY (rval)
  	|= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
        TREE_SIDE_EFFECTS (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
        TREE_THIS_VOLATILE (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
        ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
  					  complain);
        protected_set_expr_location (ret, loc);
--- 3127,3137 ----
        TREE_READONLY (rval)
  	|= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
        TREE_SIDE_EFFECTS (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array)
! 	    | CP_TYPE_ATOMIC_P (type));
        TREE_THIS_VOLATILE (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array)
! 	    | CP_TYPE_ATOMIC_P (type));
        ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
  					  complain);
        protected_set_expr_location (ret, loc);
*************** check_return_expr (tree retval, bool *no
*** 8423,8429 ****
       && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
                       (TYPE_MAIN_VARIANT (functype)))
       /* And the returned value must be non-volatile.  */
!      && ! TYPE_VOLATILE (TREE_TYPE (retval)));
       
    if (fn_returns_value_p && flag_elide_constructors)
      {
--- 8426,8433 ----
       && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
                       (TYPE_MAIN_VARIANT (functype)))
       /* And the returned value must be non-volatile.  */
!      && ! TYPE_VOLATILE (TREE_TYPE (retval)) 
!      && ! TYPE_ATOMIC (TREE_TYPE (retval)));
       
    if (fn_returns_value_p && flag_elide_constructors)
      {
*************** cp_type_quals (const_tree type)
*** 8691,8697 ****
    /* METHOD and REFERENCE_TYPEs should never have quals.  */
    gcc_assert ((TREE_CODE (type) != METHOD_TYPE
  	       && TREE_CODE (type) != REFERENCE_TYPE)
! 	      || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))
  		  == TYPE_UNQUALIFIED));
    return quals;
  }
--- 8695,8701 ----
    /* METHOD and REFERENCE_TYPEs should never have quals.  */
    gcc_assert ((TREE_CODE (type) != METHOD_TYPE
  	       && TREE_CODE (type) != REFERENCE_TYPE)
! 	    || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
  		  == TYPE_UNQUALIFIED));
    return quals;
  }
*************** bool
*** 8751,8757 ****
  cv_qualified_p (const_tree type)
  {
    int quals = cp_type_quals (type);
!   return (quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE)) != 0;
  }
  
  /* Returns nonzero if the TYPE contains a mutable member.  */
--- 8755,8761 ----
  cv_qualified_p (const_tree type)
  {
    int quals = cp_type_quals (type);
!   return (quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC)) != 0;
  }
  
  /* Returns nonzero if the TYPE contains a mutable member.  */
Index: libstdc++-v3/include/bits/atomic_base.h
===================================================================
*** libstdc++-v3/include/bits/atomic_base.h	(revision 201248)
--- libstdc++-v3/include/bits/atomic_base.h	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 346,361 ****
    // atomic_char32_t char32_t
    // atomic_wchar_t  wchar_t
    //
!   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
!   // 8 bytes, since that is what GCC built-in functions for atomic
    // memory access expect.
    template<typename _ITp>
      struct __atomic_base
      {
      private:
!       typedef _ITp 	__int_type;
  
!       __int_type 	_M_i;
  
      public:
        __atomic_base() noexcept = default;
--- 346,362 ----
    // atomic_char32_t char32_t
    // atomic_wchar_t  wchar_t
    //
!   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, 8, or
!   // 16 bytes, since that is what GCC built-in functions for atomic
    // memory access expect.
    template<typename _ITp>
      struct __atomic_base
      {
      private:
!       typedef _ITp 				__int_type;
!       typedef _ITp __attribute__ ((atomic))	__atomic_int_type;
  
!       __atomic_int_type _M_i;
  
      public:
        __atomic_base() noexcept = default;
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 669,677 ****
      struct __atomic_base<_PTp*>
      {
      private:
!       typedef _PTp* 	__pointer_type;
  
!       __pointer_type 	_M_p;
  
        // Factored out to facilitate explicit specialization.
        constexpr ptrdiff_t
--- 670,679 ----
      struct __atomic_base<_PTp*>
      {
      private:
!       typedef _PTp* 				__pointer_type;
!       typedef _PTp* __attribute ((atomic)) 	__atomic_pointer_type;
  
!       __atomic_pointer_type 	_M_p;
  
        // Factored out to facilitate explicit specialization.
        constexpr ptrdiff_t
Index: libstdc++-v3/include/std/atomic
===================================================================
*** libstdc++-v3/include/std/atomic	(revision 201248)
--- libstdc++-v3/include/std/atomic	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 161,167 ****
      struct atomic
      {
      private:
!       _Tp _M_i;
  
      public:
        atomic() noexcept = default;
--- 161,167 ----
      struct atomic
      {
      private:
!       _Tp __attribute ((atomic)) _M_i;
  
      public:
        atomic() noexcept = default;
Index: gcc/fortran/types.def
===================================================================
*** gcc/fortran/types.def	(revision 201248)
--- gcc/fortran/types.def	(working copy)
*************** DEF_PRIMITIVE_TYPE (BT_CONST_VOLATILE_PT
*** 74,79 ****
--- 74,87 ----
  		    build_pointer_type
  		     (build_qualified_type (void_type_node,
  					  TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST)))
+ DEF_PRIMITIVE_TYPE (BT_ATOMIC_PTR,
+                     build_pointer_type
+                      (build_qualified_type (void_type_node,
+                                           TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC)))
+ DEF_PRIMITIVE_TYPE (BT_CONST_ATOMIC_PTR,
+                     build_pointer_type
+                      (build_qualified_type (void_type_node,
+                           TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST|TYPE_QUAL_ATOMIC)))
  DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG)
  DEF_POINTER_TYPE (BT_PTR_ULONGLONG, BT_ULONGLONG)
  DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR)
*************** DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_VPTR
*** 113,122 ****
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_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_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR)
  
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
--- 121,140 ----
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_VOLATILE_PTR,
  		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I1_CONST_APTR_INT, BT_I1, BT_CONST_ATOMIC_PTR, 
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I2_CONST_APTR_INT, BT_I2, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I4_CONST_APTR_INT, BT_I4, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_APTR_INT, BT_I8, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_APTR_INT, BT_I16, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_VOID_APTR_INT, BT_VOID, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_APTR_INT, BT_BOOL, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_APTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR)
  
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_IN
*** 144,169 ****
  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_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR, BT_PTR, BT_INT)
  
  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_VOID_SIZE_VPTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, 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,
--- 162,197 ----
  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_I1_APTR_I1_INT, BT_I1, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I2_APTR_I2_INT, BT_I2, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I4_APTR_I4_INT, BT_I4, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I8_APTR_I8_INT, BT_I8, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I16_APTR_I16_INT, BT_I16, BT_ATOMIC_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_3 (BT_FN_VOID_APTR_I1_INT, BT_VOID, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I2_INT, BT_VOID, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I4_INT, BT_VOID, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I8_INT, BT_VOID, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I16_INT, BT_VOID, BT_ATOMIC_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_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR, BT_PTR, BT_INT)
  
  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_VOID_SIZE_APTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, 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,
*************** DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PT
*** 174,196 ****
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
--- 202,224 ----
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_APTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
Index: gcc/builtin-types.def
===================================================================
*** gcc/builtin-types.def	(revision 201248)
--- gcc/builtin-types.def	(working copy)
*************** DEF_PRIMITIVE_TYPE (BT_CONST_VOLATILE_PT
*** 99,104 ****
--- 99,112 ----
  		    build_pointer_type
  		     (build_qualified_type (void_type_node,
  					  TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST)))
+ DEF_PRIMITIVE_TYPE (BT_ATOMIC_PTR,
+ 		    build_pointer_type
+ 		     (build_qualified_type (void_type_node,
+ 					  TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC)))
+ DEF_PRIMITIVE_TYPE (BT_CONST_ATOMIC_PTR,
+ 		    build_pointer_type
+ 		     (build_qualified_type (void_type_node,
+ 			  TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST|TYPE_QUAL_ATOMIC)))
  DEF_PRIMITIVE_TYPE (BT_PTRMODE, (*lang_hooks.types.type_for_mode)(ptr_mode, 0))
  DEF_PRIMITIVE_TYPE (BT_INT_PTR, integer_ptr_type_node)
  DEF_PRIMITIVE_TYPE (BT_FLOAT_PTR, float_ptr_type_node)
*************** DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLO
*** 223,228 ****
--- 231,237 ----
  DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64)
  DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128)
  DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
+ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_APTR, BT_VOID, BT_ATOMIC_PTR)
  DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
  DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG)
*************** DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_VPTR
*** 337,346 ****
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_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_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR)
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
--- 346,365 ----
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_VOLATILE_PTR,
  		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I1_CONST_APTR_INT, BT_I1, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I2_CONST_APTR_INT, BT_I2, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I4_CONST_APTR_INT, BT_I4, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_APTR_INT, BT_I8, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_APTR_INT, BT_I16, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_VOID_APTR_INT, BT_VOID, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_APTR_INT, BT_BOOL, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_APTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR)
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_IN
*** 420,430 ****
--- 439,460 ----
  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_I1_APTR_I1_INT, BT_I1, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I2_APTR_I2_INT, BT_I2, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I4_APTR_I4_INT, BT_I4, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I8_APTR_I8_INT, BT_I8, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I16_APTR_I16_INT, BT_I16, BT_ATOMIC_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_3 (BT_FN_VOID_APTR_I1_INT, BT_VOID, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I2_INT, BT_VOID, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I4_INT, BT_VOID, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I8_INT, BT_VOID, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I16_INT, BT_VOID, BT_ATOMIC_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_4 (BT_FN_VOID_OMPFN_PT
*** 444,453 ****
  		     BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR, BT_PTR, BT_INT)
  
  DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
  		     BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
--- 474,483 ----
  		     BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR, BT_PTR, BT_INT)
  
  DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
  		     BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
*************** DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_IN
*** 455,462 ****
  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_VOID_SIZE_VPTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT)
  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,
--- 485,492 ----
  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_VOID_SIZE_APTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, BT_INT)
  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,
*************** DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PT
*** 480,502 ****
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
--- 510,532 ----
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_APTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
Index: gcc/sync-builtins.def
===================================================================
*** gcc/sync-builtins.def	(revision 201248)
--- gcc/sync-builtins.def	(working copy)
*************** DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SYNCHRON
*** 260,567 ****
  /* __sync* builtins for the C++ memory model.  */
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set",
! 		  BT_FN_BOOL_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
! DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_VPTR_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE,
  		  "__atomic_exchange",
! 		  BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_N,
  		  "__atomic_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_1,
  		  "__atomic_exchange_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_2,
  		  "__atomic_exchange_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_4,
  		  "__atomic_exchange_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_8,
  		  "__atomic_exchange_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_16,
  		  "__atomic_exchange_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD,
  		  "__atomic_load",
! 		  BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_N,
  		  "__atomic_load_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_1,
  		  "__atomic_load_1",
! 		  BT_FN_I1_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_2,
  		  "__atomic_load_2",
! 		  BT_FN_I2_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_4,
  		  "__atomic_load_4",
! 		  BT_FN_I4_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_8,
  		  "__atomic_load_8",
! 		  BT_FN_I8_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_16,
  		  "__atomic_load_16",
! 		  BT_FN_I16_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE,
  		  "__atomic_compare_exchange",
! 		  BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N,
  		  "__atomic_compare_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1,
  		  "__atomic_compare_exchange_1",
! 		  BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2,
  		  "__atomic_compare_exchange_2",
! 		  BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
  		  "__atomic_compare_exchange_4",
! 		  BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
  		  "__atomic_compare_exchange_8",
! 		  BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16,
  		  "__atomic_compare_exchange_16",
! 		  BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE,
  		  "__atomic_store",
! 		  BT_FN_VOID_SIZE_VPTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_N,
  		  "__atomic_store_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_1,
  		  "__atomic_store_1",
! 		  BT_FN_VOID_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_2,
  		  "__atomic_store_2",
! 		  BT_FN_VOID_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_4,
  		  "__atomic_store_4",
! 		  BT_FN_VOID_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_8,
  		  "__atomic_store_8",
! 		  BT_FN_VOID_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_16,
  		  "__atomic_store_16",
! 		  BT_FN_VOID_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_N,
  		  "__atomic_add_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_1,
  		  "__atomic_add_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_2,
  		  "__atomic_add_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_4,
  		  "__atomic_add_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_8,
  		  "__atomic_add_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_16,
  		  "__atomic_add_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_N,
  		  "__atomic_sub_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_1,
  		  "__atomic_sub_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_2,
  		  "__atomic_sub_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_4,
  		  "__atomic_sub_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_8,
  		  "__atomic_sub_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_16,
  		  "__atomic_sub_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_N,
  		  "__atomic_and_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_1,
  		  "__atomic_and_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_2,
  		  "__atomic_and_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_4,
  		  "__atomic_and_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_8,
  		  "__atomic_and_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_16,
  		  "__atomic_and_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_N,
  		  "__atomic_nand_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_1,
  		  "__atomic_nand_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_2,
  		  "__atomic_nand_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_4,
  		  "__atomic_nand_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_8,
  		  "__atomic_nand_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_16,
  		  "__atomic_nand_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_N,
  		  "__atomic_xor_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_1,
  		  "__atomic_xor_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_2,
  		  "__atomic_xor_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_4,
  		  "__atomic_xor_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_8,
  		  "__atomic_xor_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_16,
  		  "__atomic_xor_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_N,
  		  "__atomic_or_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_1,
  		  "__atomic_or_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_2,
  		  "__atomic_or_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_4,
  		  "__atomic_or_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_8,
  		  "__atomic_or_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_16,
  		  "__atomic_or_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_N,
  		  "__atomic_fetch_add",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_1,
  		  "__atomic_fetch_add_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_2,
  		  "__atomic_fetch_add_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_4,
  		  "__atomic_fetch_add_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_8,
  		  "__atomic_fetch_add_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_16,
  		  "__atomic_fetch_add_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_N,
  		  "__atomic_fetch_sub",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_1,
  		  "__atomic_fetch_sub_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_2,
  		  "__atomic_fetch_sub_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_4,
  		  "__atomic_fetch_sub_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_8,
  		  "__atomic_fetch_sub_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_16,
  		  "__atomic_fetch_sub_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_N,
  		  "__atomic_fetch_and",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_1,
  		  "__atomic_fetch_and_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_2,
  		  "__atomic_fetch_and_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_4,
  		  "__atomic_fetch_and_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_8,
  		  "__atomic_fetch_and_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_16,
  		  "__atomic_fetch_and_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_N,
  		  "__atomic_fetch_nand",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_1,
  		  "__atomic_fetch_nand_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_2,
  		  "__atomic_fetch_nand_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_4,
  		  "__atomic_fetch_nand_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_8,
  		  "__atomic_fetch_nand_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_16,
  		  "__atomic_fetch_nand_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_N,
  		  "__atomic_fetch_xor",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_1,
  		  "__atomic_fetch_xor_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_2,
  		  "__atomic_fetch_xor_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_4,
  		  "__atomic_fetch_xor_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_8,
  		  "__atomic_fetch_xor_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_16,
  		  "__atomic_fetch_xor_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_N,
--- 260,567 ----
  /* __sync* builtins for the C++ memory model.  */
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set",
! 		  BT_FN_BOOL_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
! DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_APTR_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE,
  		  "__atomic_exchange",
! 		  BT_FN_VOID_SIZE_APTR_PTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_N,
  		  "__atomic_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_1,
  		  "__atomic_exchange_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_2,
  		  "__atomic_exchange_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_4,
  		  "__atomic_exchange_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_8,
  		  "__atomic_exchange_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_16,
  		  "__atomic_exchange_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD,
  		  "__atomic_load",
! 		  BT_FN_VOID_SIZE_CONST_APTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_N,
  		  "__atomic_load_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_1,
  		  "__atomic_load_1",
! 		  BT_FN_I1_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_2,
  		  "__atomic_load_2",
! 		  BT_FN_I2_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_4,
  		  "__atomic_load_4",
! 		  BT_FN_I4_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_8,
  		  "__atomic_load_8",
! 		  BT_FN_I8_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_16,
  		  "__atomic_load_16",
! 		  BT_FN_I16_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE,
  		  "__atomic_compare_exchange",
! 		  BT_FN_BOOL_SIZE_APTR_PTR_PTR_INT_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N,
  		  "__atomic_compare_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1,
  		  "__atomic_compare_exchange_1",
! 		  BT_FN_BOOL_APTR_PTR_I1_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2,
  		  "__atomic_compare_exchange_2",
! 		  BT_FN_BOOL_APTR_PTR_I2_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
  		  "__atomic_compare_exchange_4",
! 		  BT_FN_BOOL_APTR_PTR_I4_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
  		  "__atomic_compare_exchange_8",
! 		  BT_FN_BOOL_APTR_PTR_I8_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16,
  		  "__atomic_compare_exchange_16",
! 		  BT_FN_BOOL_APTR_PTR_I16_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE,
  		  "__atomic_store",
! 		  BT_FN_VOID_SIZE_APTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_N,
  		  "__atomic_store_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_1,
  		  "__atomic_store_1",
! 		  BT_FN_VOID_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_2,
  		  "__atomic_store_2",
! 		  BT_FN_VOID_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_4,
  		  "__atomic_store_4",
! 		  BT_FN_VOID_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_8,
  		  "__atomic_store_8",
! 		  BT_FN_VOID_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_16,
  		  "__atomic_store_16",
! 		  BT_FN_VOID_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_N,
  		  "__atomic_add_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_1,
  		  "__atomic_add_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_2,
  		  "__atomic_add_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_4,
  		  "__atomic_add_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_8,
  		  "__atomic_add_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_16,
  		  "__atomic_add_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_N,
  		  "__atomic_sub_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_1,
  		  "__atomic_sub_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_2,
  		  "__atomic_sub_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_4,
  		  "__atomic_sub_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_8,
  		  "__atomic_sub_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_16,
  		  "__atomic_sub_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_N,
  		  "__atomic_and_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_1,
  		  "__atomic_and_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_2,
  		  "__atomic_and_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_4,
  		  "__atomic_and_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_8,
  		  "__atomic_and_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_16,
  		  "__atomic_and_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_N,
  		  "__atomic_nand_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_1,
  		  "__atomic_nand_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_2,
  		  "__atomic_nand_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_4,
  		  "__atomic_nand_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_8,
  		  "__atomic_nand_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_16,
  		  "__atomic_nand_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_N,
  		  "__atomic_xor_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_1,
  		  "__atomic_xor_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_2,
  		  "__atomic_xor_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_4,
  		  "__atomic_xor_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_8,
  		  "__atomic_xor_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_16,
  		  "__atomic_xor_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_N,
  		  "__atomic_or_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_1,
  		  "__atomic_or_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_2,
  		  "__atomic_or_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_4,
  		  "__atomic_or_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_8,
  		  "__atomic_or_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_16,
  		  "__atomic_or_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_N,
  		  "__atomic_fetch_add",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_1,
  		  "__atomic_fetch_add_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_2,
  		  "__atomic_fetch_add_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_4,
  		  "__atomic_fetch_add_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_8,
  		  "__atomic_fetch_add_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_16,
  		  "__atomic_fetch_add_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_N,
  		  "__atomic_fetch_sub",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_1,
  		  "__atomic_fetch_sub_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_2,
  		  "__atomic_fetch_sub_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_4,
  		  "__atomic_fetch_sub_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_8,
  		  "__atomic_fetch_sub_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_16,
  		  "__atomic_fetch_sub_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_N,
  		  "__atomic_fetch_and",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_1,
  		  "__atomic_fetch_and_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_2,
  		  "__atomic_fetch_and_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_4,
  		  "__atomic_fetch_and_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_8,
  		  "__atomic_fetch_and_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_16,
  		  "__atomic_fetch_and_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_N,
  		  "__atomic_fetch_nand",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_1,
  		  "__atomic_fetch_nand_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_2,
  		  "__atomic_fetch_nand_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_4,
  		  "__atomic_fetch_nand_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_8,
  		  "__atomic_fetch_nand_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_16,
  		  "__atomic_fetch_nand_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_N,
  		  "__atomic_fetch_xor",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_1,
  		  "__atomic_fetch_xor_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_2,
  		  "__atomic_fetch_xor_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_4,
  		  "__atomic_fetch_xor_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_8,
  		  "__atomic_fetch_xor_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_16,
  		  "__atomic_fetch_xor_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_N,
*************** DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_
*** 569,595 ****
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_1,
  		  "__atomic_fetch_or_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_2,
  		  "__atomic_fetch_or_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_4,
  		  "__atomic_fetch_or_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_8,
  		  "__atomic_fetch_or_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_16,
  		  "__atomic_fetch_or_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE,
  		  "__atomic_always_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_VPTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_IS_LOCK_FREE,
  		  "__atomic_is_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_VPTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_THREAD_FENCE,
--- 569,595 ----
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_1,
  		  "__atomic_fetch_or_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_2,
  		  "__atomic_fetch_or_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_4,
  		  "__atomic_fetch_or_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_8,
  		  "__atomic_fetch_or_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_16,
  		  "__atomic_fetch_or_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE,
  		  "__atomic_always_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_APTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_IS_LOCK_FREE,
  		  "__atomic_is_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_APTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_THREAD_FENCE,
Index: gcc/doc/generic.texi
===================================================================
*** gcc/doc/generic.texi	(revision 201248)
--- gcc/doc/generic.texi	(working copy)
*************** This macro holds if the type is @code{co
*** 2547,2552 ****
--- 2547,2555 ----
  @item CP_TYPE_VOLATILE_P
  This macro holds if the type is @code{volatile}-qualified.
  
+ @item CP_TYPE_ATOMIC_P
+ This macro holds if the type is @code{atomic}-qualified.
+ 
  @item CP_TYPE_RESTRICT_P
  This macro holds if the type is @code{restrict}-qualified.
  
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi	(revision 201248)
--- gcc/doc/tm.texi	(working copy)
*************** It returns true if the target supports G
*** 11375,11377 ****
--- 11375,11381 ----
  The support includes the assembler, linker and dynamic linker.
  The default value of this hook is based on target's libc.
  @end deftypefn
+ 
+ @deftypefn {Target Hook} {unsigned int} TARGET_ATOMIC_ALIGN_FOR_MODE (enum machine_mode @var{mode})
+ If defined, this function returns an appropriate alignment in bits for an atomic object of machine_mode @var{mode}.  If 0 is returned then the default alignment for the specified mode is used. 
+ @end deftypefn
Index: gcc/doc/tm.texi.in
===================================================================
*** gcc/doc/tm.texi.in	(revision 201248)
--- gcc/doc/tm.texi.in	(working copy)
*************** and the associated definitions of those
*** 8415,8417 ****
--- 8415,8419 ----
  @hook TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
  
  @hook TARGET_HAS_IFUNC_P
+ 
+ @hook TARGET_ATOMIC_ALIGN_FOR_MODE
Index: gcc/testsuite/gcc.dg/atomic-exchange-1.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-1.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-1.c	(working copy)
***************
*** 7,13 ****
  
  extern void abort(void);
  
! char v, count, ret;
  
  main ()
  {
--- 7,14 ----
  
  extern void abort(void);
  
! char __attribute__ ((atomic)) v;
! char count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-2.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-2.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-2.c	(working copy)
***************
*** 7,13 ****
  
  extern void abort(void);
  
! short v, count, ret;
  
  main ()
  {
--- 7,14 ----
  
  extern void abort(void);
  
! short __attribute__ ((atomic)) v;
! short count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-3.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-3.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-3.c	(working copy)
***************
*** 7,13 ****
  
  extern void abort(void);
  
! int v, count, ret;
  
  main ()
  {
--- 7,14 ----
  
  extern void abort(void);
  
! int __attribute__ ((atomic)) v;
! int count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-4.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-4.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-4.c	(working copy)
***************
*** 9,15 ****
  
  extern void abort(void);
  
! long long v, count, ret;
  
  main ()
  {
--- 9,16 ----
  
  extern void abort(void);
  
! long long __attribute__ ((atomic)) v;
! long long count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-5.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-5.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-5.c	(working copy)
***************
*** 8,14 ****
  
  extern void abort(void);
  
! __int128_t v, count, ret;
  
  main ()
  {
--- 8,15 ----
  
  extern void abort(void);
  
! __int128_t __attribute__ ((atomic)) v;
! __int128_t count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-op-1.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-1.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-1.c	(working copy)
***************
*** 1,13 ****
  /* Test __atomic routines for existence and proper execution on 1 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_char_short } */
  
  /* Test the execution of the __atomic_*OP builtin routines for a char.  */
  
  extern void abort(void);
  
! char v, count, res;
  const char init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 1,15 ----
  /* Test __atomic routines for existence and proper execution on 1 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_char_short } */
  
  /* Test the execution of the __atomic_*OP builtin routines for a char.  */
  
  extern void abort(void);
  
! _Atomic char v;
! char count, res;
  const char init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 527,532 ****
--- 529,535 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-2.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-2.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-2.c	(working copy)
***************
*** 1,6 ****
--- 1,7 ----
  /* Test __atomic routines for existence and proper execution on 2 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_char_short } */
  
  
***************
*** 8,14 ****
  
  extern void abort(void);
  
! short v, count, res;
  const short init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 9,16 ----
  
  extern void abort(void);
  
! _Atomic short v;
! short count, res;
  const short init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 528,533 ****
--- 530,536 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-3.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-3.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-3.c	(working copy)
***************
*** 1,13 ****
  /* Test __atomic routines for existence and proper execution on 4 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_int_long } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int.  */
  
  extern void abort(void);
  
! int v, count, res;
  const int init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 1,15 ----
  /* Test __atomic routines for existence and proper execution on 4 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_int_long } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int.  */
  
  extern void abort(void);
  
! _Atomic int v;
! int count, res;
  const int init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 527,532 ****
--- 529,535 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-4.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-4.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-4.c	(working copy)
***************
*** 2,15 ****
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_long_long_runtime } */
! /* { dg-options "" } */
! /* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for long long.  */
  
  extern void abort(void);
  
! long long v, count, res;
  const long long init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 2,16 ----
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_long_long_runtime } */
! /* { dg-options "--std=c11" } */
! /* { dg-options "--std=c11 -march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for long long.  */
  
  extern void abort(void);
  
! _Atomic long long v;
! long long count, res;
  const long long init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 529,534 ****
--- 530,536 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-5.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-5.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-5.c	(working copy)
***************
*** 1,14 ****
  /* Test __atomic routines for existence and proper execution on 16 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_int_128_runtime } */
! /* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int_128.  */
  
  extern void abort(void);
  
! __int128_t v, count, res;
  const __int128_t init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 1,16 ----
  /* Test __atomic routines for existence and proper execution on 16 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_int_128_runtime } */
! /* { dg-options "--std=c11 -mcx16" { target { i?86-*-* x86_64-*-* } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int_128.  */
  
  extern void abort(void);
  
! _Atomic __int128_t v;
! __int128_t count, res;
  const __int128_t init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 528,533 ****
--- 530,536 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 17:18 [PATCH] Add atomic type qualifier Andrew MacLeod
@ 2013-07-26 19:24 ` Andi Kleen
  2013-07-26 19:34   ` Andrew MacLeod
  2013-07-26 20:42 ` Hans-Peter Nilsson
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 31+ messages in thread
From: Andi Kleen @ 2013-07-26 19:24 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp

Andrew MacLeod <amacleod@redhat.com> writes:
>
> What it doesn't do:
>   * It doesn't implement the C11 expression expansion into atomic
> built-ins.  ie, you can't write:
> _Atomic int x;
>  x = 0;
>       and have the result be an atomic operation calling
> __atomic_store (&x, 0).   

How would this work if you want a different memory order?

-Andi

-- 
ak@linux.intel.com -- Speaking for myself only

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 19:24 ` Andi Kleen
@ 2013-07-26 19:34   ` Andrew MacLeod
  2013-07-26 21:14     ` Andi Kleen
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-26 19:34 UTC (permalink / raw)
  To: Andi Kleen; +Cc: gcc-patches, hp

On 07/26/2013 03:01 PM, Andi Kleen wrote:
> Andrew MacLeod <amacleod@redhat.com> writes:
>> What it doesn't do:
>>    * It doesn't implement the C11 expression expansion into atomic
>> built-ins.  ie, you can't write:
>> _Atomic int x;
>>   x = 0;
>>        and have the result be an atomic operation calling
>> __atomic_store (&x, 0).
> How would this work if you want a different memory order?
>
>
The way the standard is defined, any implicit operation like that is 
seq_cst.  If you want something other than seq-cst, you have to 
explicitly call atomic_store (&x, 0, model).

C11 also provides all those same atomic routines that c++11 provides for 
this reason.  They just decided to try to implement the c++ atomic 
templates in the language along the way :-P  so it feels very much like 
c++ atomics...

Andrew

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 17:18 [PATCH] Add atomic type qualifier Andrew MacLeod
  2013-07-26 19:24 ` Andi Kleen
@ 2013-07-26 20:42 ` Hans-Peter Nilsson
  2013-07-26 23:58 ` Joseph S. Myers
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 31+ messages in thread
From: Hans-Peter Nilsson @ 2013-07-26 20:42 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

On Fri, 26 Jul 2013, Andrew MacLeod wrote:
> This patch adds an atomic type qualifier to GCC.   It can be accessed via
> __attribute__((atomic)) or in C11 mode via the _Atomic keyword.

> HP, you might want to give this a try and see if you can get the alignment
> correct for the cris port finally :-)

Looks like the means to that end are there now.  Thanks!
Though I won't be able to look into it for a while.
(Looking at two more weeks of vacation and likely a hectic
period after that.)

Note to self (mostly): also implement target-specific warning
when the layout of a composite type including an atomic
("naturally" aligned) type would differ from normal (unaligned;
packed) layout.

brgds, H-P

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 19:34   ` Andrew MacLeod
@ 2013-07-26 21:14     ` Andi Kleen
  2013-07-26 22:29       ` Andrew MacLeod
  0 siblings, 1 reply; 31+ messages in thread
From: Andi Kleen @ 2013-07-26 21:14 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp

Andrew MacLeod <amacleod@redhat.com> writes:
>>
> The way the standard is defined, any implicit operation like that is
> seq_cst.  If you want something other than seq-cst, you have to
> explicitly call atomic_store (&x, 0, model).

Thanks.

This doesn't sound like a good default for x86. seq_cst requires 
somewhat expensive extra barriers that most people most likely don't
need.

-Andi

-- 
ak@linux.intel.com -- Speaking for myself only

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 21:14     ` Andi Kleen
@ 2013-07-26 22:29       ` Andrew MacLeod
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-26 22:29 UTC (permalink / raw)
  To: Andi Kleen; +Cc: gcc-patches, hp

On 07/26/2013 05:13 PM, Andi Kleen wrote:
> Andrew MacLeod <amacleod@redhat.com> writes:
>> The way the standard is defined, any implicit operation like that is
>> seq_cst.  If you want something other than seq-cst, you have to
>> explicitly call atomic_store (&x, 0, model).
> Thanks.
>
> This doesn't sound like a good default for x86. seq_cst requires
> somewhat expensive extra barriers that most people most likely don't
> need.
>
Its the only truly safe default for a multi-threaded environment.

These are the same defaults you get with C++11 as well if you don't 
explicitly use a memory model in your atomic operations:
ie
  __int_type  load(memory_order __m = memory_order_seq_cst) const noexcept

So if you don't want seq-cst, you need to specify exactly what you do want.


Andrew



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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 17:18 [PATCH] Add atomic type qualifier Andrew MacLeod
  2013-07-26 19:24 ` Andi Kleen
  2013-07-26 20:42 ` Hans-Peter Nilsson
@ 2013-07-26 23:58 ` Joseph S. Myers
  2013-07-27  1:15   ` Andrew MacLeod
  2013-08-01 21:54   ` Andrew MacLeod
  2013-07-28 21:15 ` Joseph S. Myers
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
  4 siblings, 2 replies; 31+ messages in thread
From: Joseph S. Myers @ 2013-07-26 23:58 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp

On Fri, 26 Jul 2013, Andrew MacLeod wrote:

> This patch adds an atomic type qualifier to GCC.   It can be accessed via
> __attribute__((atomic)) or in C11 mode via the _Atomic keyword.

Why the attribute - why not just the keyword?

I'll review the patch in detail later (which will involve checking each 
reference to "atomic" or "qualified" in the language part of C11, checking 
for appropriate implementation and complaining if it appears to be 
missing, and checking for appropriate testcases and complaining if those 
appear to be missing).  But some comments now:

* pedwarns for using a C11 feature in previous standard modes should as 
per usual practice be pedwarns-if-pedantic.

* I don't see anything obvious in the parser changes to implement the 
_Atomic ( type-name ) version of the syntax for atomic types (6.7.2.4).

* When C11 refers to qualified types, by default it does not include 
atomic types (6.2.5#27).  What's your rationale for including "atomic" in 
TYPE_QUALS rather than making it separate?  With either approach, a review 
of every reference to qualifiers in the front end is needed to determine 
what's correct for "atomic"; did you find that including "atomic" in 
qualifiers in the implementation made for fewer changes?

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 23:58 ` Joseph S. Myers
@ 2013-07-27  1:15   ` Andrew MacLeod
  2013-08-01 21:54   ` Andrew MacLeod
  1 sibling, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-27  1:15 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, hp

On 07/26/2013 07:21 PM, Joseph S. Myers wrote:
> On Fri, 26 Jul 2013, Andrew MacLeod wrote:
>
>> This patch adds an atomic type qualifier to GCC.   It can be accessed via
>> __attribute__((atomic)) or in C11 mode via the _Atomic keyword.
> Why the attribute - why not just the keyword?
2 reasons:
   1 - we currently have at least one target who cannot express their 
alignment requirements for an atomic value (ie, a short with 4 byte 
alignment).  Use of__attribute((atomic)) will allow proper expression 
and usage within the atomic built-ins without using C11.
  2 - compatibility with C11 and C++11.  Ultimately, the atomic object 
can be "upsized" (ie,a  6 byte object sized up to be 8 bytes).   _Atomic 
would do that for C11, but we cant really use _Atomic within the c++11 
template files, so __attribute__((atomic)) seemed pretty natural.   As 
well, this will allow c++ atomic templates to work on aforementioned 
target(s).


>
> I'll review the patch in detail later (which will involve checking each
> reference to "atomic" or "qualified" in the language part of C11, checking
> for appropriate implementation and complaining if it appears to be
> missing, and checking for appropriate testcases and complaining if those
> appear to be missing).  But some comments now:
>
> * pedwarns for using a C11 feature in previous standard modes should as
> per usual practice be pedwarns-if-pedantic.
>
> * I don't see anything obvious in the parser changes to implement the
> _Atomic ( type-name ) version of the syntax for atomic types (6.7.2.4).
>
> * When C11 refers to qualified types, by default it does not include
> atomic types (6.2.5#27).  What's your rationale for including "atomic" in
> TYPE_QUALS rather than making it separate?  With either approach, a review
> of every reference to qualifiers in the front end is needed to determine
> what's correct for "atomic"; did you find that including "atomic" in
> qualifiers in the implementation made for fewer changes?
>
I'm not good at front ends... don't really know them at all. Parsing and 
syntax and semantics scare me.   This was my initial attempt to enable 
_Atomic and hoped for help with the rest from those who do :-)  
observation and changes welcome.


Andrew

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 17:18 [PATCH] Add atomic type qualifier Andrew MacLeod
                   ` (2 preceding siblings ...)
  2013-07-26 23:58 ` Joseph S. Myers
@ 2013-07-28 21:15 ` Joseph S. Myers
  2013-07-29 15:47   ` Andrew MacLeod
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
  4 siblings, 1 reply; 31+ messages in thread
From: Joseph S. Myers @ 2013-07-28 21:15 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp

On Fri, 26 Jul 2013, Andrew MacLeod wrote:

> What it doesn't do:

* It doesn't implement the stdatomic.h header - do you intend that to be 
provided by GCC or glibc?

(Substantive review of the full patch still to come.)

>   * It doesn't implement the C11 expression expansion into atomic built-ins.
> ie, you can't write:
> _Atomic int x;
>  x = 0;
>       and have the result be an atomic operation calling __atomic_store (&x,
> 0).   That will be in a  follow on patch. So none of the expression expansion
> from C11 is included yet. This just enables that.

The hardest part will probably be compound assignment to an atomic object 
where either operand of the assignment has floating-point type - see C11 
footnote 113, but you can't actually use feholdexcept or feclearexcept or 
feupdateenv here because that would introduce libm dependencies, so back 
ends will need to provide appropriate insn patterns to do those operations 
inline.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-28 21:15 ` Joseph S. Myers
@ 2013-07-29 15:47   ` Andrew MacLeod
  2013-07-29 16:12     ` Joseph S. Myers
  2013-07-29 16:24     ` Andrew MacLeod
  0 siblings, 2 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-29 15:47 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, hp, Richard Henderson

On 07/28/2013 03:34 PM, Joseph S. Myers wrote:
> On Fri, 26 Jul 2013, Andrew MacLeod wrote:
>
>> What it doesn't do:
> * It doesn't implement the stdatomic.h header - do you intend that to be
> provided by GCC or glibc?
>
> (Substantive review of the full patch still to come.)

I figured gcc would provide it...   but I hadn't given it a ton of 
thought on whether that was good or bad.  again, that sort of thing 
isn't really my strong suit :-)
>
>>    * It doesn't implement the C11 expression expansion into atomic built-ins.
>> ie, you can't write:
>> _Atomic int x;
>>   x = 0;
>>        and have the result be an atomic operation calling __atomic_store (&x,
>> 0).   That will be in a  follow on patch. So none of the expression expansion
>> from C11 is included yet. This just enables that.
> The hardest part will probably be compound assignment to an atomic object
> where either operand of the assignment has floating-point type - see C11
> footnote 113, but you can't actually use feholdexcept or feclearexcept or
> feupdateenv here because that would introduce libm dependencies, so back
> ends will need to provide appropriate insn patterns to do those operations
> inline.
>   
Blick. What were they smoking the night before... I guess we'll probably 
need to enhance the current atomic patterns in RTL...    We should be 
able to figure out that its floating point and invoke the appropriate 
RTL pattern during expansion rather than an existing one.    OR just 
frigging call libatomic and let it deal with it. :-)  I guess there 
wouldnt be any other fallback available. Actually, thats a mess... no 
way for the librtary to know its floating point unless you tell it 
somehow with new entry points or somesuch..  very lame.

I planned to do the work in gimplification... let the atomic decls 
through, and during gimplification, loads or stores of an atomic decl 
would be converted to the appropriate load or store builtin, and at the 
same time recognize the  'decl = decl op value' expression and replace 
those as appropriate with atomic_op_fetch operations.   I had discussed 
this at some length with Lawrence crowl and Jeffrey Yasskin some time 
ago..   At gimplification time we no longer know whether the original 
form was
decl op= val  or decl = decl op val;, but the decision was that it is ok 
to recognize decl = decl op val and make that atomic.. it would still 
satisfy the language requirements..

Andrew

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-29 15:47   ` Andrew MacLeod
@ 2013-07-29 16:12     ` Joseph S. Myers
  2013-07-29 16:30       ` Andrew MacLeod
  2013-07-29 23:24       ` Andrew MacLeod
  2013-07-29 16:24     ` Andrew MacLeod
  1 sibling, 2 replies; 31+ messages in thread
From: Joseph S. Myers @ 2013-07-29 16:12 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp, Richard Henderson

On Mon, 29 Jul 2013, Andrew MacLeod wrote:

> Blick. What were they smoking the night before... I guess we'll probably need
> to enhance the current atomic patterns in RTL...    We should be able to
> figure out that its floating point and invoke the appropriate RTL pattern
> during expansion rather than an existing one.    OR just frigging call
> libatomic and let it deal with it. :-)  I guess there wouldnt be any other
> fallback available. Actually, thats a mess... no way for the librtary to know
> its floating point unless you tell it somehow with new entry points or
> somesuch..  very lame.

Note that you only need *one* of the types to be floating-point for this 
issue to apply.  If you have

_Atomic char c;
float f;

c /= f;

then all the same requirements apply; there may be exceptions to discard 
not just from the division, but from the conversion of a float division 
result to char.

> I planned to do the work in gimplification... let the atomic decls through,
> and during gimplification, loads or stores of an atomic decl would be
> converted to the appropriate load or store builtin, and at the same time
> recognize the  'decl = decl op value' expression and replace those as
> appropriate with atomic_op_fetch operations.   I had discussed this at some
> length with Lawrence crowl and Jeffrey Yasskin some time ago..   At
> gimplification time we no longer know whether the original form was
> decl op= val  or decl = decl op val;, but the decision was that it is ok to
> recognize decl = decl op val and make that atomic.. it would still satisfy the
> language requirements..

I think that's probably OK (though, is this a theorem of the formal 
modelling work that has been done on the memory model?), but note it's not 
just a decl but an arbitrary pointer dereference (the address of the 
lvalue is only evaluated once, no matter how many compare-and-exchange 
operations are needed), and the operation may end up looking like

*ptr = (convert to type of *ptr) ((promote) *ptr op (promote) val)

rather than a simple decl = decl op val.  Or something more complicated if 
the operation involves complex numbers - look at what gets for mixed real 
/ complex arithmetic, for example.  Given

_Atomic _Complex float f;
double d;

f += d;

the atomicity is for the whole complex number (and so the 
compare-and-exchange needs to work on the whole number) although only the 
real part is modified by the addition.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-29 15:47   ` Andrew MacLeod
  2013-07-29 16:12     ` Joseph S. Myers
@ 2013-07-29 16:24     ` Andrew MacLeod
  1 sibling, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-29 16:24 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: Joseph S. Myers, gcc-patches, hp, Richard Henderson

On 07/29/2013 10:59 AM, Andrew MacLeod wrote:
> Blick. What were they smoking the night before... I guess we'll 
> probably need to enhance the current atomic patterns in RTL...    We 
> should be able to figure out that its floating point and invoke the 
> appropriate RTL pattern during expansion rather than an existing 
> one.    OR just frigging call libatomic and let it deal with it. :-)  
> I guess there wouldnt be any other fallback available. Actually, thats 
> a mess... no way for the librtary to know its floating point unless 
> you tell it somehow with new entry points or somesuch..  very lame.
>
Actually, in hind sight, we will need new atomic builtins....  It lists 
other operators we need to support that we currently do not: They list
*, / , % + - << >> & ^ |
we currently  don't support *,/, modulus, right or left shift.

Maybe the simple thing is simply to emit the compare_exchange loop for 
all these, and not bother libatomic with them at all.    We can 
eventually add rtl patterns for them if we want "better performance" for 
these new bits.

As for the floating point operations, emit the same loop, and if there 
is a target pattern emit it, otherwise issue a warning saying those 
footnote items are not properly protected or whatever.

Also, If I read this right, "arithmetic type" also includes complex type 
does it not?  which means we need to support this for complex as well...

Does C++14(or onward) intend to support these additions as well?

Andrew

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-29 16:12     ` Joseph S. Myers
@ 2013-07-29 16:30       ` Andrew MacLeod
  2013-07-29 16:48         ` Joseph S. Myers
  2013-07-29 23:24       ` Andrew MacLeod
  1 sibling, 1 reply; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-29 16:30 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, hp, Richard Henderson

On 07/29/2013 12:06 PM, Joseph S. Myers wrote:
> On Mon, 29 Jul 2013, Andrew MacLeod wrote:
>
>> Blick. What were they smoking the night before... I guess we'll probably need
>> to enhance the current atomic patterns in RTL...    We should be able to
>> figure out that its floating point and invoke the appropriate RTL pattern
>> during expansion rather than an existing one.    OR just frigging call
>> libatomic and let it deal with it. :-)  I guess there wouldnt be any other
>> fallback available. Actually, thats a mess... no way for the librtary to know
>> its floating point unless you tell it somehow with new entry points or
>> somesuch..  very lame.
> Note that you only need *one* of the types to be floating-point for this
> issue to apply.  If you have
>
> _Atomic char c;
> float f;
>
> c /= f;
>
> then all the same requirements apply; there may be exceptions to discard
> not just from the division, but from the conversion of a float division
> result to char.
yes, unfortunately.   but  gimplification should turn this to:
t0 = c
t1 =(float) t0
t2 = t0 / f
t3 = (char) t2
c = t3

so we simply see a floating point division bracketted by load and store 
from a TYPE_ATOMIC expression. so we'd should be able to recognize the 
need for the floating point extra stuff based on the type of the 
operation .  and just wrap the whole blasted thing.

I must say, I'm not a fan :-)

>
>> I planned to do the work in gimplification... let the atomic decls through,
>> and during gimplification, loads or stores of an atomic decl would be
>> converted to the appropriate load or store builtin, and at the same time
>> recognize the  'decl = decl op value' expression and replace those as
>> appropriate with atomic_op_fetch operations.   I had discussed this at some
>> length with Lawrence crowl and Jeffrey Yasskin some time ago..   At
>> gimplification time we no longer know whether the original form was
>> decl op= val  or decl = decl op val;, but the decision was that it is ok to
>> recognize decl = decl op val and make that atomic.. it would still satisfy the
>> language requirements..
> I think that's probably OK (though, is this a theorem of the formal
> modelling work that has been done on the memory model?), but note it's not
I have no idea if its a theorem or not.
> just a decl but an arbitrary pointer dereference (the address of the
> lvalue is only evaluated once, no matter how many compare-and-exchange
> operations are needed), and the operation may end up looking like
>
> *ptr = (convert to type of *ptr) ((promote) *ptr op (promote) val)
>
> rather than a simple decl = decl op val.  Or something more complicated if
I think gimplification takes care of that as well since all assignments 
have to be in the form   DECL = VALUE op VALUE.. it constructs the 
sequence so that something like
*op_expr += 1

is properly transformed to
t0 = op_expr
   t1 = *t0
t2 = t1 + 1
*t0 = t2

With the TYPE_ATOMIC attribute set and rippled through the op_expr 
expression, we know that
*t0 is atomic in nature, so t1 is an atomic load, *t0 is an atomic 
store, and looking back at t2 = t1 + 1 can see that this is an atomic += 1.

same thing with a normal load of an expression... the TYPE_ATOMIC gimple 
attribute *ought* to tell us everything we need.

> the operation involves complex numbers - look at what gets for mixed real
> / complex arithmetic, for example.  Given
>
> _Atomic _Complex float f;
> double d;
>
> f += d;
>
> the atomicity is for the whole complex number (and so the
> compare-and-exchange needs to work on the whole number) although only the
> real part is modified by the addition.


complex I hadn't thought about until just now, I'll have to look.  I 
know we can deal with parts on complex sometimes.   Hopefully at 
gimplification time we still have the whole complex reference and if we 
just take care of that with the atomic builtins, we'll maintain the 
entire thing as we need.

Andrew



>

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-29 16:30       ` Andrew MacLeod
@ 2013-07-29 16:48         ` Joseph S. Myers
  2013-07-29 18:20           ` Andrew MacLeod
  0 siblings, 1 reply; 31+ messages in thread
From: Joseph S. Myers @ 2013-07-29 16:48 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp, Richard Henderson

On Mon, 29 Jul 2013, Andrew MacLeod wrote:

> complex I hadn't thought about until just now, I'll have to look.  I know we
> can deal with parts on complex sometimes.   Hopefully at gimplification time
> we still have the whole complex reference and if we just take care of that
> with the atomic builtins, we'll maintain the entire thing as we need.

You have things in a fairly complicated form, building up COMPLEX_EXPRs 
out of operations on the individual parts of the complex operands.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-29 16:48         ` Joseph S. Myers
@ 2013-07-29 18:20           ` Andrew MacLeod
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-29 18:20 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, hp, Richard Henderson

On 07/29/2013 12:42 PM, Joseph S. Myers wrote:
> On Mon, 29 Jul 2013, Andrew MacLeod wrote:
>
>> complex I hadn't thought about until just now, I'll have to look.  I know we
>> can deal with parts on complex sometimes.   Hopefully at gimplification time
>> we still have the whole complex reference and if we just take care of that
>> with the atomic builtins, we'll maintain the entire thing as we need.
> You have things in a fairly complicated form, building up COMPLEX_EXPRs
> out of operations on the individual parts of the complex operands.
>
I tried:

   __complex__ double d;
int main (void)
{

   d = 0;
   d = d + 5;
}

and it seems to break it into:
d = __complex__ (0.0, 0.0);

and
d.1 = d;
   d.0 = d.1;
   D.1723 = REALPART_EXPR <d.0>;
   D.1724 = D.1723 + 5.0e+0;
   D.1725 = IMAGPART_EXPR <d.0>;
   d.2 = COMPLEX_EXPR <D.1724, D.1725>;
   d = d.2;

so again the loads and stores to (D) appear to be completely wrap the 
entire complex operation, so this should be handle-able the same way...

So you really should be able to key into the atomic load from D followed 
by the store to D and look at whats in between.

I thini is is straightforward in the gimplifier, we ought to have the d 
=d op V expression at some point and be able to detect that d is the 
same and atomic, and check op.   but if it turns out not to be, then I 
could simply turn those atomic loads and stores into atomic loads and 
stores  in the gimplifier and stop there., Then have a very early 
always-run SSA pass pattern match looking for atomic stores fed from 
atomic loads, and examine the operations in between, looking for 
patterns that match  d = d op v, and then turning the loads/store and 
intermediate bits into the specified compare_exchange loops...

I'll get to this shortly.

Andrew

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-29 16:12     ` Joseph S. Myers
  2013-07-29 16:30       ` Andrew MacLeod
@ 2013-07-29 23:24       ` Andrew MacLeod
  2013-07-30 12:03         ` Joseph S. Myers
  1 sibling, 1 reply; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-29 23:24 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, hp, Richard Henderson

On 07/29/2013 12:06 PM, Joseph S. Myers wrote:
> On Mon, 29 Jul 2013, Andrew MacLeod wrote:
>
>> I planned to do the work in gimplification... let the atomic decls through,
>> and during gimplification, loads or stores of an atomic decl would be
>> converted to the appropriate load or store builtin, and at the same time
>> recognize the  'decl = decl op value' expression and replace those as
>> appropriate with atomic_op_fetch operations.   I had discussed this at some
>> length with Lawrence crowl and Jeffrey Yasskin some time ago..   At
>> gimplification time we no longer know whether the original form was
>> decl op= val  or decl = decl op val;, but the decision was that it is ok to
>> recognize decl = decl op val and make that atomic.. it would still satisfy the
>> language requirements..
> I think that's probably OK (though, is this a theorem of the formal
> modelling work that has been done on the memory model?), but note it's not
> just a decl but an arbitrary pointer dereference (the address of the
> lvalue is only evaluated once, no matter how many compare-and-exchange
> operations are needed), and the operation may end up looking like
>
> *ptr = (convert to type of *ptr) ((promote) *ptr op (promote) val)
>
> rather than a simple decl = decl op val.  Or something more complicated if
> the operation involves complex numbers - look at what gets for mixed real
> / complex arithmetic, for example.  Given
>
> _Atomic _Complex float f;
> double d;
>
> f += d;
>
> the atomicity is for the whole complex number (and so the
> compare-and-exchange needs to work on the whole number) although only the
> real part is modified by the addition.
>

Ive been poking at this today, and Im wondering what you think of the 
idea of adding a flag to MODIFY_EXPR,
#define MODIFY_EXPR_IS_COMPOUND(NODE) 
MODIFY_EXPR_CHECK(NODE)->base.asm_written_flag

and set that in the MODIFY_EXPR node when we create it from the "x op= 
y" form in the front end.   That flag seems to be free for expressions.

  It will then be trivial to locate these expressions and issue a 
builtin or the wrapper compare_exchange code during gimplification. We 
just check if MODIFY_EXPR_IS_COMPOUND() is true and TYPE_ATOMIC() is set 
on the expression type.   (Ive already confirmed the atomic type is set 
as the attribute ripples up to the MODIFY_EXPR node's type.) then we 
know all the important bits from the MODIFY_EXPR to perform the operation.

Otherwise, it looks like it can get a bit hairy...

What do you think?  As a side effect, we also only get it for the actual 
statements we care about as well.

Andrew



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

* Re: [PATCH] Add atomic type qualifier
  2013-07-29 23:24       ` Andrew MacLeod
@ 2013-07-30 12:03         ` Joseph S. Myers
  2013-07-30 12:38           ` Andrew MacLeod
  0 siblings, 1 reply; 31+ messages in thread
From: Joseph S. Myers @ 2013-07-30 12:03 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp, Richard Henderson

On Mon, 29 Jul 2013, Andrew MacLeod wrote:

> Ive been poking at this today, and Im wondering what you think of the idea of
> adding a flag to MODIFY_EXPR,
> #define MODIFY_EXPR_IS_COMPOUND(NODE)
> MODIFY_EXPR_CHECK(NODE)->base.asm_written_flag
> 
> and set that in the MODIFY_EXPR node when we create it from the "x op= y" form
> in the front end.   That flag seems to be free for expressions.

My suggestion is that the IR generated by the front end should make it 
completely explicit what may need retrying with a compare-and-exchange, 
rather than relying on non-obvious details to reconstruct the semantics 
required at gimplification time - there are too many transformations 
(folding etc.) that may happen on existing trees and no clear way to be 
confident that you can still identify all the operands accurately after 
such transformations.  That is, an ATOMIC_COMPOUND_MODIFY_EXPR or similar, 
whose operands are: the LHS of the assignment; a temporary variable, "old" 
in C11 footnote 113; the RHS; and the "old op val" expression complete 
with the conversion to the type of the LHS.  Gimplification would then 
(carry out the effects of stabilize_reference on the LHS and save_expr on 
the RHS and) do "old = LHS;" followed by the do-while compare-exchange 
loop.

A flag on the expression could indicate that the floating-point semantics 
are required.  I'd guess back ends would need to provide three insn 
patterns, corresponding to feholdexcept, feclearexcept and feupdateenv, 
that there'd be corresponding built-in functions for these used at 
gimplification time, and that a target hook would give the type used for 
fenv_t by these built-in functions (*not* necessarily the same as the 
fenv_t used by any implementation of the functions in libm).  The target 
should also be able to declare that there's no support for floating-point 
exceptions (e.g. for soft-float) and so floating-point cases don't need 
any special handling.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-30 12:03         ` Joseph S. Myers
@ 2013-07-30 12:38           ` Andrew MacLeod
  2013-07-30 13:25             ` Joseph S. Myers
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 12:38 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, hp, Richard Henderson

On 07/30/2013 07:41 AM, Joseph S. Myers wrote:
> On Mon, 29 Jul 2013, Andrew MacLeod wrote:
>
>> Ive been poking at this today, and Im wondering what you think of the idea of
>> adding a flag to MODIFY_EXPR,
>> #define MODIFY_EXPR_IS_COMPOUND(NODE)
>> MODIFY_EXPR_CHECK(NODE)->base.asm_written_flag
>>
>> and set that in the MODIFY_EXPR node when we create it from the "x op= y" form
>> in the front end.   That flag seems to be free for expressions.
> My suggestion is that the IR generated by the front end should make it
> completely explicit what may need retrying with a compare-and-exchange,
> rather than relying on non-obvious details to reconstruct the semantics
> required at gimplification time - there are too many transformations
> (folding etc.) that may happen on existing trees and no clear way to be
> confident that you can still identify all the operands accurately after
> such transformations.  That is, an ATOMIC_COMPOUND_MODIFY_EXPR or similar,
> whose operands are: the LHS of the assignment; a temporary variable, "old"
> in C11 footnote 113; the RHS; and the "old op val" expression complete
> with the conversion to the type of the LHS.  Gimplification would then
> (carry out the effects of stabilize_reference on the LHS and save_expr on
> the RHS and) do "old = LHS;" followed by the do-while compare-exchange
> loop.
In fact, after thinking about it overnight, I came to similar 
conclusions...  I believe it requires new builtin(s) for these 
operations.   Something like

    __atomic_compound_assign (&atomic_expr, enum atomic_operation_type, 
blah, blah,...)

A call to this builtin would be generated right from the parser when it 
sees the op= expression, and the built-in can then travel throughout 
gimple as a normal atomic built-in operation like the rest.  During 
expansion to RTL it can be turned into whatever sequence we happen to 
need.   This is what happens currently with the various 
__atomic_fetch_op and __atomic_op_fetch.  In fact, they are a subset of 
required operations, so I should be able to combine the implementation 
of those with this new one.

  Is C++ planning to match  these behaviours in the atomic library? It 
would need to access this builtin as well so that the C++ template code 
can invoke it.


> A flag on the expression could indicate that the floating-point semantics
> are required.  I'd guess back ends would need to provide three insn
> patterns, corresponding to feholdexcept, feclearexcept and feupdateenv,
> that there'd be corresponding built-in functions for these used at
> gimplification time, and that a target hook would give the type used for
> fenv_t by these built-in functions (*not* necessarily the same as the
> fenv_t used by any implementation of the functions in libm).  The target
> should also be able to declare that there's no support for floating-point
> exceptions (e.g. for soft-float) and so floating-point cases don't need
> any special handling.
>
I think the fact that it requires floating point sematics should be 
determinable from the types of the expressions involved.  If there is a 
floating point somewhere, then we'll need to utilize the patterns.  
we'll still have the types, although it would certainly be easy enough 
to add a flag to the builtin... and maybe thats the way to go after all.

THis also means that for the 3 floating point operations all we need are 
RTL insn patterns, no buitin.  And as with the other atomics, if the 
pattern doesnt exist, we just wont emit it.  we could add a warning 
easily enough in this case.

I think we're somewhere good now :-)

I guess I'll do the same thing for normal references to an atomic 
variable... issue the atomic load or atomic store directly from the 
parser...

Andrew

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-30 12:38           ` Andrew MacLeod
@ 2013-07-30 13:25             ` Joseph S. Myers
  2013-07-30 13:58               ` Andrew MacLeod
  0 siblings, 1 reply; 31+ messages in thread
From: Joseph S. Myers @ 2013-07-30 13:25 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches, hp, Richard Henderson

On Tue, 30 Jul 2013, Andrew MacLeod wrote:

> > A flag on the expression could indicate that the floating-point semantics
> > are required.  I'd guess back ends would need to provide three insn
> > patterns, corresponding to feholdexcept, feclearexcept and feupdateenv,
> > that there'd be corresponding built-in functions for these used at
> > gimplification time, and that a target hook would give the type used for
> > fenv_t by these built-in functions (*not* necessarily the same as the
> > fenv_t used by any implementation of the functions in libm).  The target
> > should also be able to declare that there's no support for floating-point
> > exceptions (e.g. for soft-float) and so floating-point cases don't need
> > any special handling.
> > 
> I think the fact that it requires floating point sematics should be
> determinable from the types of the expressions involved.  If there is a

My reasoning for such a flag is:

The gimplifier shouldn't need to know the details of the semantics for 
operand promotions, how various arithmetic on complex numbers is carried 
out, and how a result is converted back to the destination type for the 
store.  Even if it's the language-specific gimplification code rather than 
the language-independent gimplifier, we still want those details to be in 
one place (currently build_binary_op for the binary operation semantics), 
shared by atomic and non-atomic operations.

Hence my suggestion that the operands to the new built-in function / 
operation do not include the unmodified RHS, and do not directly specify 
the operation in question.  Instead, one operand is an expression of the 
form

  (convert-to-LHS-type) (old op val)

where "old" and "val" are the temporary variables given in C11 footnote 
113 and probably allocated by the front end ("val" initialized once, "old" 
initialized once but then potentially changing each time through the 
loop).  The trees for that expression would be generated by 
build_binary_op and contain everything required for the semantics of e.g. 
complex arithmetic.

It's true that in the case where floating-point issues arise, 
floating-point types will be involved somewhere in this expression (and 
otherwise, they will not be - though the initializer for "val" might 
itself have involved floating-point arithmetic), but you'd need to search 
recursively for them; having a flag seems simpler.

> THis also means that for the 3 floating point operations all we need are RTL
> insn patterns, no buitin.  And as with the other atomics, if the pattern

I think something will also be needed to specify allocation of the fenv_t 
temporary (whether in memory or registers).

> doesnt exist, we just wont emit it.  we could add a warning easily enough in
> this case.

Note there's a difference between no need to emit it, no warning should be 
given (soft float) and need to emit it but patterns not yet written so 
warning should be given (hard float but patterns not yet implemented for 
the architecture).

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-30 13:25             ` Joseph S. Myers
@ 2013-07-30 13:58               ` Andrew MacLeod
  2013-07-31 12:19                 ` Andrew MacLeod
  0 siblings, 1 reply; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 13:58 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, hp, Richard Henderson

On 07/30/2013 09:16 AM, Joseph S. Myers wrot
> My reasoning for such a flag is:
>
>
>
> Hence my suggestion that the operands to the new built-in function /
> operation do not include the unmodified RHS, and do not directly specify
> the operation in question.  Instead, one operand is an expression of the
> form
>
>    (convert-to-LHS-type) (old op val)
>
> where "old" and "val" are the temporary variables given in C11 footnote
> 113 and probably allocated by the front end ("val" initialized once, "old"
> initialized once but then potentially changing each time through the
> loop).  The trees for that expression would be generated by
> build_binary_op and contain everything required for the semantics of e.g.
> complex arithmetic.
>
> It's true that in the case where floating-point issues arise,
> floating-point types will be involved somewhere in this expression (and
> otherwise, they will not be - though the initializer for "val" might
> itself have involved floating-point arithmetic), but you'd need to search
> recursively for them; having a flag seems simpler.
>
I agree.

>> THis also means that for the 3 floating point operations all we need are RTL
>> insn patterns, no buitin.  And as with the other atomics, if the pattern
> I think something will also be needed to specify allocation of the fenv_t
> temporary (whether in memory or registers).
>
>> doesnt exist, we just wont emit it.  we could add a warning easily enough in
>> this case.
> Note there's a difference between no need to emit it, no warning should be
> given (soft float) and need to emit it but patterns not yet written so
> warning should be given (hard float but patterns not yet implemented for
> the architecture).

In fact, the flag could be the presence of the fenv_t variable.. Null 
for that variable field in the builtin indicate you don't need the 
patterns emitted.

I';ll get back to you in a bit with the actual built-in's format once I 
poke around the existing one and see how I can leverage it. I rewrote 
all that code last year and it ought to be pretty simple to add new 
operand support.  It better be anyway :-)

Amndrew



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

* [PATCH 0/5] Atomic type qualifier
  2013-07-26 17:18 [PATCH] Add atomic type qualifier Andrew MacLeod
                   ` (3 preceding siblings ...)
  2013-07-28 21:15 ` Joseph S. Myers
@ 2013-07-30 16:56 ` Andrew MacLeod
  2013-07-30 17:13   ` [PATCH 2/5] Atomic type qualifier - Add atomic type to tree node Andrew MacLeod
                     ` (5 more replies)
  4 siblings, 6 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 16:56 UTC (permalink / raw)
  To: gcc-patches

On 07/26/2013 01:15 PM, Andrew MacLeod wrote:
> This patch adds an atomic type qualifier to GCC.   It can be accessed 
> via __attribute__((atomic)) or in C11 mode via the _Atomic keyword.
>
> What it does:
>  *  All the __atomic builtins now expect an atomic qualified value for 
> the atomic variable.  Non-atomic values can still be passed in, but 
> they are not guaranteed to work if the original type is not compatible 
> with the atomic type  No fears.  At the moment, every target's atomic 
> types line up with the unsigned type of the same size, so like magic, 
> its all good for existing code.
>  *  There is a new target hook "atomic_align_for_mode" which a target 
> can use to override the default alignment when the atomic variation 
> requires something different.   There may be other attributes 
> eventually, but for now alignment is the only thing supported.  I 
> considered size, but the effort to do that is what drove me to the 
> re-architecture project :-P  At least the mechanism is now in place 
> for overrides when atomic requirements aren't just the default it use 
> to be.    (I introduced atomicQI_type_node, atomicHI_type_node,  
> atomicSI_type_node, atomicDI_type_node, atomicTI_type_node, ).  I 
> tested this by aligning all shorts to 32 byte boundaries and 
> bootstrapping/running all the tests.
>  * I went through the front ends trying to treat  atomic qualifier 
> mostly like a volatile, since thats is the basic behaviour one 
> expects.  In the backend, it sets the TREE_IS_VOLATILE bit so 
> behaviour ought to be the same as before, plus they are/will be always 
> used in __atomic_built-in functions.
>  * I changed the libstdc++ atomic implementation so that all the 
> atomic classes use __attribute__((atomic)) on their data members, 
> ensuring that if anyone overrides the atomic type, it should work fine 
> with C++ atomics.   It also served as a good test that I had the type 
> set up properly... getting TYPE_CANONICAL() correct throughout the C++ 
> compiler was, well..., lets just say painful.
> * I changed 2 of the atomic test sets, one uses 
> __attribute__((atomic)) to ensure the attribute compiles ok, and the 
> other uses _Atomic and --std=c11 to ensure that compiles OK.
>
> What it doesn't do:
>   * It doesn't implement the C11 expression expansion into atomic 
> built-ins.  ie, you can't write:
> _Atomic int x;
>  x = 0;
>       and have the result be an atomic operation calling 
> __atomic_store (&x, 0).   That will be in a  follow on patch. So none 
> of the expression expansion from C11 is included yet. This just 
> enables that.
>  * It doesn't do a full set of checks when _Atomic is used in invalid 
> ways.  I don't know the standard nor the front end well enough.. Im 
> hoping someone else will pitch in with that eventually, assuming 
> someone cares enough :-)  There are a couple of errors issued, but 
> that is it.
>
> This bootstraps on x86_64, and passes all the testsuites with no new 
> regressions.  I didnt split it up any more than this because most of 
> it is inter-related... plus this is already split out from a much 
> larger set of changes :-) I did try to at least organize the ordering, 
> all the long boring stuff is at the end :-)
>
> Both front end and back end stuff in here.  I think I caught it all, 
> but have a look. There is time to find any remaining issues I may have 
> missed.
>
> Andrew
>
I split the original patch into some smaller hunks, and cleaned up a few 
bit and pieces here and there... following:


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

* [PATCH 2/5] Atomic type qualifier - Add atomic type to tree node
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
@ 2013-07-30 17:13   ` Andrew MacLeod
  2013-07-30 17:14   ` [PATCH 4/5] Atomic type qualifier - Change built-in function types Andrew MacLeod
                     ` (4 subsequent siblings)
  5 siblings, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 17:13 UTC (permalink / raw)
  To: gcc-patches

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

This patch adds an atomic qualifier to the type node.  it sets up 
atomic{QHSDT}I_type_node types upon startup and used the alignment 
target hook to override alignment if need be.

Whenever new atomic types are created, they will inherit this alignment  
setting if they would otherwise be aligned to a lower boundry.

The middle end is also taught to treat decls that are atomic much the 
way we handle volatile...  ie, "don't really try to optimize this thing".

Adnrew


[-- Attachment #2: f2.diff --]
[-- Type: text/x-patch, Size: 14207 bytes --]



	* tree.h (struct tree_base): Add atomic_flag field.
	(TYPE_ATOMIC): New accessor macro.
	(enum cv_qualifier): Add TYPE_QUAL_ATOMIC.
	(TYPE_QUALS, TYPE_QUALS_NO_ADDR_SPACE): Add TYPE_QUAL_ATOMIC.
	(TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC): New macro.
	(enum tree_index): Add TI_ATOMIC{QHSDT}I_TYPE.
	(atomic{QHSDT}I_type_node): Add new type nodes.
	* emit-rtl.c (set_mem_attributes_minus_bitpos): Atomics are volatile.
	* function.c (assign_stack_temp_for_type): Atomics are volatile.
	* print-tree.c (print_node): Print atomic qualifier.
	* tree-pretty-print.c (dump_generic_node): Print atomic type attribute.
	* tree.c (set_type_quals): Set TYPE_ATOMIC.
	(find_atomic_core_type): New.  Function to get atomic type from size.
	(build_qualified_type): Tweak for atomic qualifier overrides.
	(build_atomic_variant): New.  Build atomic variant node.
	(build_common_tree_nodes): Build atomic{QHSDT}I_type_node, allowing
	for override with target hook.
	* alias.c (objects_must_conflict_p): Treat atomics as volatile.
	* calls.c (expand_call): Treat atomics as volatile.


Index: gcc/tree.h
===================================================================
*** gcc/tree.h	(revision 201248)
--- gcc/tree.h	(working copy)
*************** struct GTY(()) tree_base {
*** 457,463 ****
        unsigned packed_flag : 1;
        unsigned user_align : 1;
        unsigned nameless_flag : 1;
!       unsigned spare0 : 4;
  
        unsigned spare1 : 8;
  
--- 457,464 ----
        unsigned packed_flag : 1;
        unsigned user_align : 1;
        unsigned nameless_flag : 1;
!       unsigned atomic_flag : 1;
!       unsigned spare0 : 3;
  
        unsigned spare1 : 8;
  
*************** extern enum machine_mode vector_type_mod
*** 2205,2210 ****
--- 2206,2214 ----
  /* Nonzero in a type considered volatile as a whole.  */
  #define TYPE_VOLATILE(NODE) (TYPE_CHECK (NODE)->base.volatile_flag)
  
+ /* Nonzero in a type considered atomic as a whole.  */
+ #define TYPE_ATOMIC(NODE) (TYPE_CHECK (NODE)->base.u.bits.atomic_flag)
+ 
  /* Means this type is const-qualified.  */
  #define TYPE_READONLY(NODE) (TYPE_CHECK (NODE)->base.readonly_flag)
  
*************** enum cv_qualifier
*** 2226,2232 ****
      TYPE_UNQUALIFIED   = 0x0,
      TYPE_QUAL_CONST    = 0x1,
      TYPE_QUAL_VOLATILE = 0x2,
!     TYPE_QUAL_RESTRICT = 0x4
    };
  
  /* Encode/decode the named memory support as part of the qualifier.  If more
--- 2230,2237 ----
      TYPE_UNQUALIFIED   = 0x0,
      TYPE_QUAL_CONST    = 0x1,
      TYPE_QUAL_VOLATILE = 0x2,
!     TYPE_QUAL_RESTRICT = 0x4,
!     TYPE_QUAL_ATOMIC   = 0x8
    };
  
  /* Encode/decode the named memory support as part of the qualifier.  If more
*************** enum cv_qualifier
*** 2245,2250 ****
--- 2250,2256 ----
  #define TYPE_QUALS(NODE)					\
    ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)		\
  	  | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
+ 	  | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC)		\
  	  | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)		\
  	  | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE)))))
  
*************** enum cv_qualifier
*** 2252,2259 ****
--- 2258,2273 ----
  #define TYPE_QUALS_NO_ADDR_SPACE(NODE)				\
    ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)		\
  	  | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
+ 	  | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC)		\
+ 	  | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
+ /* The same as TYPE_QUALS without the address space and atomic 
+    qualifications.  */
+ #define TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC(NODE)		\
+   ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST)		\
+ 	  | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE)		\
  	  | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
  
+ 
  /* These flags are available for each language front end to use internally.  */
  #define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_0)
  #define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_1)
*************** enum tree_index
*** 4178,4183 ****
--- 4192,4203 ----
    TI_UINTDI_TYPE,
    TI_UINTTI_TYPE,
  
+   TI_ATOMICQI_TYPE,
+   TI_ATOMICHI_TYPE,
+   TI_ATOMICSI_TYPE,
+   TI_ATOMICDI_TYPE,
+   TI_ATOMICTI_TYPE,
+ 
    TI_UINT16_TYPE,
    TI_UINT32_TYPE,
    TI_UINT64_TYPE,
*************** extern GTY(()) tree global_trees[TI_MAX]
*** 4334,4339 ****
--- 4354,4365 ----
  #define unsigned_intDI_type_node	global_trees[TI_UINTDI_TYPE]
  #define unsigned_intTI_type_node	global_trees[TI_UINTTI_TYPE]
  
+ #define atomicQI_type_node	global_trees[TI_ATOMICQI_TYPE]
+ #define atomicHI_type_node	global_trees[TI_ATOMICHI_TYPE]
+ #define atomicSI_type_node	global_trees[TI_ATOMICSI_TYPE]
+ #define atomicDI_type_node	global_trees[TI_ATOMICDI_TYPE]
+ #define atomicTI_type_node	global_trees[TI_ATOMICTI_TYPE]
+ 
  #define uint16_type_node		global_trees[TI_UINT16_TYPE]
  #define uint32_type_node		global_trees[TI_UINT32_TYPE]
  #define uint64_type_node		global_trees[TI_UINT64_TYPE]
Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c	(revision 201248)
--- gcc/emit-rtl.c	(working copy)
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1607,1613 ****
       front-end routine) and use it.  */
    attrs.alias = get_alias_set (t);
  
!   MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
    MEM_POINTER (ref) = POINTER_TYPE_P (type);
  
    /* Default values from pre-existing memory attributes if present.  */
--- 1607,1613 ----
       front-end routine) and use it.  */
    attrs.alias = get_alias_set (t);
  
!   MEM_VOLATILE_P (ref) |= (TYPE_VOLATILE (type) || TYPE_ATOMIC (type));
    MEM_POINTER (ref) = POINTER_TYPE_P (type);
  
    /* Default values from pre-existing memory attributes if present.  */
Index: gcc/function.c
===================================================================
*** gcc/function.c	(revision 201248)
--- gcc/function.c	(working copy)
*************** assign_stack_temp_for_type (enum machine
*** 901,907 ****
  
    /* If a type is specified, set the relevant flags.  */
    if (type != 0)
!     MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
    MEM_NOTRAP_P (slot) = 1;
  
    return slot;
--- 901,907 ----
  
    /* If a type is specified, set the relevant flags.  */
    if (type != 0)
!     MEM_VOLATILE_P (slot) = (TYPE_VOLATILE (type) || TYPE_ATOMIC (type));
    MEM_NOTRAP_P (slot) = 1;
  
    return slot;
Index: gcc/print-tree.c
===================================================================
*** gcc/print-tree.c	(revision 201248)
--- gcc/print-tree.c	(working copy)
*************** print_node (FILE *file, const char *pref
*** 304,309 ****
--- 304,311 ----
  
    if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node))
      fputs (" readonly", file);
+   if (TYPE_P (node) ? TYPE_ATOMIC (node) : TYPE_ATOMIC (node))
+     fputs (" atomic", file);
    if (!TYPE_P (node) && TREE_CONSTANT (node))
      fputs (" constant", file);
    else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
Index: gcc/tree-pretty-print.c
===================================================================
*** gcc/tree-pretty-print.c	(revision 201248)
--- gcc/tree-pretty-print.c	(working copy)
*************** dump_generic_node (pretty_printer *buffe
*** 679,684 ****
--- 679,686 ----
  	unsigned int quals = TYPE_QUALS (node);
  	enum tree_code_class tclass;
  
+ 	if (quals & TYPE_QUAL_ATOMIC)
+ 	  pp_string (buffer, "atomic ");
  	if (quals & TYPE_QUAL_CONST)
  	  pp_string (buffer, "const ");
  	else if (quals & TYPE_QUAL_VOLATILE)
*************** dump_generic_node (pretty_printer *buffe
*** 980,985 ****
--- 982,989 ----
        {
  	unsigned int quals = TYPE_QUALS (node);
  
+ 	if (quals & TYPE_QUAL_ATOMIC)
+ 	  pp_string (buffer, "atomic ");
  	if (quals & TYPE_QUAL_CONST)
  	  pp_string (buffer, "const ");
  	if (quals & TYPE_QUAL_VOLATILE)
Index: gcc/tree.c
===================================================================
*** gcc/tree.c	(revision 201248)
--- gcc/tree.c	(working copy)
*************** set_type_quals (tree type, int type_qual
*** 5937,5942 ****
--- 5937,5943 ----
    TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
    TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
    TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+   TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
    TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
  }
  
*************** check_aligned_type (const_tree cand, con
*** 5970,5975 ****
--- 5971,6018 ----
  				   TYPE_ATTRIBUTES (base)));
  }
  
+ /* This function checks to see if TYPE matches the size one of the built-in 
+    atomic types, and returns that core atomic type.  */
+ 
+ tree
+ find_atomic_core_type (tree type)
+ {
+   tree base_atomic_type;
+ 
+   /* Only handle complete types.  */
+   if (TYPE_SIZE (type) == NULL_TREE)
+     return NULL_TREE;
+ 
+   HOST_WIDE_INT type_size = tree_low_cst (TYPE_SIZE (type), 1);
+   switch (type_size)
+     {
+     case 8:
+       base_atomic_type = atomicQI_type_node;
+       break;
+ 
+     case 16:
+       base_atomic_type = atomicHI_type_node;
+       break;
+ 
+     case 32:
+       base_atomic_type = atomicSI_type_node;
+       break;
+ 
+     case 64:
+       base_atomic_type = atomicDI_type_node;
+       break;
+ 
+     case 128:
+       base_atomic_type = atomicTI_type_node;
+       break;
+ 
+     default:
+       base_atomic_type = NULL_TREE;
+     }
+ 
+   return base_atomic_type;
+ }
+ 
  /* Return a version of the TYPE, qualified as indicated by the
     TYPE_QUALS, if one exists.  If no qualified version exists yet,
     return NULL_TREE.  */
*************** build_qualified_type (tree type, int typ
*** 6009,6014 ****
--- 6052,6070 ----
        t = build_variant_type_copy (type);
        set_type_quals (t, type_quals);
  
+       if (((type_quals & TYPE_QUAL_ATOMIC) == TYPE_QUAL_ATOMIC))
+ 	{
+ 	  /* See if this object can map to a basic atomic type.  */
+ 	  tree atomic_type = find_atomic_core_type (type);
+ 	  if (atomic_type)
+ 	    {
+ 	      /* Ensure the alignment of this type is compatible with
+ 		 the required alignment of the atomic type.  */
+ 	      if (TYPE_ALIGN (atomic_type) > TYPE_ALIGN (t))
+ 		TYPE_ALIGN (t) = TYPE_ALIGN (atomic_type);
+ 	    }
+ 	}
+ 
        if (TYPE_STRUCTURAL_EQUALITY_P (type))
  	/* Propagate structural equality. */
  	SET_TYPE_STRUCTURAL_EQUALITY (t);
*************** make_or_reuse_accum_type (unsigned size,
*** 9521,9526 ****
--- 9577,9607 ----
    return make_accum_type (size, unsignedp, satp);
  }
  
+ 
+ /* Create an atomic variant node for TYPE.  This routine is called during
+    initialization of data types to create the 5 basic atomic types. The generic
+    build_variant_type function requires these to already be set up in order to
+    function properly, so cannot be called from there.  
+    if ALIGN is non-zero, then ensure alignment is overridden to this value.  */
+ 
+ static tree
+ build_atomic_variant (tree type, unsigned int align)
+ {
+   tree t;
+ 
+   /* Make sure its not already registered.  */
+   if ((t = get_qualified_type (type, TYPE_QUAL_ATOMIC)))
+     return t;
+   
+   t = build_variant_type_copy (type);
+   set_type_quals (t, TYPE_QUAL_ATOMIC);
+ 
+   if (align)
+     TYPE_ALIGN (t) = align;
+ 
+   return t;
+ }
+ 
  /* Create nodes for all integer types (and error_mark_node) using the sizes
     of C datatypes.  SIGNED_CHAR specifies whether char is signed,
     SHORT_DOUBLE specifies whether double should be of the same precision
*************** build_common_tree_nodes (bool signed_cha
*** 9603,9608 ****
--- 9684,9704 ----
    unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
    unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
  
+   /* Dont call build_qualified type for atomics.  That routine does special
+      processing for atomics, and until they are initialized its better not
+      to make that call.  
+      
+      Check to see if there is a target override for atomic types.  */
+ 
+ #define SET_ATOMIC_TYPE_NODE(TYPE, MODE, DEFAULT) 		\
+  (TYPE) = build_atomic_variant (DEFAULT, targetm.atomic_align_for_mode (MODE));
+ 
+   SET_ATOMIC_TYPE_NODE (atomicQI_type_node, QImode, unsigned_intQI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicHI_type_node, HImode, unsigned_intHI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicSI_type_node, SImode, unsigned_intSI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicDI_type_node, DImode, unsigned_intDI_type_node);
+   SET_ATOMIC_TYPE_NODE (atomicTI_type_node, TImode, unsigned_intTI_type_node);
+ 
    access_public_node = get_identifier ("public");
    access_protected_node = get_identifier ("protected");
    access_private_node = get_identifier ("private");
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 201248)
--- gcc/alias.c	(working copy)
*************** objects_must_conflict_p (tree t1, tree t
*** 486,493 ****
  
    /* If they are the same type, they must conflict.  */
    if (t1 == t2
!       /* Likewise if both are volatile.  */
!       || (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2)))
      return 1;
  
    set1 = t1 ? get_alias_set (t1) : 0;
--- 486,494 ----
  
    /* If they are the same type, they must conflict.  */
    if (t1 == t2
!       /* Likewise if both are volatile or atomic.  */
!       || (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2))
!       || (t1 != 0 && TYPE_ATOMIC (t1) && t2 != 0 && TYPE_ATOMIC (t2)))
      return 1;
  
    set1 = t1 ? get_alias_set (t1) : 0;
Index: gcc/calls.c
===================================================================
*** gcc/calls.c	(revision 201248)
--- gcc/calls.c	(working copy)
*************** expand_call (tree exp, rtx target, int i
*** 2592,2597 ****
--- 2592,2598 ----
  	 optimized.  */
        || (flags & (ECF_RETURNS_TWICE | ECF_NORETURN))
        || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr)))
+       || TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (addr)))
        /* If the called function is nested in the current one, it might access
  	 some of the caller's arguments, but could clobber them beforehand if
  	 the argument areas are shared.  */

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

* [PATCH 3/5] Atomic type qualifier - front end changes
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
  2013-07-30 17:13   ` [PATCH 2/5] Atomic type qualifier - Add atomic type to tree node Andrew MacLeod
  2013-07-30 17:14   ` [PATCH 4/5] Atomic type qualifier - Change built-in function types Andrew MacLeod
@ 2013-07-30 17:14   ` Andrew MacLeod
  2013-08-09  0:06     ` Joseph S. Myers
  2013-07-30 17:14   ` [PATCH 1/5] Atomic type qualifier - Add type alignment override hook Andrew MacLeod
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 17:14 UTC (permalink / raw)
  To: gcc-patches

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

Teach the front ends to handle __attribute__((atomic)) and set the 
ATOMIC_TYPE bit in the type tree.

Also add RID_ATOMIC and recognize the _Atomic keyword, and treat it like 
__attribute__((atomic)) was specified.

Places that set TREE_THIS_VOLATILE and TREE_SIDE_EFFECTS for volatile 
symbols also need to set these fields for atomic variables.  All through 
the middle end we have always treated atomics as volatile in order to 
avoid any kind of optimization.



[-- Attachment #2: f3.diff --]
[-- Type: text/x-patch, Size: 35185 bytes --]


	c-family
	* c-common.h (enum rid): Add RID_ATOMIC.
	* c-common.c (struct c_common_resword c_common_r): Add "_Atomic".
	(struct attribute_spec c_common_att): Add "atomic" attribute.
	(handle_atomic_attribute): New.  Add atomic qualifier to type.
	(sync_resolve_params): Use MAIN_VARIANT as cast for the non-atomic
	parameters.
	(keyword_is_type_qualifier): Add RID_ATOMIC;
	* c-format.c (check_format_types): Add atomic as a qualifer check.
	* c-pretty-print.c (pp_c_cv_qualifiers): Handle atomic qualifier.

	c
	* c-tree.h (struct c_declspecs): Add atomic_p field.
	* c-aux-info.c (gen_type): Handle atomic qualifier.
	* c-decl.c (shadow_tag_warned): Add atomic_p to declspecs check.
	(quals_from_declspecs): Add atomic_p to declspecs check.
	(grokdeclarator): Check atomic and warn of duplicate or errors.
	(build_null_declspecs): Handle atomic_p.
	(declspecs_add_qual): Handle RID_ATOMIC.
	* c-parser.c (c_token_starts_typename): Add RID_ATOMIC.
	(c_token_is_qualifier, c_token_starts_declspecs): Add RID_ATOMIC.
	(c_parser_declspecs, c_parser_attribute_any_word): Add RID_ATOMIC.
	* c-typeck.c (build_indirect_ref): Treat atomic as volatile.
	(build_array_ref, convert_for_assignment): Treat atomic as volatile.

	objc
	* objc-act.c (objc_push_parm): Treat atomic as volatile.

	cp
	* cp-tree.h (CP_TYPE_ATOMIC_P): New macro.
	(enum cp_decl_spec): Add ds_atomic.
	* class.c (build_simple_base_path): Treat atomic as volatile.
	* cvt.c (diagnose_ref_binding): Handle atomic.
	(convert_from_reference, convert_to_void): Treat atomic as volatile.
	* decl.c (grokfndecl): Treat atomic as volatile.
	(build_ptrmemfunc_type): Set TYPE_ATOMIC.
	(grokdeclarator): handle atomic qualifier.
	* mangle.c (dump_substitution_candidates): Add atomic to the qualifier
	list.
	* parser.c (cp_parser_type_specifier): Handle RID_ATOMIC.
	(cp_parser_cv_qualifier_seq_opt): Handle RID_ATOMIC.
	(set_and_check_decl_spec_loc): Add atomic to decl_spec_names[].
	* pt.c (check_cv_quals_for_unify): Add TYPE_QUAL_ATOMIC to check.
	* rtti.c (qualifier_flags): Set atomic qualifier flag.
	* semantics.c (non_const_var_error): Check CP_TYPE_ATOMIC_P too.
	* tree.c (cp_build_qualified_type_real): Add TYPE_QUAL_ATOMIC.
	(cv_unqualified): Add TYPE_QUAL_ATOMIC to mask.
	* typeck.c (build_class_member_access_expr): Treat atomic as volatile.
	(cp_build_indirect_ref, cp_build_array_ref): Treat atomic as volatile.
	(check_return_expr, cp_type_quals): Treat atomic as volatile.
	(cv_qualified_p): Add TYPE_QUAL_ATOMIC to mask.


Index: gcc/c-family/c-common.h
===================================================================
*** gcc/c-family/c-common.h	(revision 201248)
--- gcc/c-family/c-common.h	(working copy)
*************** enum rid
*** 66,72 ****
    RID_UNSIGNED, RID_LONG,    RID_CONST, RID_EXTERN,
    RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
    RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
!   RID_NORETURN,
  
    /* C extensions */
    RID_COMPLEX, RID_THREAD, RID_SAT,
--- 66,72 ----
    RID_UNSIGNED, RID_LONG,    RID_CONST, RID_EXTERN,
    RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
    RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
!   RID_NORETURN, RID_ATOMIC,
  
    /* C extensions */
    RID_COMPLEX, RID_THREAD, RID_SAT,
Index: gcc/c-family/c-common.c
===================================================================
*** gcc/c-family/c-common.c	(revision 201248)
--- gcc/c-family/c-common.c	(working copy)
*************** static tree handle_unused_attribute (tre
*** 325,330 ****
--- 325,331 ----
  static tree handle_externally_visible_attribute (tree *, tree, tree, int,
  						 bool *);
  static tree handle_const_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_atomic_attribute (tree *, tree, tree, int, bool *);
  static tree handle_transparent_union_attribute (tree *, tree, tree,
  						int, bool *);
  static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
*************** const struct c_common_resword c_common_r
*** 401,406 ****
--- 402,408 ----
  {
    { "_Alignas",		RID_ALIGNAS,   D_CONLY },
    { "_Alignof",		RID_ALIGNOF,   D_CONLY },
+   { "_Atomic",		RID_ATOMIC,    D_CONLY },
    { "_Bool",		RID_BOOL,      D_CONLY },
    { "_Complex",		RID_COMPLEX,	0 },
    { "_Imaginary",	RID_IMAGINARY, D_CONLY },
*************** const struct attribute_spec c_common_att
*** 637,642 ****
--- 639,646 ----
    /* The same comments as for noreturn attributes apply to const ones.  */
    { "const",                  0, 0, true,  false, false,
  			      handle_const_attribute, false },
+   { "atomic",		      0, 0, false, true, false,
+ 			      handle_atomic_attribute, false},
    { "transparent_union",      0, 0, false, false, false,
  			      handle_transparent_union_attribute, false },
    { "constructor",            0, 1, true,  false, false,
*************** handle_const_attribute (tree *node, tree
*** 6842,6847 ****
--- 6846,6879 ----
    return NULL_TREE;
  }
  
+ 
+ /* Handle an "atomic" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ 
+ static tree
+ handle_atomic_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ 			int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   bool ignored = true;
+   if (TYPE_P (*node) && TREE_CODE (*node) != ARRAY_TYPE)
+     {
+       tree type = *node;
+ 
+       if (!TYPE_ATOMIC (type))
+ 	{
+ 	  *node = build_qualified_type (type, TYPE_QUAL_ATOMIC);
+ 	  ignored = false;
+ 	}
+     }
+ 
+   if (ignored)
+     {
+       warning (OPT_Wattributes, "%qE attribute ignored", name);
+       *no_add_attrs = true;
+     }
+   return NULL_TREE;
+ }
+ 
  /* Handle a "transparent_union" attribute; arguments as in
     struct attribute_spec.handler.  */
  
*************** sync_resolve_params (location_t loc, tre
*** 10012,10022 ****
    unsigned int parmnum;
  
    function_args_iter_init (&iter, TREE_TYPE (function));
!   /* We've declared the implementation functions to use "volatile void *"
       as the pointer parameter, so we shouldn't get any complaints from the
       call to check_function_arguments what ever type the user used.  */
    function_args_iter_next (&iter);
    ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
  
    /* For the rest of the values, we need to cast these to FTYPE, so that we
       don't get warnings for passing pointer types, etc.  */
--- 10044,10055 ----
    unsigned int parmnum;
  
    function_args_iter_init (&iter, TREE_TYPE (function));
!   /* We've declared the implementation functions to use "atomic volatile void *"
       as the pointer parameter, so we shouldn't get any complaints from the
       call to check_function_arguments what ever type the user used.  */
    function_args_iter_next (&iter);
    ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
+   ptype = TYPE_MAIN_VARIANT (ptype);
  
    /* For the rest of the values, we need to cast these to FTYPE, so that we
       don't get warnings for passing pointer types, etc.  */
*************** keyword_is_type_qualifier (enum rid keyw
*** 11388,11393 ****
--- 11421,11427 ----
      case RID_CONST:
      case RID_VOLATILE:
      case RID_RESTRICT:
+     case RID_ATOMIC:
        return true;
      default:
        return false;
Index: gcc/c-family/c-format.c
===================================================================
*** gcc/c-family/c-format.c	(revision 201248)
--- gcc/c-family/c-format.c	(working copy)
*************** check_format_types (format_wanted_type *
*** 2374,2379 ****
--- 2374,2380 ----
  		  && pedantic
  		  && (TYPE_READONLY (cur_type)
  		      || TYPE_VOLATILE (cur_type)
+ 		      || TYPE_ATOMIC (cur_type)
  		      || TYPE_RESTRICT (cur_type)))
  		warning (OPT_Wformat_, "extra type qualifiers in format "
  			 "argument (argument %d)",
Index: gcc/c-family/c-pretty-print.c
===================================================================
*** gcc/c-family/c-pretty-print.c	(revision 201248)
--- gcc/c-family/c-pretty-print.c	(working copy)
*************** pp_c_cv_qualifiers (c_pretty_printer *pp
*** 186,193 ****
--- 186,201 ----
    if (p != NULL && (*p == '*' || *p == '&'))
      pp_c_whitespace (pp);
  
+   if (qualifiers & TYPE_QUAL_ATOMIC)
+     {
+       pp_c_ws_string (pp, func_type ? "__attribute__((atomic))" : "atomic");
+       previous = true;
+     }
+ 
    if (qualifiers & TYPE_QUAL_CONST)
      {
+       if (previous)
+         pp_c_whitespace (pp);
        pp_c_ws_string (pp, func_type ? "__attribute__((const))" : "const");
        previous = true;
      }
Index: gcc/c/c-tree.h
===================================================================
*** gcc/c/c-tree.h	(revision 201248)
--- gcc/c/c-tree.h	(working copy)
*************** struct c_declspecs {
*** 328,333 ****
--- 328,335 ----
    BOOL_BITFIELD volatile_p : 1;
    /* Whether "restrict" was specified.  */
    BOOL_BITFIELD restrict_p : 1;
+   /* Whether "_Atomic" was specified.  */
+   BOOL_BITFIELD atomic_p : 1;
    /* Whether "_Sat" was specified.  */
    BOOL_BITFIELD saturating_p : 1;
    /* Whether any alignment specifier (even with zero alignment) was
Index: gcc/c/c-aux-info.c
===================================================================
*** gcc/c/c-aux-info.c	(revision 201248)
--- gcc/c/c-aux-info.c	(working copy)
*************** gen_type (const char *ret_val, tree t, f
*** 285,290 ****
--- 285,292 ----
        switch (TREE_CODE (t))
  	{
  	case POINTER_TYPE:
+ 	  if (TYPE_ATOMIC (t))
+ 	    ret_val = concat ("atomic ", ret_val, NULL);
  	  if (TYPE_READONLY (t))
  	    ret_val = concat ("const ", ret_val, NULL);
  	  if (TYPE_VOLATILE (t))
*************** gen_type (const char *ret_val, tree t, f
*** 425,430 ****
--- 427,434 ----
  	  gcc_unreachable ();
  	}
      }
+   if (TYPE_ATOMIC (t))
+     ret_val = concat ("atomic ", ret_val, NULL);
    if (TYPE_READONLY (t))
      ret_val = concat ("const ", ret_val, NULL);
    if (TYPE_VOLATILE (t))
Index: gcc/c/c-decl.c
===================================================================
*** gcc/c/c-decl.c	(revision 201248)
--- gcc/c/c-decl.c	(working copy)
*************** shadow_tag_warned (const struct c_declsp
*** 3712,3717 ****
--- 3712,3718 ----
                     && declspecs->typespec_kind != ctsk_tagfirstref
  		   && (declspecs->const_p
  		       || declspecs->volatile_p
+ 		       || declspecs->atomic_p
  		       || declspecs->restrict_p
  		       || declspecs->address_space))
  	    {
*************** shadow_tag_warned (const struct c_declsp
*** 3801,3806 ****
--- 3802,3808 ----
  
    if (!warned && !in_system_header && (declspecs->const_p
  				       || declspecs->volatile_p
+ 				       || declspecs->atomic_p
  				       || declspecs->restrict_p
  				       || declspecs->address_space))
      {
*************** quals_from_declspecs (const struct c_dec
*** 3832,3837 ****
--- 3834,3840 ----
    int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
  	       | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
  	       | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
+ 	       | (specs->atomic_p ? TYPE_QUAL_ATOMIC : 0)
  	       | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
    gcc_assert (!specs->type
  	      && !specs->decl_attr
*************** grokdeclarator (const struct c_declarato
*** 4911,4916 ****
--- 4914,4920 ----
    int constp;
    int restrictp;
    int volatilep;
+   int atomicp;
    int type_quals = TYPE_UNQUALIFIED;
    tree name = NULL_TREE;
    bool funcdef_flag = false;
*************** grokdeclarator (const struct c_declarato
*** 5065,5070 ****
--- 5069,5075 ----
    constp = declspecs->const_p + TYPE_READONLY (element_type);
    restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
    volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
+   atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type);
    as1 = declspecs->address_space;
    as2 = TYPE_ADDR_SPACE (element_type);
    address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
*************** grokdeclarator (const struct c_declarato
*** 5077,5082 ****
--- 5082,5090 ----
  	pedwarn (loc, OPT_Wpedantic, "duplicate %<restrict%>");
        if (volatilep > 1)
  	pedwarn (loc, OPT_Wpedantic, "duplicate %<volatile%>");
+       if (atomicp > 1)
+ 	pedwarn (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
+ 
      }
  
    if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 != as2)
*************** grokdeclarator (const struct c_declarato
*** 5090,5095 ****
--- 5098,5104 ----
    type_quals = ((constp ? TYPE_QUAL_CONST : 0)
  		| (restrictp ? TYPE_QUAL_RESTRICT : 0)
  		| (volatilep ? TYPE_QUAL_VOLATILE : 0)
+ 		| (atomicp ? TYPE_QUAL_ATOMIC : 0)
  		| ENCODE_QUAL_ADDR_SPACE (address_space));
  
    /* Warn about storage classes that are invalid for certain
*************** grokdeclarator (const struct c_declarato
*** 5651,5656 ****
--- 5660,5670 ----
  	      FOR_EACH_VEC_SAFE_ELT_REVERSE (arg_info->tags, ix, tag)
  		TYPE_CONTEXT (tag->type) = type;
  	    }
+ 	    if (atomicp)
+ 	      {
+ 		error_at (loc, "_Atomic type qualifier in function declarator");
+ 		type = error_mark_node;
+ 	      }
  	    break;
  	  }
  	case cdk_pointer:
*************** build_null_declspecs (void)
*** 8825,8830 ****
--- 8839,8845 ----
    ret->thread_p = false;
    ret->const_p = false;
    ret->volatile_p = false;
+   ret->atomic_p = false;
    ret->restrict_p = false;
    ret->saturating_p = false;
    ret->alignas_p = false;
*************** declspecs_add_qual (source_location loc,
*** 8886,8891 ****
--- 8901,8910 ----
        specs->restrict_p = true;
        specs->locations[cdw_restrict] = loc;
        break;
+     case RID_ATOMIC:
+       dupe = specs->atomic_p;
+       specs->atomic_p = true;
+       break;
      default:
        gcc_unreachable ();
      }
Index: gcc/c/c-parser.c
===================================================================
*** gcc/c/c-parser.c	(revision 201248)
--- gcc/c/c-parser.c	(working copy)
*************** c_token_starts_typename (c_token *token)
*** 489,494 ****
--- 489,495 ----
  	case RID_UNION:
  	case RID_TYPEOF:
  	case RID_CONST:
+ 	case RID_ATOMIC:
  	case RID_VOLATILE:
  	case RID_RESTRICT:
  	case RID_ATTRIBUTE:
*************** c_token_is_qualifier (c_token *token)
*** 571,576 ****
--- 572,578 ----
  	case RID_VOLATILE:
  	case RID_RESTRICT:
  	case RID_ATTRIBUTE:
+ 	case RID_ATOMIC:
  	  return true;
  	default:
  	  return false;
*************** c_token_starts_declspecs (c_token *token
*** 651,656 ****
--- 653,659 ----
  	case RID_ACCUM:
  	case RID_SAT:
  	case RID_ALIGNAS:
+ 	case RID_ATOMIC:
  	  return true;
  	default:
  	  return false;
*************** c_parser_static_assert_declaration_no_se
*** 1948,1955 ****
--- 1951,1960 ----
       restrict
       volatile
       address-space-qualifier
+      atomic
  
     (restrict is new in C99.)
+    (atomic is new in C11.)
  
     GNU extensions:
  
*************** c_parser_declspecs (c_parser *parser, st
*** 2171,2176 ****
--- 2176,2185 ----
  	  t = c_parser_typeof_specifier (parser);
  	  declspecs_add_type (loc, specs, t);
  	  break;
+ 	case RID_ATOMIC:
+ 	  if (!flag_isoc11)
+ 	    pedwarn (loc, 0, "_Atomic qualifier provided in ISO C11");
+ 	  /* Fallthru.  */
  	case RID_CONST:
  	case RID_VOLATILE:
  	case RID_RESTRICT:
*************** c_parser_attribute_any_word (c_parser *p
*** 3487,3492 ****
--- 3496,3502 ----
  	case RID_SAT:
  	case RID_TRANSACTION_ATOMIC:
  	case RID_TRANSACTION_CANCEL:
+ 	case RID_ATOMIC:
  	  ok = true;
  	  break;
  	default:
Index: gcc/c/c-typeck.c
===================================================================
*** gcc/c/c-typeck.c	(revision 201248)
--- gcc/c/c-typeck.c	(working copy)
*************** build_indirect_ref (location_t loc, tree
*** 2268,2276 ****
  	  /* A de-reference of a pointer to const is not a const.  It is valid
  	     to change it via some other pointer.  */
  	  TREE_READONLY (ref) = TYPE_READONLY (t);
! 	  TREE_SIDE_EFFECTS (ref)
! 	    = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
! 	  TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
  	  protected_set_expr_location (ref, loc);
  	  return ref;
  	}
--- 2268,2276 ----
  	  /* A de-reference of a pointer to const is not a const.  It is valid
  	     to change it via some other pointer.  */
  	  TREE_READONLY (ref) = TYPE_READONLY (t);
! 	  TREE_SIDE_EFFECTS (ref) = (TYPE_VOLATILE (t) || TYPE_ATOMIC (t)
! 				     || TREE_SIDE_EFFECTS (pointer));
! 	  TREE_THIS_VOLATILE (ref) = (TYPE_VOLATILE (t) || TYPE_ATOMIC (t));
  	  protected_set_expr_location (ref, loc);
  	  return ref;
  	}
*************** build_array_ref (location_t loc, tree ar
*** 2408,2416 ****
--- 2408,2418 ----
  	    | TREE_READONLY (array));
        TREE_SIDE_EFFECTS (rval)
  	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+ 	    | TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (array)))
  	    | TREE_SIDE_EFFECTS (array));
        TREE_THIS_VOLATILE (rval)
  	|= (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (array)))
+ 	    | TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (array)))
  	    /* This was added by rms on 16 Nov 91.
  	       It fixes  vol struct foo *a;  a->elts[1]
  	       in an inline function.
*************** convert_for_assignment (location_t locat
*** 5578,5585 ****
  	  else if (TREE_CODE (ttr) != FUNCTION_TYPE
  		   && TREE_CODE (ttl) != FUNCTION_TYPE)
  	    {
! 	      if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
! 		  & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
  		{
  		  WARN_FOR_QUALIFIERS (location, 0,
  				       G_("passing argument %d of %qE discards "
--- 5580,5589 ----
  	  else if (TREE_CODE (ttr) != FUNCTION_TYPE
  		   && TREE_CODE (ttl) != FUNCTION_TYPE)
  	    {
! 	      /* Assignments between atomic and non-atomic objects are OK since
! 	         the atomic access is always through an interface call.  */
! 	      if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
! 		  & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
  		{
  		  WARN_FOR_QUALIFIERS (location, 0,
  				       G_("passing argument %d of %qE discards "
Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c	(revision 201248)
--- gcc/objc/objc-act.c	(working copy)
*************** objc_push_parm (tree parm)
*** 8244,8249 ****
--- 8244,8250 ----
    c_apply_type_quals_to_decl
    ((TYPE_READONLY (TREE_TYPE (parm)) ? TYPE_QUAL_CONST : 0)
     | (TYPE_RESTRICT (TREE_TYPE (parm)) ? TYPE_QUAL_RESTRICT : 0)
+    | (TYPE_ATOMIC (TREE_TYPE (parm)) ? TYPE_QUAL_ATOMIC : 0)
     | (TYPE_VOLATILE (TREE_TYPE (parm)) ? TYPE_QUAL_VOLATILE : 0), parm);
  
    objc_parmlist = chainon (objc_parmlist, parm);
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h	(revision 201248)
--- gcc/cp/cp-tree.h	(working copy)
*************** enum languages { lang_c, lang_cplusplus,
*** 1293,1298 ****
--- 1293,1302 ----
  #define CP_TYPE_VOLATILE_P(NODE)			\
    ((cp_type_quals (NODE) & TYPE_QUAL_VOLATILE) != 0)
  
+ /* Nonzero if this type is atomic-qualified.  */
+ #define CP_TYPE_ATOMIC_P(NODE)				\
+   ((cp_type_quals (NODE) & TYPE_QUAL_ATOMIC) != 0)
+ 
  /* Nonzero if this type is restrict-qualified.  */
  #define CP_TYPE_RESTRICT_P(NODE)			\
    ((cp_type_quals (NODE) & TYPE_QUAL_RESTRICT) != 0)
*************** typedef enum cp_decl_spec {
*** 4758,4763 ****
--- 4762,4768 ----
    ds_const,
    ds_volatile,
    ds_restrict,
+   ds_atomic,
    ds_inline,
    ds_virtual,
    ds_explicit,
Index: gcc/cp/class.c
===================================================================
*** gcc/cp/class.c	(revision 201248)
--- gcc/cp/class.c	(working copy)
*************** build_simple_base_path (tree expr, tree
*** 542,548 ****
  	   to mark the expression itself.  */
  	if (type_quals & TYPE_QUAL_CONST)
  	  TREE_READONLY (expr) = 1;
! 	if (type_quals & TYPE_QUAL_VOLATILE)
  	  TREE_THIS_VOLATILE (expr) = 1;
  
  	return expr;
--- 542,548 ----
  	   to mark the expression itself.  */
  	if (type_quals & TYPE_QUAL_CONST)
  	  TREE_READONLY (expr) = 1;
! 	if (type_quals & (TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
  	  TREE_THIS_VOLATILE (expr) = 1;
  
  	return expr;
Index: gcc/cp/cvt.c
===================================================================
*** gcc/cp/cvt.c	(revision 201248)
--- gcc/cp/cvt.c	(working copy)
*************** diagnose_ref_binding (location_t loc, tr
*** 385,390 ****
--- 385,396 ----
        else if (CP_TYPE_VOLATILE_P (ttl))
  	msg = G_("conversion to volatile reference type %q#T "
  	         "from rvalue of type %qT");
+       else if (CP_TYPE_ATOMIC_P (ttl) && decl)
+ 	msg = G_("initialization of atomic reference type %q#T from "
+ 	         "rvalue of type %qT");
+       else if (CP_TYPE_ATOMIC_P (ttl))
+ 	msg = G_("conversion to atomic reference type %q#T "
+ 	         "from rvalue of type %qT");
        else if (decl)
  	msg = G_("initialization of non-const reference type %q#T from "
  	         "rvalue of type %qT");
*************** convert_from_reference (tree val)
*** 537,543 ****
  	  so that we get the proper error message if the result is used
  	  to assign to.  Also, &* is supposed to be a no-op.  */
        TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
!       TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
        TREE_SIDE_EFFECTS (ref)
  	= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
        val = ref;
--- 543,550 ----
  	  so that we get the proper error message if the result is used
  	  to assign to.  Also, &* is supposed to be a no-op.  */
        TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
!       TREE_THIS_VOLATILE (ref) = (CP_TYPE_VOLATILE_P (t) 
! 				  || CP_TYPE_ATOMIC_P (t));
        TREE_SIDE_EFFECTS (ref)
  	= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
        val = ref;
*************** convert_to_void (tree expr, impl_conv_vo
*** 1010,1016 ****
  	tree type = TREE_TYPE (expr);
  	int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
  			   == REFERENCE_TYPE;
! 	int is_volatile = TYPE_VOLATILE (type);
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
  	/* Can't load the value if we don't know the type.  */
--- 1017,1023 ----
  	tree type = TREE_TYPE (expr);
  	int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
  			   == REFERENCE_TYPE;
! 	int is_volatile = (TYPE_VOLATILE (type) || TYPE_ATOMIC (type));
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
  	/* Can't load the value if we don't know the type.  */
*************** convert_to_void (tree expr, impl_conv_vo
*** 1170,1176 ****
  	tree type = TREE_TYPE (expr);
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
! 	if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning))
  	  switch (implicit)
  	    {
  	      case ICV_CAST:
--- 1177,1184 ----
  	tree type = TREE_TYPE (expr);
  	int is_complete = COMPLETE_TYPE_P (complete_type (type));
  
! 	if ((TYPE_VOLATILE (type) || TYPE_ATOMIC (type))
! 	    && !is_complete && (complain & tf_warning))
  	  switch (implicit)
  	    {
  	      case ICV_CAST:
Index: gcc/cp/decl.c
===================================================================
*** gcc/cp/decl.c	(revision 201248)
--- gcc/cp/decl.c	(working copy)
*************** grokfndecl (tree ctype,
*** 7368,7374 ****
    for (t = parms; t; t = DECL_CHAIN (t))
      DECL_CONTEXT (t) = decl;
    /* Propagate volatile out from type to decl.  */
!   if (TYPE_VOLATILE (type))
      TREE_THIS_VOLATILE (decl) = 1;
  
    /* Setup decl according to sfk.  */
--- 7368,7374 ----
    for (t = parms; t; t = DECL_CHAIN (t))
      DECL_CONTEXT (t) = decl;
    /* Propagate volatile out from type to decl.  */
!   if (TYPE_VOLATILE (type) || TYPE_ATOMIC (type))
      TREE_THIS_VOLATILE (decl) = 1;
  
    /* Setup decl according to sfk.  */
*************** build_ptrmemfunc_type (tree type)
*** 7984,7989 ****
--- 7984,7990 ----
        TYPE_READONLY (t) = (type_quals & TYPE_QUAL_CONST) != 0;
        TYPE_VOLATILE (t) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
        TYPE_RESTRICT (t) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+       TYPE_ATOMIC (t) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
        TYPE_MAIN_VARIANT (t) = unqualified_variant;
        TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
        TYPE_NEXT_VARIANT (unqualified_variant) = t;
*************** grokdeclarator (const cp_declarator *dec
*** 9199,9204 ****
--- 9200,9207 ----
      type_quals |= TYPE_QUAL_VOLATILE;
    if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
      type_quals |= TYPE_QUAL_RESTRICT;
+   if (decl_spec_seq_has_spec_p (declspecs, ds_atomic))
+     type_quals |= TYPE_QUAL_ATOMIC;
    if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
      error ("qualifiers are not allowed on declaration of %<operator %T%>",
  	   ctor_return_type);
Index: gcc/cp/mangle.c
===================================================================
*** gcc/cp/mangle.c	(revision 201248)
--- gcc/cp/mangle.c	(working copy)
*************** dump_substitution_candidates (void)
*** 326,331 ****
--- 326,332 ----
        if (TYPE_P (el) &&
  	  (CP_TYPE_RESTRICT_P (el)
  	   || CP_TYPE_VOLATILE_P (el)
+ 	   || CP_TYPE_ATOMIC_P (el)
  	   || CP_TYPE_CONST_P (el)))
  	fprintf (stderr, "CV-");
        fprintf (stderr, "%s (%s at %p)\n",
Index: gcc/cp/parser.c
===================================================================
*** gcc/cp/parser.c	(revision 201248)
--- gcc/cp/parser.c	(working copy)
*************** cp_parser_type_specifier (cp_parser* par
*** 14090,14095 ****
--- 14090,14103 ----
  	*is_cv_qualifier = true;
        break;
  
+     case RID_ATOMIC:
+       ds = ds_atomic;
+       if (is_cv_qualifier)
+ 	*is_cv_qualifier = true;
+       if (!flag_isoc11)
+         pedwarn (token->location, 0, "_Atomic qualifier provided in ISO C11");
+       break;
+ 
      case RID_RESTRICT:
        ds = ds_restrict;
        if (is_cv_qualifier)
*************** cp_parser_cv_qualifier_seq_opt (cp_parse
*** 17341,17346 ****
--- 17349,17358 ----
  	  cv_qualifier = TYPE_QUAL_RESTRICT;
  	  break;
  
+ 	case RID_ATOMIC:
+ 	  cv_qualifier = TYPE_QUAL_ATOMIC;
+ 	  break;
+ 
  	default:
  	  cv_qualifier = TYPE_UNQUALIFIED;
  	  break;
*************** set_and_check_decl_spec_loc (cp_decl_spe
*** 23477,23482 ****
--- 23489,23495 ----
  	    "const",
  	    "volatile",
  	    "restrict",
+ 	    "atomic"
  	    "inline",
  	    "virtual",
  	    "explicit",
Index: gcc/cp/pt.c
===================================================================
*** gcc/cp/pt.c	(revision 201248)
--- gcc/cp/pt.c	(working copy)
*************** check_cv_quals_for_unify (int strict, tr
*** 16375,16381 ****
        if ((TREE_CODE (arg) == REFERENCE_TYPE
  	   || TREE_CODE (arg) == FUNCTION_TYPE
  	   || TREE_CODE (arg) == METHOD_TYPE)
! 	  && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)))
  	return 0;
  
        if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
--- 16375,16382 ----
        if ((TREE_CODE (arg) == REFERENCE_TYPE
  	   || TREE_CODE (arg) == FUNCTION_TYPE
  	   || TREE_CODE (arg) == METHOD_TYPE)
! 	  && (parm_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE 
! 			    | TYPE_QUAL_ATOMIC)))
  	return 0;
  
        if ((!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM)
Index: gcc/cp/rtti.c
===================================================================
*** gcc/cp/rtti.c	(revision 201248)
--- gcc/cp/rtti.c	(working copy)
*************** qualifier_flags (tree type)
*** 808,813 ****
--- 808,815 ----
      flags |= 2;
    if (quals & TYPE_QUAL_RESTRICT)
      flags |= 4;
+   if (quals & TYPE_QUAL_ATOMIC)
+     flags |= 8;
    return flags;
  }
  
Index: gcc/cp/semantics.c
===================================================================
*** gcc/cp/semantics.c	(revision 201248)
--- gcc/cp/semantics.c	(working copy)
*************** non_const_var_error (tree r)
*** 7776,7781 ****
--- 7776,7784 ----
        else if (CP_TYPE_VOLATILE_P (type))
  	inform (DECL_SOURCE_LOCATION (r),
  		"%q#D is volatile", r);
+       else if (CP_TYPE_ATOMIC_P (type))
+ 	inform (DECL_SOURCE_LOCATION (r),
+ 		"%q#D is atomic", r);
        else if (!DECL_INITIAL (r)
  	       || !TREE_CONSTANT (DECL_INITIAL (r)))
  	inform (DECL_SOURCE_LOCATION (r),
Index: gcc/cp/tree.c
===================================================================
*** gcc/cp/tree.c	(revision 201248)
--- gcc/cp/tree.c	(working copy)
*************** cp_build_qualified_type_real (tree type,
*** 1059,1072 ****
    /* A reference or method type shall not be cv-qualified.
       [dcl.ref], [dcl.fct].  This used to be an error, but as of DR 295
       (in CD1) we always ignore extra cv-quals on functions.  */
!   if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
        && (TREE_CODE (type) == REFERENCE_TYPE
  	  || TREE_CODE (type) == FUNCTION_TYPE
  	  || TREE_CODE (type) == METHOD_TYPE))
      {
        if (TREE_CODE (type) == REFERENCE_TYPE)
! 	bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
!       type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
      }
  
    /* But preserve any function-cv-quals on a FUNCTION_TYPE.  */
--- 1059,1073 ----
    /* A reference or method type shall not be cv-qualified.
       [dcl.ref], [dcl.fct].  This used to be an error, but as of DR 295
       (in CD1) we always ignore extra cv-quals on functions.  */
!   if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC)
        && (TREE_CODE (type) == REFERENCE_TYPE
  	  || TREE_CODE (type) == FUNCTION_TYPE
  	  || TREE_CODE (type) == METHOD_TYPE))
      {
        if (TREE_CODE (type) == REFERENCE_TYPE)
! 	bad_quals |= type_quals 
! 		    & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC);
!       type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_ATOMIC);
      }
  
    /* But preserve any function-cv-quals on a FUNCTION_TYPE.  */
*************** cv_unqualified (tree type)
*** 1142,1148 ****
      return type;
  
    quals = cp_type_quals (type);
!   quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
    return cp_build_qualified_type (type, quals);
  }
  
--- 1143,1149 ----
      return type;
  
    quals = cp_type_quals (type);
!   quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC);
    return cp_build_qualified_type (type, quals);
  }
  
Index: gcc/cp/typeck.c
===================================================================
*** gcc/cp/typeck.c	(revision 201248)
--- gcc/cp/typeck.c	(working copy)
*************** build_class_member_access_expr (tree obj
*** 2417,2423 ****
  	 expression itself.  */
        if (type_quals & TYPE_QUAL_CONST)
  	TREE_READONLY (result) = 1;
!       if (type_quals & TYPE_QUAL_VOLATILE)
  	TREE_THIS_VOLATILE (result) = 1;
      }
    else if (BASELINK_P (member))
--- 2417,2423 ----
  	 expression itself.  */
        if (type_quals & TYPE_QUAL_CONST)
  	TREE_READONLY (result) = 1;
!       if (type_quals & (TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
  	TREE_THIS_VOLATILE (result) = 1;
      }
    else if (BASELINK_P (member))
*************** cp_build_indirect_ref (tree ptr, ref_ope
*** 2941,2947 ****
  	     so that we get the proper error message if the result is used
  	     to assign to.  Also, &* is supposed to be a no-op.  */
  	  TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! 	  TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
  	  TREE_SIDE_EFFECTS (ref)
  	    = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
  	  return ref;
--- 2941,2948 ----
  	     so that we get the proper error message if the result is used
  	     to assign to.  Also, &* is supposed to be a no-op.  */
  	  TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
! 	  TREE_THIS_VOLATILE (ref) = (CP_TYPE_VOLATILE_P (t) 
! 				      || CP_TYPE_ATOMIC_P (t));
  	  TREE_SIDE_EFFECTS (ref)
  	    = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer));
  	  return ref;
*************** cp_build_array_ref (location_t loc, tree
*** 3126,3134 ****
        TREE_READONLY (rval)
  	|= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
        TREE_SIDE_EFFECTS (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
        TREE_THIS_VOLATILE (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
        ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
  					  complain);
        protected_set_expr_location (ret, loc);
--- 3127,3137 ----
        TREE_READONLY (rval)
  	|= (CP_TYPE_CONST_P (type) | TREE_READONLY (array));
        TREE_SIDE_EFFECTS (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array)
! 	    | CP_TYPE_ATOMIC_P (type));
        TREE_THIS_VOLATILE (rval)
! 	|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array)
! 	    | CP_TYPE_ATOMIC_P (type));
        ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
  					  complain);
        protected_set_expr_location (ret, loc);
*************** check_return_expr (tree retval, bool *no
*** 8423,8429 ****
       && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
                       (TYPE_MAIN_VARIANT (functype)))
       /* And the returned value must be non-volatile.  */
!      && ! TYPE_VOLATILE (TREE_TYPE (retval)));
       
    if (fn_returns_value_p && flag_elide_constructors)
      {
--- 8426,8433 ----
       && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
                       (TYPE_MAIN_VARIANT (functype)))
       /* And the returned value must be non-volatile.  */
!      && ! TYPE_VOLATILE (TREE_TYPE (retval)) 
!      && ! TYPE_ATOMIC (TREE_TYPE (retval)));
       
    if (fn_returns_value_p && flag_elide_constructors)
      {
*************** cp_type_quals (const_tree type)
*** 8691,8697 ****
    /* METHOD and REFERENCE_TYPEs should never have quals.  */
    gcc_assert ((TREE_CODE (type) != METHOD_TYPE
  	       && TREE_CODE (type) != REFERENCE_TYPE)
! 	      || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE))
  		  == TYPE_UNQUALIFIED));
    return quals;
  }
--- 8695,8701 ----
    /* METHOD and REFERENCE_TYPEs should never have quals.  */
    gcc_assert ((TREE_CODE (type) != METHOD_TYPE
  	       && TREE_CODE (type) != REFERENCE_TYPE)
! 	    || ((quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC))
  		  == TYPE_UNQUALIFIED));
    return quals;
  }
*************** bool
*** 8751,8757 ****
  cv_qualified_p (const_tree type)
  {
    int quals = cp_type_quals (type);
!   return (quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE)) != 0;
  }
  
  /* Returns nonzero if the TYPE contains a mutable member.  */
--- 8755,8761 ----
  cv_qualified_p (const_tree type)
  {
    int quals = cp_type_quals (type);
!   return (quals & (TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC)) != 0;
  }
  
  /* Returns nonzero if the TYPE contains a mutable member.  */
Index: gcc/doc/generic.texi
===================================================================
*** gcc/doc/generic.texi	(revision 201248)
--- gcc/doc/generic.texi	(working copy)
*************** This macro holds if the type is @code{co
*** 2547,2552 ****
--- 2547,2555 ----
  @item CP_TYPE_VOLATILE_P
  This macro holds if the type is @code{volatile}-qualified.
  
+ @item CP_TYPE_ATOMIC_P
+ This macro holds if the type is @code{atomic}-qualified.
+ 
  @item CP_TYPE_RESTRICT_P
  This macro holds if the type is @code{restrict}-qualified.
  

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

* [PATCH 4/5] Atomic type qualifier - Change built-in function types
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
  2013-07-30 17:13   ` [PATCH 2/5] Atomic type qualifier - Add atomic type to tree node Andrew MacLeod
@ 2013-07-30 17:14   ` Andrew MacLeod
  2013-07-30 17:14   ` [PATCH 3/5] Atomic type qualifier - front end changes Andrew MacLeod
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 17:14 UTC (permalink / raw)
  To: gcc-patches

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

This patch changes all the __Atomic built-in functions to take a pointer 
to an atomic volatile object instead of just a volatile object.

This will allow the atomic operations to work with any requested 
alignment change for a target.

I am not adding support for the __sync built-ins to expect the atomic 
qualifier as they are in deprecation mode.



[-- Attachment #2: f4.diff --]
[-- Type: text/x-patch, Size: 48825 bytes --]


	fortran
	* types.def (BT_ATOMIC_PTR, BT_CONST_ATOMIC_PTR): New
	primitive data types for volatile atomic pointers.
	(BT_FN_VOID_APTR): Renamed from BT_FN_VOID_VPTR.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT,
	BT_FN_BOOL_SIZE_CONST_VPTR): Renamed to APTR variant.
	(BT_FN_I{1,2,4,8,16}_CONST_APTR_INT): New.
	(BT_FN_I{1,2,4,8,16}_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT,
	BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, 
	BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_BOOL_INT_INT): Renamed to APTR
	variant.

	gcc
	* builtin-types.def (BT_ATOMIC_PTR, BT_CONST_ATOMIC_PTR): New
	primitive data types for volatile atomic pointers.
	(BT_FN_VOID_APTR): Renamed from BT_FN_VOID_VPTR.
	(BT_FN_VOID_VPTR_INT, BT_FN_BOOL_VPTR_INT,
	BT_FN_BOOL_SIZE_CONST_VPTR): Renamed to APTR variant.
	(BT_FN_I{1,2,4,8,16}_CONST_APTR_INT): New.
	(BT_FN_I{1,2,4,8,16}_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_APTR_I{1,2,4,8,16}_INT): New.
	(BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT,
	BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, 
	BT_FN_BOOL_VPTR_PTR_I{1,2,4,8,16}_BOOL_INT_INT): Renamed to APTR
	variant.
	* sync-builtins.def: Change all __atomic builtins to use the APTR
	atomic pointer variant for the first parameter instead of VPTR..

        doc
	* extend.texi: Add atomic pointer note to __atomic built-ins.

Index: gcc/fortran/types.def
===================================================================
*** gcc/fortran/types.def	(revision 201248)
--- gcc/fortran/types.def	(working copy)
*************** DEF_PRIMITIVE_TYPE (BT_CONST_VOLATILE_PT
*** 74,79 ****
--- 74,87 ----
  		    build_pointer_type
  		     (build_qualified_type (void_type_node,
  					  TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST)))
+ DEF_PRIMITIVE_TYPE (BT_ATOMIC_PTR,
+                     build_pointer_type
+                      (build_qualified_type (void_type_node,
+                                           TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC)))
+ DEF_PRIMITIVE_TYPE (BT_CONST_ATOMIC_PTR,
+                     build_pointer_type
+                      (build_qualified_type (void_type_node,
+                           TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST|TYPE_QUAL_ATOMIC)))
  DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG)
  DEF_POINTER_TYPE (BT_PTR_ULONGLONG, BT_ULONGLONG)
  DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR)
*************** DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_VPTR
*** 113,122 ****
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_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_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR)
  
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
--- 121,140 ----
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_VOLATILE_PTR,
  		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I1_CONST_APTR_INT, BT_I1, BT_CONST_ATOMIC_PTR, 
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I2_CONST_APTR_INT, BT_I2, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I4_CONST_APTR_INT, BT_I4, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_APTR_INT, BT_I8, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_APTR_INT, BT_I16, BT_CONST_ATOMIC_PTR,
!                      BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_VOID_APTR_INT, BT_VOID, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_APTR_INT, BT_BOOL, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_APTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR)
  
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_IN
*** 144,169 ****
  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_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR, BT_PTR, BT_INT)
  
  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_VOID_SIZE_VPTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, 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,
--- 162,197 ----
  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_I1_APTR_I1_INT, BT_I1, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I2_APTR_I2_INT, BT_I2, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I4_APTR_I4_INT, BT_I4, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I8_APTR_I8_INT, BT_I8, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I16_APTR_I16_INT, BT_I16, BT_ATOMIC_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_3 (BT_FN_VOID_APTR_I1_INT, BT_VOID, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I2_INT, BT_VOID, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I4_INT, BT_VOID, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I8_INT, BT_VOID, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I16_INT, BT_VOID, BT_ATOMIC_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_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR, BT_PTR, BT_INT)
  
  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_VOID_SIZE_APTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, 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,
*************** DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PT
*** 174,196 ****
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
--- 202,224 ----
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_APTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
                       BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
Index: gcc/builtin-types.def
===================================================================
*** gcc/builtin-types.def	(revision 201248)
--- gcc/builtin-types.def	(working copy)
*************** DEF_PRIMITIVE_TYPE (BT_CONST_VOLATILE_PT
*** 99,104 ****
--- 99,112 ----
  		    build_pointer_type
  		     (build_qualified_type (void_type_node,
  					  TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST)))
+ DEF_PRIMITIVE_TYPE (BT_ATOMIC_PTR,
+ 		    build_pointer_type
+ 		     (build_qualified_type (void_type_node,
+ 					  TYPE_QUAL_VOLATILE|TYPE_QUAL_ATOMIC)))
+ DEF_PRIMITIVE_TYPE (BT_CONST_ATOMIC_PTR,
+ 		    build_pointer_type
+ 		     (build_qualified_type (void_type_node,
+ 			  TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST|TYPE_QUAL_ATOMIC)))
  DEF_PRIMITIVE_TYPE (BT_PTRMODE, (*lang_hooks.types.type_for_mode)(ptr_mode, 0))
  DEF_PRIMITIVE_TYPE (BT_INT_PTR, integer_ptr_type_node)
  DEF_PRIMITIVE_TYPE (BT_FLOAT_PTR, float_ptr_type_node)
*************** DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLO
*** 223,228 ****
--- 231,237 ----
  DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64)
  DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128)
  DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
+ DEF_FUNCTION_TYPE_1 (BT_FN_VOID_APTR, BT_VOID, BT_ATOMIC_PTR)
  DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
  DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG)
*************** DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_VPTR
*** 337,346 ****
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_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_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR)
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
--- 346,365 ----
  		     BT_INT)
  DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_VOLATILE_PTR,
  		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I1_CONST_APTR_INT, BT_I1, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I2_CONST_APTR_INT, BT_I2, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I4_CONST_APTR_INT, BT_I4, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_APTR_INT, BT_I8, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_APTR_INT, BT_I16, BT_CONST_ATOMIC_PTR,
! 		     BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_VOID_APTR_INT, BT_VOID, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_APTR_INT, BT_BOOL, BT_ATOMIC_PTR, BT_INT)
! DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_APTR, BT_BOOL, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR)
  
  DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
  
*************** DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_IN
*** 420,430 ****
--- 439,460 ----
  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_I1_APTR_I1_INT, BT_I1, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I2_APTR_I2_INT, BT_I2, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I4_APTR_I4_INT, BT_I4, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I8_APTR_I8_INT, BT_I8, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_I16_APTR_I16_INT, BT_I16, BT_ATOMIC_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_3 (BT_FN_VOID_APTR_I1_INT, BT_VOID, BT_ATOMIC_PTR, BT_I1, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I2_INT, BT_VOID, BT_ATOMIC_PTR, BT_I2, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I4_INT, BT_VOID, BT_ATOMIC_PTR, BT_I4, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I8_INT, BT_VOID, BT_ATOMIC_PTR, BT_I8, BT_INT)
+ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_APTR_I16_INT, BT_VOID, BT_ATOMIC_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_4 (BT_FN_VOID_OMPFN_PT
*** 444,453 ****
  		     BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_VOLATILE_PTR, BT_PTR, BT_INT)
  
  DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
  		     BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
--- 474,483 ----
  		     BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
  DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
  		     BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_INT)
! DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_APTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_CONST_ATOMIC_PTR, BT_PTR, BT_INT)
  
  DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
  		     BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
*************** DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_IN
*** 455,462 ****
  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_VOID_SIZE_VPTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT)
  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,
--- 485,492 ----
  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_VOID_SIZE_APTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, BT_INT)
  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,
*************** DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PT
*** 480,502 ****
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
--- 510,532 ----
  DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
  		     BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
  		     BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I1_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I2_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I4_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I8_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_APTR_PTR_I16_BOOL_INT_INT, 
! 		     BT_BOOL, BT_ATOMIC_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
  		     BT_INT)
! DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_APTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
! 		     BT_ATOMIC_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
  
  
  DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
Index: gcc/sync-builtins.def
===================================================================
*** gcc/sync-builtins.def	(revision 201248)
--- gcc/sync-builtins.def	(working copy)
*************** DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SYNCHRON
*** 260,567 ****
  /* __sync* builtins for the C++ memory model.  */
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set",
! 		  BT_FN_BOOL_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
! DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_VPTR_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE,
  		  "__atomic_exchange",
! 		  BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_N,
  		  "__atomic_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_1,
  		  "__atomic_exchange_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_2,
  		  "__atomic_exchange_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_4,
  		  "__atomic_exchange_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_8,
  		  "__atomic_exchange_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_16,
  		  "__atomic_exchange_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD,
  		  "__atomic_load",
! 		  BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_N,
  		  "__atomic_load_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_1,
  		  "__atomic_load_1",
! 		  BT_FN_I1_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_2,
  		  "__atomic_load_2",
! 		  BT_FN_I2_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_4,
  		  "__atomic_load_4",
! 		  BT_FN_I4_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_8,
  		  "__atomic_load_8",
! 		  BT_FN_I8_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_16,
  		  "__atomic_load_16",
! 		  BT_FN_I16_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE,
  		  "__atomic_compare_exchange",
! 		  BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N,
  		  "__atomic_compare_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1,
  		  "__atomic_compare_exchange_1",
! 		  BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2,
  		  "__atomic_compare_exchange_2",
! 		  BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
  		  "__atomic_compare_exchange_4",
! 		  BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
  		  "__atomic_compare_exchange_8",
! 		  BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16,
  		  "__atomic_compare_exchange_16",
! 		  BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE,
  		  "__atomic_store",
! 		  BT_FN_VOID_SIZE_VPTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_N,
  		  "__atomic_store_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_1,
  		  "__atomic_store_1",
! 		  BT_FN_VOID_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_2,
  		  "__atomic_store_2",
! 		  BT_FN_VOID_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_4,
  		  "__atomic_store_4",
! 		  BT_FN_VOID_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_8,
  		  "__atomic_store_8",
! 		  BT_FN_VOID_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_16,
  		  "__atomic_store_16",
! 		  BT_FN_VOID_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_N,
  		  "__atomic_add_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_1,
  		  "__atomic_add_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_2,
  		  "__atomic_add_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_4,
  		  "__atomic_add_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_8,
  		  "__atomic_add_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_16,
  		  "__atomic_add_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_N,
  		  "__atomic_sub_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_1,
  		  "__atomic_sub_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_2,
  		  "__atomic_sub_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_4,
  		  "__atomic_sub_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_8,
  		  "__atomic_sub_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_16,
  		  "__atomic_sub_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_N,
  		  "__atomic_and_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_1,
  		  "__atomic_and_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_2,
  		  "__atomic_and_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_4,
  		  "__atomic_and_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_8,
  		  "__atomic_and_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_16,
  		  "__atomic_and_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_N,
  		  "__atomic_nand_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_1,
  		  "__atomic_nand_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_2,
  		  "__atomic_nand_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_4,
  		  "__atomic_nand_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_8,
  		  "__atomic_nand_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_16,
  		  "__atomic_nand_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_N,
  		  "__atomic_xor_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_1,
  		  "__atomic_xor_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_2,
  		  "__atomic_xor_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_4,
  		  "__atomic_xor_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_8,
  		  "__atomic_xor_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_16,
  		  "__atomic_xor_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_N,
  		  "__atomic_or_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_1,
  		  "__atomic_or_fetch_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_2,
  		  "__atomic_or_fetch_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_4,
  		  "__atomic_or_fetch_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_8,
  		  "__atomic_or_fetch_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_16,
  		  "__atomic_or_fetch_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_N,
  		  "__atomic_fetch_add",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_1,
  		  "__atomic_fetch_add_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_2,
  		  "__atomic_fetch_add_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_4,
  		  "__atomic_fetch_add_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_8,
  		  "__atomic_fetch_add_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_16,
  		  "__atomic_fetch_add_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_N,
  		  "__atomic_fetch_sub",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_1,
  		  "__atomic_fetch_sub_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_2,
  		  "__atomic_fetch_sub_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_4,
  		  "__atomic_fetch_sub_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_8,
  		  "__atomic_fetch_sub_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_16,
  		  "__atomic_fetch_sub_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_N,
  		  "__atomic_fetch_and",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_1,
  		  "__atomic_fetch_and_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_2,
  		  "__atomic_fetch_and_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_4,
  		  "__atomic_fetch_and_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_8,
  		  "__atomic_fetch_and_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_16,
  		  "__atomic_fetch_and_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_N,
  		  "__atomic_fetch_nand",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_1,
  		  "__atomic_fetch_nand_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_2,
  		  "__atomic_fetch_nand_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_4,
  		  "__atomic_fetch_nand_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_8,
  		  "__atomic_fetch_nand_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_16,
  		  "__atomic_fetch_nand_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_N,
  		  "__atomic_fetch_xor",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_1,
  		  "__atomic_fetch_xor_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_2,
  		  "__atomic_fetch_xor_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_4,
  		  "__atomic_fetch_xor_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_8,
  		  "__atomic_fetch_xor_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_16,
  		  "__atomic_fetch_xor_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_N,
--- 260,567 ----
  /* __sync* builtins for the C++ memory model.  */
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set",
! 		  BT_FN_BOOL_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
! DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_APTR_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE,
  		  "__atomic_exchange",
! 		  BT_FN_VOID_SIZE_APTR_PTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_N,
  		  "__atomic_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_1,
  		  "__atomic_exchange_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_2,
  		  "__atomic_exchange_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_4,
  		  "__atomic_exchange_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_8,
  		  "__atomic_exchange_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_16,
  		  "__atomic_exchange_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD,
  		  "__atomic_load",
! 		  BT_FN_VOID_SIZE_CONST_APTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_N,
  		  "__atomic_load_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_1,
  		  "__atomic_load_1",
! 		  BT_FN_I1_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_2,
  		  "__atomic_load_2",
! 		  BT_FN_I2_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_4,
  		  "__atomic_load_4",
! 		  BT_FN_I4_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_8,
  		  "__atomic_load_8",
! 		  BT_FN_I8_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_16,
  		  "__atomic_load_16",
! 		  BT_FN_I16_CONST_APTR_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE,
  		  "__atomic_compare_exchange",
! 		  BT_FN_BOOL_SIZE_APTR_PTR_PTR_INT_INT,
  		  ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N,
  		  "__atomic_compare_exchange_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1,
  		  "__atomic_compare_exchange_1",
! 		  BT_FN_BOOL_APTR_PTR_I1_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2,
  		  "__atomic_compare_exchange_2",
! 		  BT_FN_BOOL_APTR_PTR_I2_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
  		  "__atomic_compare_exchange_4",
! 		  BT_FN_BOOL_APTR_PTR_I4_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
  		  "__atomic_compare_exchange_8",
! 		  BT_FN_BOOL_APTR_PTR_I8_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16,
  		  "__atomic_compare_exchange_16",
! 		  BT_FN_BOOL_APTR_PTR_I16_BOOL_INT_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE,
  		  "__atomic_store",
! 		  BT_FN_VOID_SIZE_APTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_N,
  		  "__atomic_store_n",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_1,
  		  "__atomic_store_1",
! 		  BT_FN_VOID_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_2,
  		  "__atomic_store_2",
! 		  BT_FN_VOID_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_4,
  		  "__atomic_store_4",
! 		  BT_FN_VOID_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_8,
  		  "__atomic_store_8",
! 		  BT_FN_VOID_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_16,
  		  "__atomic_store_16",
! 		  BT_FN_VOID_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_N,
  		  "__atomic_add_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_1,
  		  "__atomic_add_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_2,
  		  "__atomic_add_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_4,
  		  "__atomic_add_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_8,
  		  "__atomic_add_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_16,
  		  "__atomic_add_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_N,
  		  "__atomic_sub_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_1,
  		  "__atomic_sub_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_2,
  		  "__atomic_sub_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_4,
  		  "__atomic_sub_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_8,
  		  "__atomic_sub_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_16,
  		  "__atomic_sub_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_N,
  		  "__atomic_and_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_1,
  		  "__atomic_and_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_2,
  		  "__atomic_and_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_4,
  		  "__atomic_and_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_8,
  		  "__atomic_and_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_16,
  		  "__atomic_and_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_N,
  		  "__atomic_nand_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_1,
  		  "__atomic_nand_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_2,
  		  "__atomic_nand_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_4,
  		  "__atomic_nand_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_8,
  		  "__atomic_nand_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_16,
  		  "__atomic_nand_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_N,
  		  "__atomic_xor_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_1,
  		  "__atomic_xor_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_2,
  		  "__atomic_xor_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_4,
  		  "__atomic_xor_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_8,
  		  "__atomic_xor_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_16,
  		  "__atomic_xor_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_N,
  		  "__atomic_or_fetch",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_1,
  		  "__atomic_or_fetch_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_2,
  		  "__atomic_or_fetch_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_4,
  		  "__atomic_or_fetch_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_8,
  		  "__atomic_or_fetch_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_16,
  		  "__atomic_or_fetch_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_N,
  		  "__atomic_fetch_add",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_1,
  		  "__atomic_fetch_add_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_2,
  		  "__atomic_fetch_add_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_4,
  		  "__atomic_fetch_add_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_8,
  		  "__atomic_fetch_add_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_16,
  		  "__atomic_fetch_add_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_N,
  		  "__atomic_fetch_sub",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_1,
  		  "__atomic_fetch_sub_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_2,
  		  "__atomic_fetch_sub_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_4,
  		  "__atomic_fetch_sub_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_8,
  		  "__atomic_fetch_sub_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_16,
  		  "__atomic_fetch_sub_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_N,
  		  "__atomic_fetch_and",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_1,
  		  "__atomic_fetch_and_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_2,
  		  "__atomic_fetch_and_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_4,
  		  "__atomic_fetch_and_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_8,
  		  "__atomic_fetch_and_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_16,
  		  "__atomic_fetch_and_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_N,
  		  "__atomic_fetch_nand",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_1,
  		  "__atomic_fetch_nand_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_2,
  		  "__atomic_fetch_nand_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_4,
  		  "__atomic_fetch_nand_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_8,
  		  "__atomic_fetch_nand_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_16,
  		  "__atomic_fetch_nand_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_N,
  		  "__atomic_fetch_xor",
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_1,
  		  "__atomic_fetch_xor_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_2,
  		  "__atomic_fetch_xor_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_4,
  		  "__atomic_fetch_xor_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_8,
  		  "__atomic_fetch_xor_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_16,
  		  "__atomic_fetch_xor_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_N,
*************** DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_
*** 569,595 ****
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_1,
  		  "__atomic_fetch_or_1",
! 		  BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_2,
  		  "__atomic_fetch_or_2",
! 		  BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_4,
  		  "__atomic_fetch_or_4",
! 		  BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_8,
  		  "__atomic_fetch_or_8",
! 		  BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_16,
  		  "__atomic_fetch_or_16",
! 		  BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE,
  		  "__atomic_always_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_VPTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_IS_LOCK_FREE,
  		  "__atomic_is_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_VPTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_THREAD_FENCE,
--- 569,595 ----
  		  BT_FN_VOID_VAR, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_1,
  		  "__atomic_fetch_or_1",
! 		  BT_FN_I1_APTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_2,
  		  "__atomic_fetch_or_2",
! 		  BT_FN_I2_APTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_4,
  		  "__atomic_fetch_or_4",
! 		  BT_FN_I4_APTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_8,
  		  "__atomic_fetch_or_8",
! 		  BT_FN_I8_APTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_16,
  		  "__atomic_fetch_or_16",
! 		  BT_FN_I16_APTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE,
  		  "__atomic_always_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_APTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_IS_LOCK_FREE,
  		  "__atomic_is_lock_free",
! 		  BT_FN_BOOL_SIZE_CONST_APTR, ATTR_CONST_NOTHROW_LEAF_LIST)
  
  
  DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_THREAD_FENCE,
Index: gcc/doc/extend.texi
===================================================================
*** gcc/doc/extend.texi	(revision 201248)
--- gcc/doc/extend.texi	(working copy)
*************** reserved for the memory model.  The rema
*** 7320,7325 ****
--- 7320,7334 ----
  for future use and should be 0.  Use of the predefined atomic values
  ensures proper usage.
  
+ All __atomic built-in functions expect the first parameter to be a type with
+ the atomic attribute set.  It is OK on most targets to continue using the
+ non-atomic version for backward compatability. The only time there will be a
+ compatability issues is if the atomic implementation for a target overrides 
+ the alignment of the atomic type in order to implement lock free routines.
+ This facility did not exist before GCC 4.9, so there are no compatibility
+ issues up until then.  Targets with such requirements would have had
+ non-function atomic lockfree operations up until this facility became available.
+ 
  @deftypefn {Built-in Function} @var{type} __atomic_load_n (@var{type} *ptr, int memmodel)
  This built-in function implements an atomic load operation.  It returns the
  contents of @code{*@var{ptr}}.

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

* [PATCH 1/5] Atomic type qualifier - Add type alignment override hook
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
                     ` (2 preceding siblings ...)
  2013-07-30 17:14   ` [PATCH 3/5] Atomic type qualifier - front end changes Andrew MacLeod
@ 2013-07-30 17:14   ` Andrew MacLeod
  2013-07-30 17:32   ` [PATCH 5/5] Atomic type qualifier - Use atomic objects Andrew MacLeod
  2013-08-02 19:22   ` [PATCH] - C11 expressions and stdatomic.h - Just for current state Andrew MacLeod
  5 siblings, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 17:14 UTC (permalink / raw)
  To: gcc-patches

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

This patch adds a target hook which a target can use to override the 
alignment of the lock-free atomic type for a given mode.

Andrew


[-- Attachment #2: f1.diff --]
[-- Type: text/x-patch, Size: 3667 bytes --]



	* hooks.c (hook_uint_mode_0): Return 0 unit hook.
	* hooks.h (hook_uint_mode_0): Prototype.
	* target.def (atomic_align_for_mode): define hook.
	* tm.texi (TARGET_ATOMIC_TYPE_FOR_MODE): Define.
	* doc/tm.texi.in (TARGET_ATOMIC_TYPE_FOR_MODE): Add.

Index: gcc/hooks.c
===================================================================
*** gcc/hooks.c	(revision 201248)
--- gcc/hooks.c	(working copy)
*************** hook_rtx_tree_int_null (tree a ATTRIBUTE
*** 352,357 ****
--- 352,364 ----
    return NULL;
  }
  
+ /* Generic hook that takes a machine mode and returns an unsigned int 0.  */
+ unsigned int
+ hook_uint_mode_0 (enum machine_mode m ATTRIBUTE_UNUSED)
+ {
+   return 0;
+ }
+ 
  /* Generic hook that takes three trees and returns the last one as is.  */
  tree
  hook_tree_tree_tree_tree_3rd_identity (tree a ATTRIBUTE_UNUSED,
Index: gcc/hooks.h
===================================================================
*** gcc/hooks.h	(revision 201248)
--- gcc/hooks.h	(working copy)
*************** extern tree hook_tree_tree_tree_tree_3rd
*** 89,94 ****
--- 89,95 ----
  extern tree hook_tree_tree_int_treep_bool_null (tree, int, tree *, bool);
  
  extern unsigned hook_uint_void_0 (void);
+ extern unsigned int hook_uint_mode_0 (enum machine_mode);
  
  extern bool default_can_output_mi_thunk_no_vcall (const_tree, HOST_WIDE_INT,
  						  HOST_WIDE_INT, const_tree);
Index: gcc/target.def
===================================================================
*** gcc/target.def	(revision 201248)
--- gcc/target.def	(working copy)
*************** DEFHOOKPOD
*** 5116,5122 ****
   @code{atomic_test_and_set} is not exactly 1, i.e. the\
   @code{bool} @code{true}.",
   unsigned char, 1)
!  
  /* Leave the boolean fields at the end.  */
  
  /* True if we can create zeroed data by switching to a BSS section
--- 5116,5134 ----
   @code{atomic_test_and_set} is not exactly 1, i.e. the\
   @code{bool} @code{true}.",
   unsigned char, 1)
! 
! /* Return an unsigned int representing the alignment (in bits) of the atomic
!    type which maps to machine MODE.  This allows alignment to be overridden
!    as needed.  */
! DEFHOOK
! (atomic_align_for_mode,
! "If defined, this function returns an appropriate alignment in bits for an\
!  atomic object of machine_mode @var{mode}.  If 0 is returned then the\
!  default alignment for the specified mode is used. ",
!  unsigned int, (enum machine_mode mode),
!  hook_uint_mode_0)
! 
! 
  /* Leave the boolean fields at the end.  */
  
  /* True if we can create zeroed data by switching to a BSS section
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi	(revision 201248)
--- gcc/doc/tm.texi	(working copy)
*************** It returns true if the target supports G
*** 11375,11377 ****
--- 11375,11381 ----
  The support includes the assembler, linker and dynamic linker.
  The default value of this hook is based on target's libc.
  @end deftypefn
+ 
+ @deftypefn {Target Hook} {unsigned int} TARGET_ATOMIC_ALIGN_FOR_MODE (enum machine_mode @var{mode})
+ If defined, this function returns an appropriate alignment in bits for an atomic object of machine_mode @var{mode}.  If 0 is returned then the default alignment for the specified mode is used. 
+ @end deftypefn
Index: gcc/doc/tm.texi.in
===================================================================
*** gcc/doc/tm.texi.in	(revision 201248)
--- gcc/doc/tm.texi.in	(working copy)
*************** and the associated definitions of those
*** 8415,8417 ****
--- 8415,8419 ----
  @hook TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
  
  @hook TARGET_HAS_IFUNC_P
+ 
+ @hook TARGET_ATOMIC_ALIGN_FOR_MODE

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

* [PATCH 5/5] Atomic type qualifier - Use atomic objects
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
                     ` (3 preceding siblings ...)
  2013-07-30 17:14   ` [PATCH 1/5] Atomic type qualifier - Add type alignment override hook Andrew MacLeod
@ 2013-07-30 17:32   ` Andrew MacLeod
  2013-08-02 19:22   ` [PATCH] - C11 expressions and stdatomic.h - Just for current state Andrew MacLeod
  5 siblings, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-30 17:32 UTC (permalink / raw)
  To: gcc-patches

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

This patch turns on the atomic qualifier for all C++ atomic objects

It also modifies a few testcases to ensure __attribute__((atomic)) and 
_Atomic are recognized by the compiler and compile as expected.



[-- Attachment #2: f5.diff --]
[-- Type: text/x-patch, Size: 11840 bytes --]


	libstdc++-v3
	* include/bits/atomic_base.h (struct __atomic_base): Add
	__attribute__((atomic) to member data element.
	(struct __atomic_base<_PTp*>): Add __attribute__((atomic)) to member
	data element.
	* include/std/atomic (struct atomic): Add __attribute__((atomic)) to
	member data element.

	testsuite
	* gcc.dg/atomic-exchange-{1-5}.c: Change atomic var to use
	__attribute__((atomic)).
	* gcc.dg/atomic-op-{1-5}.c: Add --std=c11 and change atomic var to
	use _Atomic keyword.


Index: libstdc++-v3/include/bits/atomic_base.h
===================================================================
*** libstdc++-v3/include/bits/atomic_base.h	(revision 201248)
--- libstdc++-v3/include/bits/atomic_base.h	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 346,361 ****
    // atomic_char32_t char32_t
    // atomic_wchar_t  wchar_t
    //
!   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or
!   // 8 bytes, since that is what GCC built-in functions for atomic
    // memory access expect.
    template<typename _ITp>
      struct __atomic_base
      {
      private:
!       typedef _ITp 	__int_type;
  
!       __int_type 	_M_i;
  
      public:
        __atomic_base() noexcept = default;
--- 346,362 ----
    // atomic_char32_t char32_t
    // atomic_wchar_t  wchar_t
    //
!   // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, 8, or
!   // 16 bytes, since that is what GCC built-in functions for atomic
    // memory access expect.
    template<typename _ITp>
      struct __atomic_base
      {
      private:
!       typedef _ITp 				__int_type;
!       typedef _ITp __attribute__ ((atomic))	__atomic_int_type;
  
!       __atomic_int_type _M_i;
  
      public:
        __atomic_base() noexcept = default;
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 669,677 ****
      struct __atomic_base<_PTp*>
      {
      private:
!       typedef _PTp* 	__pointer_type;
  
!       __pointer_type 	_M_p;
  
        // Factored out to facilitate explicit specialization.
        constexpr ptrdiff_t
--- 670,679 ----
      struct __atomic_base<_PTp*>
      {
      private:
!       typedef _PTp* 				__pointer_type;
!       typedef _PTp* __attribute ((atomic)) 	__atomic_pointer_type;
  
!       __atomic_pointer_type 	_M_p;
  
        // Factored out to facilitate explicit specialization.
        constexpr ptrdiff_t
Index: libstdc++-v3/include/std/atomic
===================================================================
*** libstdc++-v3/include/std/atomic	(revision 201248)
--- libstdc++-v3/include/std/atomic	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 161,167 ****
      struct atomic
      {
      private:
!       _Tp _M_i;
  
      public:
        atomic() noexcept = default;
--- 161,167 ----
      struct atomic
      {
      private:
!       _Tp __attribute ((atomic)) _M_i;
  
      public:
        atomic() noexcept = default;
Index: gcc/testsuite/gcc.dg/atomic-exchange-1.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-1.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-1.c	(working copy)
***************
*** 7,13 ****
  
  extern void abort(void);
  
! char v, count, ret;
  
  main ()
  {
--- 7,14 ----
  
  extern void abort(void);
  
! char __attribute__ ((atomic)) v;
! char count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-2.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-2.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-2.c	(working copy)
***************
*** 7,13 ****
  
  extern void abort(void);
  
! short v, count, ret;
  
  main ()
  {
--- 7,14 ----
  
  extern void abort(void);
  
! short __attribute__ ((atomic)) v;
! short count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-3.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-3.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-3.c	(working copy)
***************
*** 7,13 ****
  
  extern void abort(void);
  
! int v, count, ret;
  
  main ()
  {
--- 7,14 ----
  
  extern void abort(void);
  
! int __attribute__ ((atomic)) v;
! int count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-4.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-4.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-4.c	(working copy)
***************
*** 9,15 ****
  
  extern void abort(void);
  
! long long v, count, ret;
  
  main ()
  {
--- 9,16 ----
  
  extern void abort(void);
  
! long long __attribute__ ((atomic)) v;
! long long count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-exchange-5.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-exchange-5.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-exchange-5.c	(working copy)
***************
*** 8,14 ****
  
  extern void abort(void);
  
! __int128_t v, count, ret;
  
  main ()
  {
--- 8,15 ----
  
  extern void abort(void);
  
! __int128_t __attribute__ ((atomic)) v;
! __int128_t count, ret;
  
  main ()
  {
Index: gcc/testsuite/gcc.dg/atomic-op-1.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-1.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-1.c	(working copy)
***************
*** 1,13 ****
  /* Test __atomic routines for existence and proper execution on 1 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_char_short } */
  
  /* Test the execution of the __atomic_*OP builtin routines for a char.  */
  
  extern void abort(void);
  
! char v, count, res;
  const char init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 1,15 ----
  /* Test __atomic routines for existence and proper execution on 1 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_char_short } */
  
  /* Test the execution of the __atomic_*OP builtin routines for a char.  */
  
  extern void abort(void);
  
! _Atomic char v;
! char count, res;
  const char init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 527,532 ****
--- 529,535 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-2.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-2.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-2.c	(working copy)
***************
*** 1,6 ****
--- 1,7 ----
  /* Test __atomic routines for existence and proper execution on 2 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_char_short } */
  
  
***************
*** 8,14 ****
  
  extern void abort(void);
  
! short v, count, res;
  const short init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 9,16 ----
  
  extern void abort(void);
  
! _Atomic short v;
! short count, res;
  const short init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 528,533 ****
--- 530,536 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-3.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-3.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-3.c	(working copy)
***************
*** 1,13 ****
  /* Test __atomic routines for existence and proper execution on 4 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_int_long } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int.  */
  
  extern void abort(void);
  
! int v, count, res;
  const int init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 1,15 ----
  /* Test __atomic routines for existence and proper execution on 4 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_int_long } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int.  */
  
  extern void abort(void);
  
! _Atomic int v;
! int count, res;
  const int init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 527,532 ****
--- 529,535 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-4.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-4.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-4.c	(working copy)
***************
*** 2,15 ****
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_long_long_runtime } */
! /* { dg-options "" } */
! /* { dg-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for long long.  */
  
  extern void abort(void);
  
! long long v, count, res;
  const long long init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 2,16 ----
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_long_long_runtime } */
! /* { dg-options "--std=c11" } */
! /* { dg-options "--std=c11 -march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for long long.  */
  
  extern void abort(void);
  
! _Atomic long long v;
! long long count, res;
  const long long init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 529,534 ****
--- 530,536 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();
Index: gcc/testsuite/gcc.dg/atomic-op-5.c
===================================================================
*** gcc/testsuite/gcc.dg/atomic-op-5.c	(revision 201248)
--- gcc/testsuite/gcc.dg/atomic-op-5.c	(working copy)
***************
*** 1,14 ****
  /* Test __atomic routines for existence and proper execution on 16 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
  /* { dg-require-effective-target sync_int_128_runtime } */
! /* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int_128.  */
  
  extern void abort(void);
  
! __int128_t v, count, res;
  const __int128_t init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
--- 1,16 ----
  /* Test __atomic routines for existence and proper execution on 16 byte 
     values with each valid memory model.  */
  /* { dg-do run } */
+ /* { dg-options "--std=c11" } */
  /* { dg-require-effective-target sync_int_128_runtime } */
! /* { dg-options "--std=c11 -mcx16" { target { i?86-*-* x86_64-*-* } } } */
  
  /* Test the execution of the __atomic_*OP builtin routines for an int_128.  */
  
  extern void abort(void);
  
! _Atomic __int128_t v;
! __int128_t count, res;
  const __int128_t init = ~0;
  
  /* The fetch_op routines return the original value before the operation.  */
*************** test_or ()
*** 528,533 ****
--- 530,536 ----
      abort ();
  }
  
+ int
  main ()
  {
    test_fetch_add ();

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

* Re: [PATCH] Add atomic type qualifier
  2013-07-30 13:58               ` Andrew MacLeod
@ 2013-07-31 12:19                 ` Andrew MacLeod
  0 siblings, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-07-31 12:19 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, Richard Henderson

On 07/30/2013 09:44 AM, Andrew MacLeod wrote:
> On 07/30/2013 09:16 AM, Joseph S. Myers wrot
>
>
>>> THis also means that for the 3 floating point operations all we need 
>>> are RTL
>>> insn patterns, no buitin.  And as with the other atomics, if the 
>>> pattern
>> I think something will also be needed to specify allocation of the 
>> fenv_t
>> temporary (whether in memory or registers).
>>
>>> doesnt exist, we just wont emit it.  we could add a warning easily 
>>> enough in
>>> this case.
>> Note there's a difference between no need to emit it, no warning 
>> should be
>> given (soft float) and need to emit it but patterns not yet written so
>> warning should be given (hard float but patterns not yet implemented for
>> the architecture).
>
> In fact, the flag could be the presence of the fenv_t variable.. Null 
> for that variable field in the builtin indicate you don't need the 
> patterns emitted.
>
> I';ll get back to you in a bit with the actual built-in's format once 
> I poke around the existing one and see how I can leverage it. I 
> rewrote all that code last year and it ought to be pretty simple to 
> add new operand support.  It better be anyway :-)
>

I worked out the built-ins and what they need to do... and you know 
what?  I'm not sure I see the point any more.

I am going to give a shot at simply expanding this code right in the 
front end.   For the floating and complex types I'll create temps and 
pass them to the generic atomic routines for load and 
compare_exchange... I should be able to directly call the same routines 
that sort out what can be mapped to lock free and what can't.  And in 
the end, the optimizers can sort out how to make things better. that way 
we dont need any support anywhere else. (well, we may need 3 builtins 
for the floating point stuff.. I don't know..  I'll worry about that later.)

On a side note,  after Friday, I'm off for 2 weeks, so I'll be pretty 
quiet until  the 19th or 20th.

Btw, if anyone wants to take a stab at a stdatomic.h file, that would be 
OK with me :-)

Andrew




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

* Re: [PATCH] Add atomic type qualifier
  2013-07-26 23:58 ` Joseph S. Myers
  2013-07-27  1:15   ` Andrew MacLeod
@ 2013-08-01 21:54   ` Andrew MacLeod
  1 sibling, 0 replies; 31+ messages in thread
From: Andrew MacLeod @ 2013-08-01 21:54 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches

On 07/26/2013 07:21 PM, Joseph S. Myers wrote:
> On Fri, 26 Jul 2013, Andrew MacLeod wrote:
>
>> This patch adds an atomic type qualifier to GCC.   It can be accessed via
>> __attribute__((atomic)) or in C11 mode via the _Atomic keyword.
> Why the attribute - why not just the keyword?
>
>
> * When C11 refers to qualified types, by default it does not include
> atomic types (6.2.5#27).  What's your rationale for including "atomic" in
> TYPE_QUALS rather than making it separate?  With either approach, a review
> of every reference to qualifiers in the front end is needed to determine
> what's correct for "atomic"; did you find that including "atomic" in
> qualifiers in the implementation made for fewer changes?
>
Ive gotten the expressions mostly working  (= and op= work great), but 
am having some issues with plain loads and identifying the correct time 
to emit the load...   I've also hacked up a rough approximation of what 
stdatomic.h would need.

I also think I'll revisit how atomic values are marked in the front 
end... now that Im doing  all the real work in the front end, I don't 
think I want that attribute all over the place like I did before.     I 
may well decide to remove it from the qualifiers and make it a separate 
type now...   So don't worry about reviewing those files...

I likely wont get to this until I get back from vacation in a couple of 
weeks however.  I will post the state of things before I go, both for my 
own recollection when I return, and in case anyone just happens to feel 
really interested and wants to have a look at some of  the remaining 
required changes.  ha. I wish.    Its starting to get close tho.

Andrew

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

* [PATCH] - C11 expressions and stdatomic.h -   Just for current state
  2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
                     ` (4 preceding siblings ...)
  2013-07-30 17:32   ` [PATCH 5/5] Atomic type qualifier - Use atomic objects Andrew MacLeod
@ 2013-08-02 19:22   ` Andrew MacLeod
  2013-08-07 23:06     ` Joseph S. Myers
  5 siblings, 1 reply; 31+ messages in thread
From: Andrew MacLeod @ 2013-08-02 19:22 UTC (permalink / raw)
  To: gcc-patches

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

On 07/30/2013 12:49 PM, Andrew MacLeod wrote:
> I split the original patch into some smaller hunks, and cleaned up a 
> few bit and pieces here and there... following:
>
>
Not looking for a review, but posting progress to this point since I'm 
off for 2 weeks, and someone might want to play with this.

I re-examined implementing the atomic type as its own canonical type 
instead of a qualified variant, as well as some variations... and 
ultimately, I think the current qualified implementation I posted is 
probably the best one to work with.  Its very convenient to be able to 
get to the non-atomic type by using TYPE_MAIN_VARIANT...  Anyway, so the 
original 5 patches stand, but will require closer auditing . (starting 
at http://gcc.gnu.org/ml/gcc-patches/2013-07/msg01478.html)

I've attached 2 patches anda  header file here.  One is the changes 
required for handling the C11 atomic expressions...  ie x += 4.2, and 
the other is a first cut at the content for the stdatomic.h include 
file, adna  required change for it.

The atomic expression patch works on many cases, but falls short with 
any kind of complexity on the RHS of an expression which needs to be 
mapped to an atomic_load.  Whilst parsing, we cant tell, and the rhs 
tends to become an expression before we really know. so In the comments 
I have my proposed solution which I will look at when I return in 2 weeks.
Basically, rather than have the ATOMIC_TYPE attribute ripple all the way 
through an expression, as soon as we see an ATOMIC_TYPE, we wrap it in a 
new node ATOMIC_EXPR, which holds the atomic expression, and sets it own 
expression type to the non-atomic variant.  This means the only 
expressions which will have the TYPE_ATOMIC flag set will be ones which 
are wrapped in  ATOMIC_EXPR, and those are the ones where we need to go 
and replace with an __atomic_load or whatever.

I have also punted on the floating point exception stuff which footnote 
113 requires.. we'll worry about that later.

Nevertheless, the patch that is there can do some interest8ing things... 
it can compile and execute this test file successfully as proof of 
concept... with all the right conmversions and use of lockfree routines 
when available.  (use -mcx16 on an x86_64 box, btw, or the __atomic_*_16 
routines will be unresolved )   complex types also work.  long double 
complex is 32 bytes in size, and will make calls into libatomic to 
resolve those operations.

double __attribute__((atomic)) a;
float __attribute__((atomic)) t;
long double __attribute__((atomic))  ld;
char __attribute__((atomic)) c;
int __attribute__((atomic)) i;
long long __attribute__((atomic)) l;
int g;
main ()
{
   g = 40;
   ld = t = a = 4.567;
   c = l = i = g + 2;
   printf ("%f == %f == %Lf == 4.567\n", t, a, ld);
   printf ("%d == %d == %ld == 42\n", c , i, l);
}


I have also attach a mockup of stdatomic.h...   I haven't even tried 
compiling or testing it yet, so it may have a syntax error or something, 
but I wanted to see if the functionality was possible.
THe only thing missing is the ability to find the non-atomic type of an 
atomic type.

Ive included an additional 2 line patch which should  change the meaning 
of __typeof__  (again untested, the joys of imminently leaving for 2 
weeks  :-).   Im not sure the normal practical uses of
__typeof__ have much meaning for an atomic type, it seems far more 
useful to have __typeof__ for an atomic qualified type to return the 
non-atomic variant.   If there is resistance to that definition, then 
I'll need to create a __nonatomic_typeof__ variant...  thats just a bit 
more work.  In any case, that patch is required for stdatomic.h to be 
implemented.  You can see where I used it to call the generic atomic 
operations with all the proper types for the non-atomic fields which 
need a temp vazr.     The header file is actually quite short.  I don't 
know how to implement it other than with macro wrappers around the builtins.

And thats it. I'll be back in 2 weeks to get back at wrapping this, and 
adding some testcases and error reporting.

unless *YOU*  beat me to it :-)

Andrew





[-- Attachment #2: expr.diff --]
[-- Type: text/x-patch, Size: 14138 bytes --]


	* c/c-parser.c (c_parser_expr_no_commas): Call build_atomic_load on RHS.
	* c/c-typeck.c (build_modify_expr): Call build_atomic_assign for atomic
	expressions.
	(build_atomic_assign): New.  Construct appropriate sequences for
	atomic assignemnt operations.
	(build_atomic_load):  New.  Construct an atomic load.
	* c-family/c-common.h (build_atomic_load): Prototype.

Index: gcc/c/c-parser.c
===================================================================
*** gcc/c/c-parser.c	(revision 201248)
--- gcc/c/c-parser.c	(working copy)
*************** c_parser_expr_no_commas (c_parser *parse
*** 5440,5445 ****
--- 5440,5472 ----
        code = BIT_IOR_EXPR;
        break;
      default:
+       /* TODO
+ 	 This doesnt work. Expressions like ~a where a is atomic do not function
+ 	 properly. since the rhs is parsed/consumed as an entire expression.  
+ 	 and at the time, we don't know if this expression is a RHS or LHS, so
+ 	 we dont know if we need a load or not.
+ 
+ 	 I think we need to introduce an ATOMIC_EXPR node, and whenever the
+ 	 type of an expression becomes TYPE_ATOMIC(), we immiedately hang the
+ 	 expression off a new ATOMIC_EXPR node as operand 0, and change the
+ 	 type of the ATOMIC_EXPR node to TYPE_MAIN_VARIANT(atomic_type).  This
+ 	 will encapsulate all the expressions which need to be handled with an
+ 	 ATOMIC_EXPR node, and then at this point, scan the rhs and see if there
+ 	 are any ATOMIC_EXPR, and replace those nodes with atomic_loads's of 
+ 	 the ATOMIC_EXPR operand.
+ 
+ 	 THis will also change the LHS processing in build_modify_expr... 
+ 	 although *in theory* the top level expression *ought* to be the
+ 	 only thing that should have an ATOMIC_EXPR(), so it may be as
+ 	 simple as checking the LHS is an ATOMIC_EXPR node rather than 
+ 	 the current check of ATOMIC_TYPE (lhs).
+ 
+ 	 This also means the TYPE_ATOMIC flag in expressions should ONLY 
+ 	 occur on the operand of an ATOMIC_EXPR() nodes... anywhere else 
+ 	 would be an error.  */
+       if (TREE_CODE (lhs.value) != ERROR_MARK 
+ 	  && TYPE_ATOMIC (TREE_TYPE (lhs.value)))
+ 	lhs.value = build_atomic_load (op_location, lhs.value);
        return lhs;
      }
    c_parser_consume_token (parser);
Index: gcc/c/c-typeck.c
===================================================================
*** gcc/c/c-typeck.c	(revision 201248)
--- gcc/c/c-typeck.c	(working copy)
*************** static void readonly_warning (tree, enum
*** 103,108 ****
--- 103,110 ----
  static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
  static void record_maybe_used_decl (tree);
  static int comptypes_internal (const_tree, const_tree, bool *, bool *);
+ static tree build_atomic_assign (location_t, tree, enum tree_code, tree);
+ 
  \f
  /* Return true if EXP is a null pointer constant, false otherwise.  */
  
*************** build_modify_expr (location_t location,
*** 4830,4835 ****
--- 4832,4838 ----
    tree lhstype = TREE_TYPE (lhs);
    tree olhstype = lhstype;
    bool npc;
+   bool is_atomic_op;
  
    /* Types that aren't fully specified cannot be used in assignments.  */
    lhs = require_complete_type (lhs);
*************** build_modify_expr (location_t location,
*** 4842,4847 ****
--- 4845,4852 ----
    if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign))
      return error_mark_node;
  
+   is_atomic_op = TYPE_ATOMIC (TREE_TYPE (lhs));
+ 
    if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
      {
        rhs_semantic_type = TREE_TYPE (rhs);
*************** build_modify_expr (location_t location,
*** 4872,4883 ****
      {
        lhs = c_fully_fold (lhs, false, NULL);
        lhs = stabilize_reference (lhs);
-       newrhs = build_binary_op (location,
- 				modifycode, lhs, rhs, 1);
  
!       /* The original type of the right hand side is no longer
! 	 meaningful.  */
!       rhs_origtype = NULL_TREE;
      }
  
    if (c_dialect_objc ())
--- 4877,4893 ----
      {
        lhs = c_fully_fold (lhs, false, NULL);
        lhs = stabilize_reference (lhs);
  
!       /* Construct the RHS for any non-atomic compound assignemnt. */
!       if (!is_atomic_op)
!         {
! 	  newrhs = build_binary_op (location,
! 				    modifycode, lhs, rhs, 1);
! 
! 	  /* The original type of the right hand side is no longer
! 	     meaningful.  */
! 	  rhs_origtype = NULL_TREE;
! 	}
      }
  
    if (c_dialect_objc ())
*************** build_modify_expr (location_t location,
*** 4944,4949 ****
--- 4954,4968 ----
  		    "enum conversion in assignment is invalid in C++");
      }
  
+   /* If the lhs is atomic, remove that qualifier.  */
+   if (is_atomic_op)
+     {
+       lhstype = build_qualified_type (lhstype, 
+ 				      TYPE_QUALS(lhstype) & ~TYPE_QUAL_ATOMIC);
+       olhstype = build_qualified_type (olhstype, 
+ 				       TYPE_QUALS(lhstype) & ~TYPE_QUAL_ATOMIC);
+     }
+ 
    /* Convert new value to destination type.  Fold it first, then
       restore any excess precision information, for the sake of
       conversion warnings.  */
*************** build_modify_expr (location_t location,
*** 4970,4978 ****
  
    /* Scan operands.  */
  
!   result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
!   TREE_SIDE_EFFECTS (result) = 1;
!   protected_set_expr_location (result, location);
  
    /* If we got the LHS in a different type for storing in,
       convert the result back to the nominal type of LHS
--- 4989,5002 ----
  
    /* Scan operands.  */
  
!   if (is_atomic_op)
!     result = build_atomic_assign (location, lhs, modifycode, newrhs);
!   else
!     {
!       result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
!       TREE_SIDE_EFFECTS (result) = 1;
!       protected_set_expr_location (result, location);
!     }
  
    /* If we got the LHS in a different type for storing in,
       convert the result back to the nominal type of LHS
*************** c_build_va_arg (location_t loc, tree exp
*** 10972,10974 ****
--- 10996,11207 ----
  		"C++ requires promoted type, not enum type, in %<va_arg%>");
    return build_va_arg (loc, expr, type);
  }
+ 
+ 
+ /* Expand atomic compound assignments into an approriate sequence as
+    specified by the C11 standard section 6.5.16.2.   
+     given 
+        _Atomic T1 E1
+        T2 E2
+        E1 op= E2
+ 
+  This sequence is used for integer, floating point and complex types. 
+ 
+  In addition the 'fe' prefixed routines may need to be invoked for 
+  floating point and complex when annex F is in effect (regarding floating
+  point or exceptional conditions)  See 6.5.16.2 footnote 113:
+ 
+  TODO these are not implemented as yes, but the comments are placed at the
+  correct locations in the code for the appropriate calls to be made.  They
+  should only be issued if the expression type is !INTEGRAL_TYPE_P().
+ 
+   T1 newval;
+   T1 old;
+   T1 *addr
+   T2 val
+   fenv_t fenv
+ 
+   addr = &E1;
+   val = (E2);
+   __atomic_load (addr, &old, SEQ_CST);
+   feholdexcept (&fenv);				<<-- float & complex only
+ loop:
+     newval = old op val;
+     if (__atomic_compare_exchange_strong (addr, &old, &newval, SEQ_CST,
+ 					  SEQ_CST))
+       goto done;
+     feclearexcept (FE_ALL_EXCEPT);		<<-- float & complex only
+     goto loop:
+ done:
+   feupdateenv (&fenv);				<<-- float & complex only
+ 
+ 
+  Also note that the compiler is simply issuing the generic form of the atomic
+  operations. This requires temp(s) and has their address taken.  The atomic
+  processing is smart enough to figure out when the size of an object can
+  utilize a lock free versionm, and convert the built-in call to the appropriate
+  lockfree routine.  The optimizers will then dispose of any temps that are no
+  longer required, and lock free implementations are utilized for integer, float
+  and complex as long as there is target supoprt for the required size. 
+ 
+  If the operator is NOP_EXPR, then this is a simple assignment, and an
+  __atomic_store is issued to perform the assignment rather than the above loop.
+ 
+ */
+ 
+ /* Build an atomic assignment at LOC, expanding into the proper sequence to
+    store LHS MODIFYCODE= RHS.  Return a value representing the result of 
+    the operation.  */
+ tree
+ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
+ 		     tree rhs)
+ {
+   tree fndecl, func_call;
+   vec<tree, va_gc> *params;
+   tree val, nonatomic_type, newval, newval_addr;
+   tree old, old_addr;
+   tree stmt, goto_stmt;
+   tree loop_label, loop_decl, done_label, done_decl;
+ 
+   tree lhs_type = TREE_TYPE (lhs);
+   tree lhs_addr = build_unary_op (loc, ADDR_EXPR, lhs, 0);
+   tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+ 
+   gcc_assert (TYPE_ATOMIC (lhs_type));
+ 
+   /* allocate enough vector items for a compare_exchange.  */
+   vec_alloc (params, 6);
+ 
+   /* Remove the qualifiers for the rest of the expressions and create
+      the VAL temp variable to hold the RHS.  */
+   nonatomic_type = build_qualified_type (lhs_type, TYPE_UNQUALIFIED);
+   val = create_tmp_var (nonatomic_type, NULL);
+   TREE_ADDRESSABLE (val) = 1;
+   rhs = build2 (MODIFY_EXPR, nonatomic_type, val, rhs);
+   SET_EXPR_LOCATION (rhs, loc);
+   add_stmt (rhs);
+ 
+   /* NOP_EXPR indicates its a straight store of the RHS. Simply issue
+      and atomic_store.  */
+   if (modifycode == NOP_EXPR)
+     {
+       /* Build __atomic_store (&lhs, &val, SEQ_CST)  */
+       rhs = build_unary_op (loc, ADDR_EXPR, val, 0);
+       fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_STORE);
+       params->quick_push (lhs_addr);
+       params->quick_push (rhs);
+       params->quick_push (seq_cst);
+       func_call = build_function_call_vec (loc, fndecl, params, NULL);
+       add_stmt (func_call);
+ 
+       /* Val is the value which was stored, return it for any further value
+ 	 propagation.  */
+       return val;
+     }
+ 
+   /* Create the variables and labels required for the op= form.  */
+   old = create_tmp_var (nonatomic_type, NULL);
+   old_addr = build_unary_op (loc, ADDR_EXPR, old, 0);
+   TREE_ADDRESSABLE (val) = 1;
+ 
+   newval = create_tmp_var (nonatomic_type, NULL);
+   newval_addr = build_unary_op (loc, ADDR_EXPR, newval, 0);
+   TREE_ADDRESSABLE (newval) = 1;
+ 
+   loop_decl = create_artificial_label (loc);
+   loop_label = build1 (LABEL_EXPR, void_type_node, loop_decl);
+ 
+   done_decl = create_artificial_label (loc);
+   done_label = build1 (LABEL_EXPR, void_type_node, done_decl);
+ 
+   /* __atomic_load (addr, &old, SEQ_CST).  */
+   fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
+   params->quick_push (lhs_addr);
+   params->quick_push (old_addr);
+   params->quick_push (seq_cst);
+   func_call = build_function_call_vec (loc, fndecl, params, NULL);
+   add_stmt (func_call);
+   params->truncate (0);
+ 
+   /* TODO if (!integral)  issue feholdexcept (&fenv); */
+ 
+   /* loop:  */
+   add_stmt (loop_label);
+ 
+   /* newval = old + val;  */
+   rhs = build_binary_op (loc, modifycode, old, val, 1);
+   rhs = build2 (MODIFY_EXPR, nonatomic_type, newval, rhs);
+   SET_EXPR_LOCATION (rhs, loc);
+   add_stmt (rhs);
+ 
+   /* if (__atomic_compare_exchange (addr, &old, &new, false, SEQ_CST, SEQ_CST))
+        goto done;  */
+   fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_COMPARE_EXCHANGE);
+   params->quick_push (lhs_addr);
+   params->quick_push (old_addr);
+   params->quick_push (newval_addr);
+   params->quick_push (integer_zero_node);
+   params->quick_push (seq_cst);
+   params->quick_push (seq_cst);
+   func_call = build_function_call_vec (loc, fndecl, params, NULL);
+ 
+   goto_stmt = build1 (GOTO_EXPR, void_type_node, done_decl);
+   SET_EXPR_LOCATION (goto_stmt, loc);
+ 
+   stmt = build3 (COND_EXPR, void_type_node, func_call, goto_stmt, NULL_TREE);
+   SET_EXPR_LOCATION (stmt, loc);
+   add_stmt (stmt);
+   
+   /* TODO if (!integral) issue feclearexcept (FE_ALL_EXCEPT);  */
+ 
+   /* goto loop;  */
+   goto_stmt  = build1 (GOTO_EXPR, void_type_node, loop_decl);
+   SET_EXPR_LOCATION (goto_stmt, loc);
+   add_stmt (goto_stmt);
+  
+   /* done:  */
+   add_stmt (done_label);
+ 
+   /* TODO If (!integral) issue feupdateenv (&fenv)  */
+ 
+   /* Newval is the value that was successfully stored, return that.  */
+   return newval;
+ }
+ 
+ 
+ /* This simply performs an atomic load from EXPR and returns the temp it was
+    loaded into.  */
+ 
+ tree
+ build_atomic_load (location_t loc, tree expr)
+ {
+   vec<tree, va_gc> *params;
+   tree nonatomic_type, tmp, tmp_addr, fndecl, func_call;
+   tree expr_type = TREE_TYPE (expr);
+   tree expr_addr = build_unary_op (loc, ADDR_EXPR, expr, 0);
+   tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);
+ 
+   gcc_assert (TYPE_ATOMIC (expr_type));
+ 
+   /* Expansion of a generic atomoic load may require an addition element, so
+      allocate enough to prevent a resize.  */
+   vec_alloc (params, 4);
+ 
+   /* Remove the qualifiers for the rest of the expressions and create
+      the VAL temp variable to hold the RHS.  */
+   nonatomic_type = build_qualified_type (expr_type, TYPE_UNQUALIFIED);
+   tmp = create_tmp_var (nonatomic_type, NULL);
+   tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0);
+   TREE_ADDRESSABLE (tmp) = 1;
+ 
+   /* Issue __atomic_load (&expr, &tmp, SEQ_CST);  */
+   fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
+   params->quick_push (expr_addr);
+   params->quick_push (tmp_addr);
+   params->quick_push (seq_cst);
+   func_call = build_function_call_vec (loc, fndecl, params, NULL);
+   add_stmt (func_call);
+ 
+   /* return tmp which contains the value loaded,  */
+   return tmp;
+ }
Index: gcc/c-family/c-common.h
===================================================================
*** gcc/c-family/c-common.h	(revision 201248)
--- gcc/c-family/c-common.h	(working copy)
*************** extern int field_decl_cmp (const void *,
*** 547,552 ****
--- 547,554 ----
  extern void resort_sorted_fields (void *, void *, gt_pointer_operator,
  				  void *);
  extern bool has_c_linkage (const_tree decl);
+ extern tree build_atomic_load (location_t, tree);
+ 
  \f
  /* Switches common to the C front ends.  */
  

[-- Attachment #3: typeof.diff --]
[-- Type: text/x-patch, Size: 650 bytes --]


	* cp/parser.c (cp_parser_simple_type_specifier): Change TYPEOF for
	atomic types to return the non-atomic type.

Index: gcc/cp/parser.c
===================================================================
*** gcc/cp/parser.c	(revision 201248)
--- gcc/cp/parser.c	(working copy)
*************** cp_parser_simple_type_specifier (cp_pars
*** 14262,14267 ****
--- 14262,14269 ----
        /* If it is not already a TYPE, take its type.  */
        if (!TYPE_P (type))
  	type = finish_typeof (type);
+       if (TYPE_ATOMIC (type))
+         type = TYPE_MAIN_VARIANT (type);
  
        if (decl_specs)
  	cp_parser_set_decl_spec_type (decl_specs, type,

[-- Attachment #4: stdatomic.h --]
[-- Type: text/plain, Size: 6959 bytes --]



typedef enum memory_order
{
  memory_order_relaxed,
  memory_order_consume,
  memory_order_acquire,
  memory_order_release,
  memory_order_acq_rel,
  memory_order_seq_cst
} memory_order;


typedef _Atomic _Bool 	       atomic_bool;
typedef _Atomic char	       atomic_char
typedef _Atomic schar	       atomic_schar
typedef _Atomic uchar	       atomic_uchar
typedef _Atomic short	       atomic_short
typedef _Atomic ushort	       atomic_ushort
typedef _Atomic int            atomic_int
typedef _Atomic uint           atomic_uint
typedef _Atomic long           atomic_long
typedef _Atomic ulong          atomic_ulong
typedef _Atomic llong          atomic_llong
typedef _Atomic ullong         atomic_ullong
typedef _Atomic char16_t       atomic_char16_t
typedef _Atomic char32_t       atomic_char32_t
typedef _Atomic wchar_t        atomic_wchar_t
typedef _Atomic int_least8_t   atomic_int_least8_t
typedef _Atomic uint_least8_t  atomic_uint_least8_t
typedef _Atomic int_least16_t  atomic_int_least16_t
typedef _Atomic uint_least16_t atomic_uint_least16_t
typedef _Atomic int_least32_t  atomic_int_least32_t
typedef _Atomic uint_least32_t atomic_uint_least32_t
typedef _Atomic int_least64_t  atomic_int_least64_t
typedef _Atomic uint_least64_t atomic_uint_least64_t
typedef _Atomic int_fast8_t    atomic_int_fast8_t
typedef _Atomic uint_fast8_t   atomic_uint_fast8_t
typedef _Atomic int_fast16_t   atomic_int_fast16_t
typedef _Atomic uint_fast16_t  atomic_uint_fast16_t
typedef _Atomic int_fast32_t   atomic_int_fast32_t
typedef _Atomic uint_fast32_t  atomic_uint_fast32_t
typedef _Atomic int_fast64_t   atomic_int_fast64_t
typedef _Atomic uint_fast64_t  atomic_uint_fast64_t
typedef _Atomic intptr_t       atomic_intptr_t
typedef _Atomic uintptr_t      atomic_uintptr_t
typedef _Atomic size_t         atomic_size_t
typedef _Atomic ptrdiff_t      atomic_ptrdiff_t
typedef _Atomic intmax_t       atomic_intmax_t
typedef _Atomic uintmax_t      atomic_uintmax_t        


#define ATOMIC_VAR_INIT(VALUE)	(VALUE)
#define atomic_init(PTR, VAL)	{ *(PTR) = (VAL); }

/* TODO actually kill the dependancy.  */
#define kill_dependency(Y)	(Y)

#define atomic_thread_fence 	__atomic_thread_fence
#define atomic_signal_fence 	__atomic_signal_fence 
#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), NULL)

#define ATOMIC_BOOL_LOCK_FREE			\
			__atomic_is_lock_free (sizeof (atomic_bool), NULL)
#define ATOMIC_CHAR_LOCK_FREE			\
			__atomic_is_lock_free (sizeof (atomic_char), NULL)
#define ATOMIC_CHAR16_T_LOCK_FREE		\
			__atomic_is_lock_free (sizeof (atomic_char16_t), NULL)
#define ATOMIC_CHAR32_T_LOCK_FREE		\
			__atomic_is_lock_free (sizeof (atomic_char32_t), NULL)
#define ATOMIC_WCHAR_T_LOCK_FREE		\
			__atomic_is_lock_free (sizeof (atomic_wchar_t), NULL)
#define ATOMIC_SHORT_LOCK_FREE 			\
			__atomic_is_lock_free (sizeof (atomic_short), NULL)
#define ATOMIC_INT_LOCK_FREE 			\
			__atomic_is_lock_free (sizeof (atomic_int), NULL)
#define ATOMIC_LONG_LOCK_FREE			\
			__atomic_is_lock_free (sizeof (atomic_long), NULL)
#define ATOMIC_LLONG_LOCK_FREE			\
			__atomic_is_lock_free (sizeof (atomic_llong), NULL)
#define ATOMIC_POINTER_LOCK_FREE		\
			__atomic_is_lock_free (sizeof (_Atomic void *), NULL)


/* TODO: Note this required the __typeof__ definition to drops the atomic
   qualifier, which means __typeof__ (atomic type) return the underlying 
   non-atomic type.
   I think this makes sense, as most meaningful uses of __typeof__ of an atomic
   object would want the non-atomic version to be useful, as it is above.

   If we dont want to change that meaning, we'll need to implement a __typeof__
   variant which does this. 
   
   Also note that the header file uses the generic form of __atomic builtins,
   which requires the address to be taken of the value parameter, and then
   we pass that value on.   This allows the macros to work for any type,
   and the compiler is smart enough to convert these to lock-free _N 
   variants if possible, and throw away the temps.  */

#define atomic_store_explicit(PTR, VAL, MO) ({		\
  __typeof__ (*(PTR)) __tmp  = (VAL); 			\
  __atomic_store ((PTR), &__tmp, (MO)); })

#define atomic_store(PTR, VAL)				\
  atomic_store_explicit (PTR, VAL, __ATOMIC_SEQ_CST)


#define atomic_load_explicit(PTR, MO) ({		\
  __typeof__ (*(PTR)) __tmp; 				\
  __atomic)load ((PTR), &__tmp, __ATOMIC_SEQ_CST);	\
  __tmp; })

#define atomic_load(PTR)  atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)


#define atomic_exchange_explicit(PTR, VAL, MO) ({	\
  __typeof__ (*(PTR)) __tmp  = (VAL); 			\
  __atomic_exchange_n ((PTR), (VAL), (MO)); 		\
  __tmp; })

#define atomic_exchange(PTR, VAL) 			\
  atomic_exchange_explicit(PTR, VAL, __ATOMIC_SEQ_CST)


#define atomic_compare_exchange_strong_explicit(PTR, VAL, DES, SUC, FAIL) ({ \
  __typeof__ (*(PTR)) __tmp  = (DES); 			\
  __atomic_compare_exchange_n ((PTR), (VAL), &__tmp, 0, (SUC), (FAIL)); })

#define atomic_compare_exchange_strong(PTR, VAL, DES) 			   \
  atomic_compare_exchange_strong_explicit(PTR, VAL, DES, __ATOMIC_SEQ_CST, \
				          __ATOMIC_SEQ_CST)

#define atomic_compare_exchange_weak_explicit(PTR, VAL, DES, SUC, FAIL) ({  \
  __typeof__ (*(PTR)) __tmp  = (DES); 			\
  __atomic_compare_exchange_n ((PTR), (VAL), &__tmp, 1, (SUC), (FAIL)); })

#define atomic_compare_exchange_weak(PTR, VAL, DES) 			 \
  atomic_compare_exchange_weak_explicit(PTR, VAL, DES, __ATOMIC_SEQ_CST, \
					__ATOMIC_SEQ_CST)



#define atomic_fetch_add(PTR, VAL) __atomic_fetch_add ((PTR), (VAL), 	\
						       __ATOMIC_SEQ_CST)
#define atomic_fetch_add_explicit(PTR, VAL, MO) 			\
			  __atomic_fetch_add ((PTR), (VAL), (MO))

#define atomic_fetch_sub(PTR, VAL) __atomic_fetch_sub ((PTR), (VAL), 	\
						       __ATOMIC_SEQ_CST)
#define atomic_fetch_sub_explicit(PTR, VAL, MO) 			\
			  __atomic_fetch_sub ((PTR), (VAL), (MO))

#define atomic_fetch_or(PTR, VAL) __atomic_fetch_or ((PTR), (VAL), 	\
						       __ATOMIC_SEQ_CST)
#define atomic_fetch_or_explicit(PTR, VAL, MO) 			\
			  __atomic_fetch_or ((PTR), (VAL), (MO))

#define atomic_fetch_xor(PTR, VAL) __atomic_fetch_xor ((PTR), (VAL), 	\
						       __ATOMIC_SEQ_CST)
#define atomic_fetch_xor_explicit(PTR, VAL, MO) 			\
			  __atomic_fetch_xor ((PTR), (VAL), (MO))

#define atomic_fetch_and(PTR, VAL) __atomic_fetch_and ((PTR), (VAL), 	\
						       __ATOMIC_SEQ_CST)
#define atomic_fetch_and_explicit(PTR, VAL, MO) 			\
			  __atomic_fetch_and ((PTR), (VAL), (MO))


#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
    typedef bool atomic_flag;
#else
    typedef unsigned char atomic_flag;
#endif

#define ATOMIC_FLAG_INIT	0


#define atomic_flag_test_and_set(PTR) 					\
			__atomic_flag_test_and_set ((PTR), __ATOMIC_SEQ_CST)
#define atomic_flag_test_and_set_explicit(PTR, MO)			\
			__atomic_flag_test_and_set ((PTR), (MO))

#define atomic_flag_clear(PTR)	__atomic_flag_clear ((PTR), __ATOMIC_SEQ_CST)
#define atomic_flag_clear_explicit(PTR, MO)   __atomic_flag_clear ((PTR), (MO))





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

* Re: [PATCH] - C11 expressions and stdatomic.h -   Just for current state
  2013-08-02 19:22   ` [PATCH] - C11 expressions and stdatomic.h - Just for current state Andrew MacLeod
@ 2013-08-07 23:06     ` Joseph S. Myers
  0 siblings, 0 replies; 31+ messages in thread
From: Joseph S. Myers @ 2013-08-07 23:06 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

On Fri, 2 Aug 2013, Andrew MacLeod wrote:

> The atomic expression patch works on many cases, but falls short with any kind
> of complexity on the RHS of an expression which needs to be mapped to an
> atomic_load.  Whilst parsing, we cant tell, and the rhs tends to become an
> expression before we really know. so In the comments I have my proposed
> solution which I will look at when I return in 2 weeks.
> Basically, rather than have the ATOMIC_TYPE attribute ripple all the way
> through an expression, as soon as we see an ATOMIC_TYPE, we wrap it in a new
> node ATOMIC_EXPR, which holds the atomic expression, and sets it own
> expression type to the non-atomic variant.  This means the only expressions
> which will have the TYPE_ATOMIC flag set will be ones which are wrapped in
> ATOMIC_EXPR, and those are the ones where we need to go and replace with an
> __atomic_load or whatever.

My understanding is that the issue here about loads applies exactly when 
an atomic lvalue is converted to an rvalue.

Thus, this should be handled not when the expression is parsed (it might 
after all be used as an operand of sizeof, unary &, increment, decrement 
or assignment operators, on the LHS of ".", or in some other GNU C cases 
such as __real__ and __imag__) but when the lvalue is converted to an 
rvalue.

Unfortunately there isn't a single well-defined place in the C front end 
at present that does such a conversion (and for non-atomics, it's not 
clear that e.g. inserting conversions to remove type qualifiers would be 
particularly useful).  There are calls to mark_exp_read in many relevant 
places, but that's not exactly the same (and, similarly, calls to 
default_function_array_conversion or 
default_function_array_read_conversion in some such places).  So I think 
you simply need to go through everywhere an expression appears in the 
syntax and make sure that if the context indicates lvalue-to-rvalue 
conversion happens, then a function that carries out such conversion (for 
the case of atomics) gets called.

Certainly it doesn't seem right to set the type of a containing expression 
to the non-atomic type immediately, given that lvalue conversion does not 
occur for operands of sizeof, and an atomic type may have a different type 
from the non-atomic variant.  So sizeof applied to an atomic lvalue needs 
to have the size of the atomic type.

A more ambiguous case is what happens with a cast to atomic type, or 
function returning atomic type, if the result is immediately passed to 
sizeof (and the atomic type has a different size from the non-atomic 
type).  This is related to DR#423; I'll raise it with WG14.

> Ive included an additional 2 line patch which should  change the meaning of
> __typeof__  (again untested, the joys of imminently leaving for 2 weeks  :-).
> Im not sure the normal practical uses of
> __typeof__ have much meaning for an atomic type, it seems far more useful to
> have __typeof__ for an atomic qualified type to return the non-atomic variant.

What typeof should do in general for qualified types is unclear 
(especially in the case of rvalues, where the movement in ISO C seems to 
be to say that rvalues can't have qualified types at all) - returning the 
non-atomic type seems reasonable to me.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH 3/5] Atomic type qualifier - front end changes
  2013-07-30 17:14   ` [PATCH 3/5] Atomic type qualifier - front end changes Andrew MacLeod
@ 2013-08-09  0:06     ` Joseph S. Myers
  0 siblings, 0 replies; 31+ messages in thread
From: Joseph S. Myers @ 2013-08-09  0:06 UTC (permalink / raw)
  To: Andrew MacLeod; +Cc: gcc-patches

Observations on this patch:

* build_qualified_type sets the qualifiers to exactly the set specified.  
Thus, it looks like your handle_atomic_attribute will remove existing 
qualifiers when adding "atomic".

* c-aux-info.c is meant to be generating actual valid C declarations, I 
think, meaning _Atomic rather than "atomic".

* The code you have checking for _Atomic with function declarators appears 
to be in the wrong place.  What you're testing is the combination of 
(_Atomic appears in declaration specifiers, as given by atomicp) and (some 
declarator in the nested sequence of declarators is a function 
declarator).  But there are valid cases for this - for example a function 
returning a pointer to atomic.  And there are invalid cases involving an 
atomic-qualified function type that you don't catch there - for example, 
if _Atomic is applied to a typedef for a function type rather than 
together with the declarator.

The relevant issue is whether the *function type* itself gets qualified.  
There are already pedwarns-if-pedantic for this, given that there's 
undefined behavior in ISO C for qualifiers on function types in general, 
but making this case a hard error seems reasonable enough.  To do that, 
you need to adjust the cases

        case cdk_pointer:
          {
            /* Merge any constancy or volatility into the target type
               for the pointer.  */

            if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
                && type_quals)
              pedwarn (loc, OPT_Wpedantic,
                       "ISO C forbids qualified function types");

and similar for typedefs, type names, parameters and actual function 
declarations, to give such errors.  And similarly, for all the various 
cases of things that can be declared, whenever qualifiers get applied in 
grokdeclarator you need to ensure an error is given if the type is an 
array type, since that is also a constraint violation in ISO C.

* The pedwarn for _Atomic outside C11 mode should I think only be a 
pedwarn-if-pedantic, so pass OPT_Wpedantic instead of 0.  And the text 
should match other such pedwarns (i.e. "ISO C90 does not support _Atomic" 
or "ISO C99 does not support _Atomic", depending on the standard version 
selected).

* The parser comments with syntax should refer to _Atomic not "atomic".

* You change convert_for_assignment regarding discarding qualifiers.  
Doing so is correct as far as it goes - not because of the reason in your 
comment, but because in C11 terms _Atomic isn't a type qualifier.  But I 
don't think the change is enough.  Because it's inside a conditional 
checking for allowed cases: either side being a pointer to a void type, or 
the target types being compatible.  Now the rule in 6.5.16.1#1 refers to 
"qualified or unqualified version of void", which in ISO C terms does not 
include _Atomic void, so those checks need to disallow _Atomic void.  And 
similarly, it's not enough for comp_target_types to match the unqualified 
types when it also needs to match whether _Atomic is specified (for that, 
comp_target_types should probably be changed - conditional expressions 
have the same issue).

The above relate specifically to what's in the patch.  The listed issues 
should of course have testcases added.  I still need to review it on the 
basis of reviews of C11 for references to qualifiers or _Atomic, to see 
what might be missing from the patch, and on the basis of reviews of the C 
front end for handling of qualifiers, to see what places might need to 
handle _Atomic specially; I'll do those reviews separately.  As previously 
noted, one thing missing is the _Atomic ( type-name ) syntax.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

end of thread, other threads:[~2013-08-09  0:06 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-07-26 17:18 [PATCH] Add atomic type qualifier Andrew MacLeod
2013-07-26 19:24 ` Andi Kleen
2013-07-26 19:34   ` Andrew MacLeod
2013-07-26 21:14     ` Andi Kleen
2013-07-26 22:29       ` Andrew MacLeod
2013-07-26 20:42 ` Hans-Peter Nilsson
2013-07-26 23:58 ` Joseph S. Myers
2013-07-27  1:15   ` Andrew MacLeod
2013-08-01 21:54   ` Andrew MacLeod
2013-07-28 21:15 ` Joseph S. Myers
2013-07-29 15:47   ` Andrew MacLeod
2013-07-29 16:12     ` Joseph S. Myers
2013-07-29 16:30       ` Andrew MacLeod
2013-07-29 16:48         ` Joseph S. Myers
2013-07-29 18:20           ` Andrew MacLeod
2013-07-29 23:24       ` Andrew MacLeod
2013-07-30 12:03         ` Joseph S. Myers
2013-07-30 12:38           ` Andrew MacLeod
2013-07-30 13:25             ` Joseph S. Myers
2013-07-30 13:58               ` Andrew MacLeod
2013-07-31 12:19                 ` Andrew MacLeod
2013-07-29 16:24     ` Andrew MacLeod
2013-07-30 16:56 ` [PATCH 0/5] Atomic " Andrew MacLeod
2013-07-30 17:13   ` [PATCH 2/5] Atomic type qualifier - Add atomic type to tree node Andrew MacLeod
2013-07-30 17:14   ` [PATCH 4/5] Atomic type qualifier - Change built-in function types Andrew MacLeod
2013-07-30 17:14   ` [PATCH 3/5] Atomic type qualifier - front end changes Andrew MacLeod
2013-08-09  0:06     ` Joseph S. Myers
2013-07-30 17:14   ` [PATCH 1/5] Atomic type qualifier - Add type alignment override hook Andrew MacLeod
2013-07-30 17:32   ` [PATCH 5/5] Atomic type qualifier - Use atomic objects Andrew MacLeod
2013-08-02 19:22   ` [PATCH] - C11 expressions and stdatomic.h - Just for current state Andrew MacLeod
2013-08-07 23:06     ` Joseph S. Myers

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).