public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64
@ 2015-06-26 12:06 Matthew Wahab
  2015-06-26 12:08 ` [PATCH 2/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,fetch-op builtins Matthew Wahab
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Matthew Wahab @ 2015-06-26 12:06 UTC (permalink / raw)
  To: gcc-patches

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

Hello,

The __sync builtins are implemented using barriers that are too weak for ARMv8
targets, this has been fixed on trunk for Aarch64. Since GCC-5.1 is also
generating the incorrect code, it should also be fixed.

The fix on trunk involved changes to the way that memory orders represent
barriers for __sync builtins and changes to the code generated by the
Aarch64 back-end. This patch backports the changes made to the handling of memory
orders.

The trunk patch submission is at
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg00557.html.
The commit is at https://gcc.gnu.org/viewcvs?rev=223096&root=gcc&view=rev

Testing:
- Checked aarch64-none-linux-gnu with check-gcc
- Bootstrapped x86_64-unknown-linux-gnu
- Built all targets (for c and c++) in config-list.mk with no new compiliation
   errors. (I needed to remove the --enable-werror-always flag to get round a
   printf format warning that I believe is unrelated to the change.)

Ok for the branch?
Matthew

2015-06-26  Matthew Wahab  <matthew.wahab@arm.com>

	Backport from trunk
         2015-05-12  Andrew MacLeod  <amacleod@redhat.com>

     	PR target/65697
     	* coretypes.h (MEMMODEL_SYNC, MEMMODEL_BASE_MASK): New macros.
     	(enum memmodel): Add SYNC_{ACQUIRE,RELEASE,SEQ_CST}.
     	* tree.h (memmodel_from_int, memmodel_base, is_mm_relaxed,
     	is_mm_consume,is_mm_acquire, is_mm_release, is_mm_acq_rel,
     	is_mm_seq_cst, is_mm_sync): New accessor functions.
     	* builtins.c (expand_builtin_sync_operation,
     	expand_builtin_compare_and_swap): Use MEMMODEL_SYNC_SEQ_CST.
     	(expand_builtin_sync_lock_release): Use MEMMODEL_SYNC_RELEASE.
     	(get_memmodel,  expand_builtin_atomic_compare_exchange,
     	expand_builtin_atomic_load, expand_builtin_atomic_store,
     	expand_builtin_atomic_clear): Use new accessor routines.
     	(expand_builtin_sync_synchronize): Use MEMMODEL_SYNC_SEQ_CST.
     	* optabs.c (expand_compare_and_swap_loop): Use MEMMODEL_SYNC_SEQ_CST.
     	(maybe_emit_sync_lock_test_and_set): Use new accessors and
     	MEMMODEL_SYNC_ACQUIRE.
     	(expand_sync_lock_test_and_set): Use MEMMODEL_SYNC_ACQUIRE.
     	(expand_mem_thread_fence, expand_mem_signal_fence, expand_atomic_load,
     	expand_atomic_store): Use new accessors.
     	* emit-rtl.c (need_atomic_barrier_p): Add additional enum cases.
     	* tsan.c (instrument_builtin_call): Update check for memory model beyond
     	final enum to use MEMMODEL_LAST.
     	* c-family/c-common.c: Use new accessor for memmodel_base.
     	* config/aarch64/aarch64.c (aarch64_expand_compare_and_swap): Use new
     	accessors.
     	* config/aarch64/atomics.md (atomic_load<mode>,atomic_store<mode>,
     	arch64_load_exclusive<mode>, aarch64_store_exclusive<mode>,
     	mem_thread_fence, *dmb): Likewise.
     	* config/alpha/alpha.c (alpha_split_compare_and_swap,
     	alpha_split_compare_and_swap_12): Likewise.
     	* config/arm/arm.c (arm_expand_compare_and_swap,
     	arm_split_compare_and_swap, arm_split_atomic_op): Likewise.
     	* config/arm/sync.md (atomic_load<mode>, atomic_store<mode>,
     	atomic_loaddi): Likewise.
     	* config/i386/i386.c (ix86_destroy_cost_data, ix86_memmodel_check):
     	Likewise.
     	* config/i386/sync.md (mem_thread_fence, atomic_store<mode>): Likewise.
     	* config/ia64/ia64.c (ia64_expand_atomic_op): Add new memmodel cases and
     	use new accessors.
     	* config/ia64/sync.md (mem_thread_fence, atomic_load<mode>,
     	atomic_store<mode>, atomic_compare_and_swap<mode>,
     	atomic_exchange<mode>): Use new accessors.
     	* config/mips/mips.c (mips_process_sync_loop): Likewise.
     	* config/pa/pa.md (atomic_loaddi, atomic_storedi): Likewise.
     	* config/rs6000/rs6000.c (rs6000_pre_atomic_barrier,
     	rs6000_post_atomic_barrier): Add new cases.
     	(rs6000_expand_atomic_compare_and_swap): Use new accessors.
     	* config/rs6000/sync.md (mem_thread_fence): Add new cases.
     	(atomic_load<mode>): Add new cases and use new accessors.
     	(store_quadpti): Add new cases.
     	* config/s390/s390.md (mem_thread_fence, atomic_store<mode>): Use new
     	accessors.
     	* config/sparc/sparc.c (sparc_emit_membar_for_model): Use new accessors.
     	* doc/extend.texi: Update docs to indicate 16 bits are used for memory
     	model, not 8.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Backport-2015-05-12-Andrew-MacLeod-amacleod-redhat.c.patch --]
[-- Type: text/x-patch;  name=0001-Backport-2015-05-12-Andrew-MacLeod-amacleod-redhat.c.patch, Size: 45212 bytes --]

From 4797f71dc0946cbb5a7541abd90932cef25fbfa1 Mon Sep 17 00:00:00 2001
From: amacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Tue, 12 May 2015 20:01:47 +0000
Subject: [PATCH 1/4]         Backport 2015-05-12  Andrew MacLeod 
 <amacleod@redhat.com>

	PR target/65697
	* coretypes.h (MEMMODEL_SYNC, MEMMODEL_BASE_MASK): New macros.
	(enum memmodel): Add SYNC_{ACQUIRE,RELEASE,SEQ_CST}.
	* tree.h (memmodel_from_int, memmodel_base, is_mm_relaxed,
	is_mm_consume,is_mm_acquire, is_mm_release, is_mm_acq_rel,
	is_mm_seq_cst, is_mm_sync): New accessor functions.
	* builtins.c (expand_builtin_sync_operation,
	expand_builtin_compare_and_swap): Use MEMMODEL_SYNC_SEQ_CST.
	(expand_builtin_sync_lock_release): Use MEMMODEL_SYNC_RELEASE.
	(get_memmodel,  expand_builtin_atomic_compare_exchange,
	expand_builtin_atomic_load, expand_builtin_atomic_store,
	expand_builtin_atomic_clear): Use new accessor routines.
	(expand_builtin_sync_synchronize): Use MEMMODEL_SYNC_SEQ_CST.
	* optabs.c (expand_compare_and_swap_loop): Use MEMMODEL_SYNC_SEQ_CST.
	(maybe_emit_sync_lock_test_and_set): Use new accessors and
	MEMMODEL_SYNC_ACQUIRE.
	(expand_sync_lock_test_and_set): Use MEMMODEL_SYNC_ACQUIRE.
	(expand_mem_thread_fence, expand_mem_signal_fence, expand_atomic_load,
	expand_atomic_store): Use new accessors.
	* emit-rtl.c (need_atomic_barrier_p): Add additional enum cases.
	* tsan.c (instrument_builtin_call): Update check for memory model beyond
	final enum to use MEMMODEL_LAST.
	* c-family/c-common.c: Use new accessor for memmodel_base.
	* config/aarch64/aarch64.c (aarch64_expand_compare_and_swap): Use new
	accessors.
	* config/aarch64/atomics.md (atomic_load<mode>,atomic_store<mode>,
	arch64_load_exclusive<mode>, aarch64_store_exclusive<mode>,
	mem_thread_fence, *dmb): Likewise.
	* config/alpha/alpha.c (alpha_split_compare_and_swap,
	alpha_split_compare_and_swap_12): Likewise.
	* config/arm/arm.c (arm_expand_compare_and_swap,
	arm_split_compare_and_swap, arm_split_atomic_op): Likewise.
	* config/arm/sync.md (atomic_load<mode>, atomic_store<mode>,
	atomic_loaddi): Likewise.
	* config/i386/i386.c (ix86_destroy_cost_data, ix86_memmodel_check):
	Likewise.
	* config/i386/sync.md (mem_thread_fence, atomic_store<mode>): Likewise.
	* config/ia64/ia64.c (ia64_expand_atomic_op): Add new memmodel cases and
	use new accessors.
	* config/ia64/sync.md (mem_thread_fence, atomic_load<mode>,
	atomic_store<mode>, atomic_compare_and_swap<mode>,
	atomic_exchange<mode>): Use new accessors.
	* config/mips/mips.c (mips_process_sync_loop): Likewise.
	* config/pa/pa.md (atomic_loaddi, atomic_storedi): Likewise.
	* config/rs6000/rs6000.c (rs6000_pre_atomic_barrier,
	rs6000_post_atomic_barrier): Add new cases.
	(rs6000_expand_atomic_compare_and_swap): Use new accessors.
	* config/rs6000/sync.md (mem_thread_fence): Add new cases.
	(atomic_load<mode>): Add new cases and use new accessors.
	(store_quadpti): Add new cases.
	* config/s390/s390.md (mem_thread_fence, atomic_store<mode>): Use new
	accessors.
	* config/sparc/sparc.c (sparc_emit_membar_for_model): Use new accessors.
	* doc/extend.texi: Update docs to indicate 16 bits are used for memory
	model, not 8.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223096 138bc75d-0d04-0410-961f-82ee72b054a4

Conflicts:
	gcc/ChangeLog

Change-Id: I7a995fbd128c6db920a89d5417d216f51769a875
---
 gcc/builtins.c                | 28 +++++++++----------
 gcc/c-family/c-common.c       |  2 +-
 gcc/config/aarch64/aarch64.c  |  4 +--
 gcc/config/aarch64/atomics.md | 38 ++++++++++----------------
 gcc/config/alpha/alpha.c      | 16 +++++------
 gcc/config/arm/arm.c          | 36 +++++++++++--------------
 gcc/config/arm/sync.md        | 16 +++++------
 gcc/config/i386/i386.c        |  8 +++---
 gcc/config/i386/sync.md       | 10 +++----
 gcc/config/ia64/ia64.c        |  9 +++++--
 gcc/config/ia64/sync.md       | 18 +++++++------
 gcc/config/mips/mips.c        |  2 +-
 gcc/config/pa/pa.md           |  8 +++---
 gcc/config/rs6000/rs6000.c    | 14 +++++++---
 gcc/config/rs6000/sync.md     | 15 ++++++++---
 gcc/config/s390/s390.md       |  6 ++---
 gcc/config/sparc/sparc.c      | 10 +++----
 gcc/coretypes.h               | 20 +++++++++++---
 gcc/doc/extend.texi           |  4 +--
 gcc/emit-rtl.c                |  3 +++
 gcc/optabs.c                  | 23 ++++++++--------
 gcc/tree.h                    | 63 +++++++++++++++++++++++++++++++++++++++++++
 gcc/tsan.c                    |  6 ++---
 23 files changed, 216 insertions(+), 143 deletions(-)

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 9263777..b1e2b84 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5271,7 +5271,7 @@ expand_builtin_sync_operation (machine_mode mode, tree exp,
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   val = expand_expr_force_mode (CALL_EXPR_ARG (exp, 1), mode);
 
-  return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SEQ_CST,
+  return expand_atomic_fetch_op (target, mem, val, code, MEMMODEL_SYNC_SEQ_CST,
 				 after);
 }
 
@@ -5301,8 +5301,8 @@ expand_builtin_compare_and_swap (machine_mode mode, tree exp,
 	poval = &target;
     }
   if (!expand_atomic_compare_and_swap (pbool, poval, mem, old_val, new_val,
-				       false, MEMMODEL_SEQ_CST,
-				       MEMMODEL_SEQ_CST))
+				       false, MEMMODEL_SYNC_SEQ_CST,
+				       MEMMODEL_SYNC_SEQ_CST))
     return NULL_RTX;
 
   return target;
@@ -5337,7 +5337,7 @@ expand_builtin_sync_lock_release (machine_mode mode, tree exp)
   /* Expand the operands.  */
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
 
-  expand_atomic_store (mem, const0_rtx, MEMMODEL_RELEASE, true);
+  expand_atomic_store (mem, const0_rtx, MEMMODEL_SYNC_RELEASE, true);
 }
 
 /* Given an integer representing an ``enum memmodel'', verify its
@@ -5366,7 +5366,8 @@ get_memmodel (tree exp)
       return MEMMODEL_SEQ_CST;
     }
 
-  if ((INTVAL (op) & MEMMODEL_MASK) >= MEMMODEL_LAST)
+  /* Should never see a user explicit SYNC memodel model, so >= LAST works. */
+  if (memmodel_base (val) >= MEMMODEL_LAST)
     {
       warning (OPT_Winvalid_memory_model,
 	       "invalid memory model argument to builtin");
@@ -5433,8 +5434,7 @@ expand_builtin_atomic_compare_exchange (machine_mode mode, tree exp,
       success = MEMMODEL_SEQ_CST;
     }
  
-  if ((failure & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (failure & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_release (failure) || is_mm_acq_rel (failure))
     {
       warning (OPT_Winvalid_memory_model,
 	       "invalid failure memory model for "
@@ -5496,8 +5496,7 @@ expand_builtin_atomic_load (machine_mode mode, tree exp, rtx target)
   enum memmodel model;
 
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
-  if ((model & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_release (model) || is_mm_acq_rel (model))
     {
       warning (OPT_Winvalid_memory_model,
 	       "invalid memory model for %<__atomic_load%>");
@@ -5526,9 +5525,8 @@ expand_builtin_atomic_store (machine_mode mode, tree exp)
   enum memmodel model;
 
   model = get_memmodel (CALL_EXPR_ARG (exp, 2));
-  if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED
-      && (model & MEMMODEL_MASK) != MEMMODEL_SEQ_CST
-      && (model & MEMMODEL_MASK) != MEMMODEL_RELEASE)
+  if (!(is_mm_relaxed (model) || is_mm_seq_cst (model)
+	|| is_mm_release (model)))
     {
       warning (OPT_Winvalid_memory_model,
 	       "invalid memory model for %<__atomic_store%>");
@@ -5635,9 +5633,7 @@ expand_builtin_atomic_clear (tree exp)
   mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode);
   model = get_memmodel (CALL_EXPR_ARG (exp, 1));
 
-  if ((model & MEMMODEL_MASK) == MEMMODEL_CONSUME
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQUIRE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_consume (model) || is_mm_acquire (model) || is_mm_acq_rel (model))
     {
       warning (OPT_Winvalid_memory_model,
 	       "invalid memory model for %<__atomic_store%>");
@@ -5833,7 +5829,7 @@ expand_builtin_atomic_signal_fence (tree exp)
 static void
 expand_builtin_sync_synchronize (void)
 {
-  expand_mem_thread_fence (MEMMODEL_SEQ_CST);
+  expand_mem_thread_fence (MEMMODEL_SYNC_SEQ_CST);
 }
 
 static rtx
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 7fe7fa6..117f89c 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -10741,7 +10741,7 @@ get_atomic_generic_size (location_t loc, tree function,
       if (TREE_CODE (p) == INTEGER_CST)
         {
 	  int i = tree_to_uhwi (p);
-	  if (i < 0 || (i & MEMMODEL_MASK) >= MEMMODEL_LAST)
+	  if (i < 0 || (memmodel_base (i) >= MEMMODEL_LAST))
 	    {
 	      warning_at (loc, OPT_Winvalid_memory_model,
 			  "invalid memory model argument %d of %qE", x + 1,
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 6f86ede..b8b37b8 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -9020,8 +9020,8 @@ aarch64_expand_compare_and_swap (rtx operands[])
      unlikely event of fail being ACQUIRE and succ being RELEASE we need to
      promote succ to ACQ_REL so that we don't lose the acquire semantics.  */
 
-  if (INTVAL (mod_f) == MEMMODEL_ACQUIRE
-      && INTVAL (mod_s) == MEMMODEL_RELEASE)
+  if (is_mm_acquire (memmodel_from_int (INTVAL (mod_f)))
+      && is_mm_release (memmodel_from_int (INTVAL (mod_s))))
     mod_s = GEN_INT (MEMMODEL_ACQ_REL);
 
   switch (mode)
diff --git a/gcc/config/aarch64/atomics.md b/gcc/config/aarch64/atomics.md
index 939a11e..1a38ac0 100644
--- a/gcc/config/aarch64/atomics.md
+++ b/gcc/config/aarch64/atomics.md
@@ -260,10 +260,8 @@
       UNSPECV_LDA))]
   ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    if (model == MEMMODEL_RELAXED
-	|| model == MEMMODEL_CONSUME
-	|| model == MEMMODEL_RELEASE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+    if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_release (model))
       return "ldr<atomic_sfx>\t%<w>0, %1";
     else
       return "ldar<atomic_sfx>\t%<w>0, %1";
@@ -278,10 +276,8 @@
       UNSPECV_STL))]
   ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    if (model == MEMMODEL_RELAXED
-	|| model == MEMMODEL_CONSUME
-	|| model == MEMMODEL_ACQUIRE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+    if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_acquire (model))
       return "str<atomic_sfx>\t%<w>1, %0";
     else
       return "stlr<atomic_sfx>\t%<w>1, %0";
@@ -297,10 +293,8 @@
 	UNSPECV_LX)))]
   ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    if (model == MEMMODEL_RELAXED
-	|| model == MEMMODEL_CONSUME
-	|| model == MEMMODEL_RELEASE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+    if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_release (model))
       return "ldxr<atomic_sfx>\t%w0, %1";
     else
       return "ldaxr<atomic_sfx>\t%w0, %1";
@@ -315,10 +309,8 @@
       UNSPECV_LX))]
   ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    if (model == MEMMODEL_RELAXED
-	|| model == MEMMODEL_CONSUME
-	|| model == MEMMODEL_RELEASE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+    if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_release (model))
       return "ldxr\t%<w>0, %1";
     else
       return "ldaxr\t%<w>0, %1";
@@ -335,10 +327,8 @@
       UNSPECV_SX))]
   ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[3]);
-    if (model == MEMMODEL_RELAXED
-	|| model == MEMMODEL_CONSUME
-	|| model == MEMMODEL_ACQUIRE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[3]));
+    if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_acquire (model))
       return "stxr<atomic_sfx>\t%w0, %<w>2, %1";
     else
       return "stlxr<atomic_sfx>\t%w0, %<w>2, %1";
@@ -349,8 +339,8 @@
   [(match_operand:SI 0 "const_int_operand" "")]
   ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[0]);
-    if (model != MEMMODEL_RELAXED && model != MEMMODEL_CONSUME)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
+    if (!(is_mm_relaxed (model) || is_mm_consume (model)))
       emit_insn (gen_dmb (operands[0]));
     DONE;
   }
@@ -373,8 +363,8 @@
      UNSPEC_MB))]
   ""
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[1]);
-    if (model == MEMMODEL_ACQUIRE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[1]));
+    if (is_mm_acquire (model))
       return "dmb\\tishld";
     else
       return "dmb\\tish";
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 864a8fc..731a966 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -4548,8 +4548,8 @@ alpha_split_compare_and_swap (rtx operands[])
   oldval = operands[3];
   newval = operands[4];
   is_weak = (operands[5] != const0_rtx);
-  mod_s = (enum memmodel) INTVAL (operands[6]);
-  mod_f = (enum memmodel) INTVAL (operands[7]);
+  mod_s = memmodel_from_int (INTVAL (operands[6]));
+  mod_f = memmodel_from_int (INTVAL (operands[7]));
   mode = GET_MODE (mem);
 
   alpha_pre_atomic_barrier (mod_s);
@@ -4587,12 +4587,12 @@ alpha_split_compare_and_swap (rtx operands[])
       emit_unlikely_jump (x, label1);
     }
 
-  if (mod_f != MEMMODEL_RELAXED)
+  if (!is_mm_relaxed (mod_f))
     emit_label (XEXP (label2, 0));
 
   alpha_post_atomic_barrier (mod_s);
 
-  if (mod_f == MEMMODEL_RELAXED)
+  if (is_mm_relaxed (mod_f))
     emit_label (XEXP (label2, 0));
 }
 
@@ -4653,8 +4653,8 @@ alpha_split_compare_and_swap_12 (rtx operands[])
   newval = operands[4];
   align = operands[5];
   is_weak = (operands[6] != const0_rtx);
-  mod_s = (enum memmodel) INTVAL (operands[7]);
-  mod_f = (enum memmodel) INTVAL (operands[8]);
+  mod_s = memmodel_from_int (INTVAL (operands[7]));
+  mod_f = memmodel_from_int (INTVAL (operands[8]));
   scratch = operands[9];
   mode = GET_MODE (orig_mem);
   addr = XEXP (orig_mem, 0);
@@ -4706,12 +4706,12 @@ alpha_split_compare_and_swap_12 (rtx operands[])
       emit_unlikely_jump (x, label1);
     }
 
-  if (mod_f != MEMMODEL_RELAXED)
+  if (!is_mm_relaxed (mod_f))
     emit_label (XEXP (label2, 0));
 
   alpha_post_atomic_barrier (mod_s);
 
-  if (mod_f == MEMMODEL_RELAXED)
+  if (is_mm_relaxed (mod_f))
     emit_label (XEXP (label2, 0));
 }
 
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 292fed9..7b279c7 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -27663,8 +27663,8 @@ arm_expand_compare_and_swap (rtx operands[])
      promote succ to ACQ_REL so that we don't lose the acquire semantics.  */
 
   if (TARGET_HAVE_LDACQ
-      && INTVAL (mod_f) == MEMMODEL_ACQUIRE
-      && INTVAL (mod_s) == MEMMODEL_RELEASE)
+      && is_mm_acquire (memmodel_from_int (INTVAL (mod_f)))
+      && is_mm_release (memmodel_from_int (INTVAL (mod_s))))
     mod_s = GEN_INT (MEMMODEL_ACQ_REL);
 
   switch (mode)
@@ -27737,20 +27737,18 @@ arm_split_compare_and_swap (rtx operands[])
   oldval = operands[2];
   newval = operands[3];
   is_weak = (operands[4] != const0_rtx);
-  mod_s = (enum memmodel) INTVAL (operands[5]);
-  mod_f = (enum memmodel) INTVAL (operands[6]);
+  mod_s = memmodel_from_int (INTVAL (operands[5]));
+  mod_f = memmodel_from_int (INTVAL (operands[6]));
   scratch = operands[7];
   mode = GET_MODE (mem);
 
   bool use_acquire = TARGET_HAVE_LDACQ
-                     && !(mod_s == MEMMODEL_RELAXED
-                          || mod_s == MEMMODEL_CONSUME
-                          || mod_s == MEMMODEL_RELEASE);
-
+                     && !(is_mm_relaxed (mod_s) || is_mm_consume (mod_s)
+			  || is_mm_release (mod_s));
+		
   bool use_release = TARGET_HAVE_LDACQ
-                     && !(mod_s == MEMMODEL_RELAXED
-                          || mod_s == MEMMODEL_CONSUME
-                          || mod_s == MEMMODEL_ACQUIRE);
+                     && !(is_mm_relaxed (mod_s) || is_mm_consume (mod_s)
+			  || is_mm_acquire (mod_s));
 
   /* Checks whether a barrier is needed and emits one accordingly.  */
   if (!(use_acquire || use_release))
@@ -27788,14 +27786,14 @@ arm_split_compare_and_swap (rtx operands[])
       emit_unlikely_jump (gen_rtx_SET (VOIDmode, pc_rtx, x));
     }
 
-  if (mod_f != MEMMODEL_RELAXED)
+  if (!is_mm_relaxed (mod_f))
     emit_label (label2);
 
   /* Checks whether a barrier is needed and emits one accordingly.  */
   if (!(use_acquire || use_release))
     arm_post_atomic_barrier (mod_s);
 
-  if (mod_f == MEMMODEL_RELAXED)
+  if (is_mm_relaxed (mod_f))
     emit_label (label2);
 }
 
@@ -27803,21 +27801,19 @@ void
 arm_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
 		     rtx value, rtx model_rtx, rtx cond)
 {
-  enum memmodel model = (enum memmodel) INTVAL (model_rtx);
+  enum memmodel model = memmodel_from_int (INTVAL (model_rtx));
   machine_mode mode = GET_MODE (mem);
   machine_mode wmode = (mode == DImode ? DImode : SImode);
   rtx_code_label *label;
   rtx x;
 
   bool use_acquire = TARGET_HAVE_LDACQ
-                     && !(model == MEMMODEL_RELAXED
-                          || model == MEMMODEL_CONSUME
-                          || model == MEMMODEL_RELEASE);
+                     && !(is_mm_relaxed (model) || is_mm_consume (model)
+			  || is_mm_release (model));
 
   bool use_release = TARGET_HAVE_LDACQ
-                     && !(model == MEMMODEL_RELAXED
-                          || model == MEMMODEL_CONSUME
-                          || model == MEMMODEL_ACQUIRE);
+                     && !(is_mm_relaxed (model) || is_mm_consume (model)
+			  || is_mm_acquire (model));
 
   /* Checks whether a barrier is needed and emits one accordingly.  */
   if (!(use_acquire || use_release))
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index 78bdafc..44cda61 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -73,10 +73,8 @@
       VUNSPEC_LDA))]
   "TARGET_HAVE_LDACQ"
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    if (model == MEMMODEL_RELAXED
-        || model == MEMMODEL_CONSUME
-        || model == MEMMODEL_RELEASE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+    if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_release (model))
       return \"ldr<sync_sfx>\\t%0, %1\";
     else
       return \"lda<sync_sfx>\\t%0, %1\";
@@ -91,10 +89,8 @@
       VUNSPEC_STL))]
   "TARGET_HAVE_LDACQ"
   {
-    enum memmodel model = (enum memmodel) INTVAL (operands[2]);
-    if (model == MEMMODEL_RELAXED
-        || model == MEMMODEL_CONSUME
-        || model == MEMMODEL_ACQUIRE)
+    enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
+    if (is_mm_relaxed (model) || is_mm_consume (model) || is_mm_acquire (model))
       return \"str<sync_sfx>\t%1, %0\";
     else
       return \"stl<sync_sfx>\t%1, %0\";
@@ -110,10 +106,10 @@
    (match_operand:SI 2 "const_int_operand")]		;; model
   "TARGET_HAVE_LDREXD && ARM_DOUBLEWORD_ALIGN"
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
   expand_mem_thread_fence (model);
   emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1]));
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     expand_mem_thread_fence (model);
   DONE;
 })
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 7c28a55..6851890 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -51516,7 +51516,7 @@ ix86_destroy_cost_data (void *data)
 static unsigned HOST_WIDE_INT
 ix86_memmodel_check (unsigned HOST_WIDE_INT val)
 {
-  unsigned HOST_WIDE_INT model = val & MEMMODEL_MASK;
+  enum memmodel model = memmodel_from_int (val);
   bool strong;
 
   if (val & ~(unsigned HOST_WIDE_INT)(IX86_HLE_ACQUIRE|IX86_HLE_RELEASE
@@ -51527,14 +51527,14 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
 	       "Unknown architecture specific memory model");
       return MEMMODEL_SEQ_CST;
     }
-  strong = (model == MEMMODEL_ACQ_REL || model == MEMMODEL_SEQ_CST);
-  if (val & IX86_HLE_ACQUIRE && !(model == MEMMODEL_ACQUIRE || strong))
+  strong = (is_mm_acq_rel (model) || is_mm_seq_cst (model));
+  if (val & IX86_HLE_ACQUIRE && !(is_mm_acquire (model) || strong))
     {
       warning (OPT_Winvalid_memory_model,
               "HLE_ACQUIRE not used with ACQUIRE or stronger memory model");
       return MEMMODEL_SEQ_CST | IX86_HLE_ACQUIRE;
     }
-   if (val & IX86_HLE_RELEASE && !(model == MEMMODEL_RELEASE || strong))
+  if (val & IX86_HLE_RELEASE && !(is_mm_release (model) || strong))
     {
       warning (OPT_Winvalid_memory_model,
               "HLE_RELEASE not used with RELEASE or stronger memory model");
diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md
index 61a2a81..59573d4 100644
--- a/gcc/config/i386/sync.md
+++ b/gcc/config/i386/sync.md
@@ -105,11 +105,11 @@
   [(match_operand:SI 0 "const_int_operand")]		;; model
   ""
 {
-  enum memmodel model = (enum memmodel) (INTVAL (operands[0]) & MEMMODEL_MASK);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
 
   /* Unless this is a SEQ_CST fence, the i386 memory model is strong
      enough not to require barriers of any kind.  */
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     {
       rtx (*mfence_insn)(rtx);
       rtx mem;
@@ -217,7 +217,7 @@
 		       UNSPEC_STA))]
   ""
 {
-  enum memmodel model = (enum memmodel) (INTVAL (operands[2]) & MEMMODEL_MASK);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
 
   if (<MODE>mode == DImode && !TARGET_64BIT)
     {
@@ -233,7 +233,7 @@
       operands[1] = force_reg (<MODE>mode, operands[1]);
 
       /* For seq-cst stores, when we lack MFENCE, use XCHG.  */
-      if (model == MEMMODEL_SEQ_CST && !(TARGET_64BIT || TARGET_SSE2))
+      if (is_mm_seq_cst (model) && !(TARGET_64BIT || TARGET_SSE2))
 	{
 	  emit_insn (gen_atomic_exchange<mode> (gen_reg_rtx (<MODE>mode),
 						operands[0], operands[1],
@@ -246,7 +246,7 @@
 					   operands[2]));
     }
   /* ... followed by an MFENCE, if required.  */
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     emit_insn (gen_mem_thread_fence (operands[2]));
   DONE;
 })
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 5132d2f..21da9e2 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -2389,10 +2389,12 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
 	{
 	case MEMMODEL_ACQ_REL:
 	case MEMMODEL_SEQ_CST:
+	case MEMMODEL_SYNC_SEQ_CST:
 	  emit_insn (gen_memory_barrier ());
 	  /* FALLTHRU */
 	case MEMMODEL_RELAXED:
 	case MEMMODEL_ACQUIRE:
+	case MEMMODEL_SYNC_ACQUIRE:
 	case MEMMODEL_CONSUME:
 	  if (mode == SImode)
 	    icode = CODE_FOR_fetchadd_acq_si;
@@ -2400,6 +2402,7 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
 	    icode = CODE_FOR_fetchadd_acq_di;
 	  break;
 	case MEMMODEL_RELEASE:
+	case MEMMODEL_SYNC_RELEASE:
 	  if (mode == SImode)
 	    icode = CODE_FOR_fetchadd_rel_si;
 	  else
@@ -2426,8 +2429,7 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
      front half of the full barrier.  The end half is the cmpxchg.rel.
      For relaxed and release memory models, we don't need this.  But we
      also don't bother trying to prevent it either.  */
-  gcc_assert (model == MEMMODEL_RELAXED
-	      || model == MEMMODEL_RELEASE
+  gcc_assert (is_mm_relaxed (model) || is_mm_release (model)
 	      || MEM_VOLATILE_P (mem));
 
   old_reg = gen_reg_rtx (DImode);
@@ -2471,6 +2473,7 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
     {
     case MEMMODEL_RELAXED:
     case MEMMODEL_ACQUIRE:
+    case MEMMODEL_SYNC_ACQUIRE:
     case MEMMODEL_CONSUME:
       switch (mode)
 	{
@@ -2484,8 +2487,10 @@ ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
       break;
 
     case MEMMODEL_RELEASE:
+    case MEMMODEL_SYNC_RELEASE:
     case MEMMODEL_ACQ_REL:
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       switch (mode)
 	{
 	case QImode: icode = CODE_FOR_cmpxchg_rel_qi;  break;
diff --git a/gcc/config/ia64/sync.md b/gcc/config/ia64/sync.md
index 75d746d..9c178b8 100644
--- a/gcc/config/ia64/sync.md
+++ b/gcc/config/ia64/sync.md
@@ -33,7 +33,7 @@
   [(match_operand:SI 0 "const_int_operand" "")]		;; model
   ""
 {
-  if (INTVAL (operands[0]) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (memmodel_from_int (INTVAL (operands[0]))))
     emit_insn (gen_memory_barrier ());
   DONE;
 })
@@ -60,11 +60,11 @@
    (match_operand:SI 2 "const_int_operand" "")]			;; model
   ""
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
 
   /* Unless the memory model is relaxed, we want to emit ld.acq, which
      will happen automatically for volatile memories.  */
-  gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[1]));
+  gcc_assert (is_mm_relaxed (model) || MEM_VOLATILE_P (operands[1]));
   emit_move_insn (operands[0], operands[1]);
   DONE;
 })
@@ -75,17 +75,17 @@
    (match_operand:SI 2 "const_int_operand" "")]			;; model
   ""
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
 
   /* Unless the memory model is relaxed, we want to emit st.rel, which
      will happen automatically for volatile memories.  */
-  gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[0]));
+  gcc_assert (is_mm_relaxed (model) || MEM_VOLATILE_P (operands[0]));
   emit_move_insn (operands[0], operands[1]);
 
   /* Sequentially consistent stores need a subsequent MF.  See
      http://www.decadent.org.uk/pipermail/cpp-threads/2008-December/001952.html
      for a discussion of why a MF is needed here, but not for atomic_load.  */
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     emit_insn (gen_memory_barrier ());
   DONE;
 })
@@ -101,7 +101,8 @@
    (match_operand:SI 7 "const_int_operand" "")]			;; fail model
   ""
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[6]);
+  /* No need to distinquish __sync from __atomic, so get base value.  */
+  enum memmodel model = memmodel_base (INTVAL (operands[6]));
   rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
   rtx dval, eval;
 
@@ -200,7 +201,8 @@
    (match_operand:SI 3 "const_int_operand" "")]			;; succ model
   ""
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[3]);
+  /* No need to distinquish __sync from __atomic, so get base value.  */
+  enum memmodel model = memmodel_base (INTVAL (operands[3]));
 
   switch (model)
     {
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 1733457..67ec6b9 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -13111,7 +13111,7 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
       model = MEMMODEL_ACQUIRE;
       break;
     default:
-      model = (enum memmodel) INTVAL (operands[memmodel_attr]);
+      model = memmodel_from_int (INTVAL (operands[memmodel_attr]));
     }
 
   mips_multi_start ();
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 2fd2059..9e506ac 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -707,12 +707,12 @@
    (match_operand:SI 2 "const_int_operand")]            ;; model
   "!TARGET_64BIT && !TARGET_SOFT_FLOAT"
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
   operands[1] = force_reg (SImode, XEXP (operands[1], 0));
   operands[2] = gen_reg_rtx (DImode);
   expand_mem_thread_fence (model);
   emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1], operands[2]));
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     expand_mem_thread_fence (model);
   DONE;
 })
@@ -734,12 +734,12 @@
    (match_operand:SI 2 "const_int_operand")]            ;; model
   "!TARGET_64BIT && !TARGET_SOFT_FLOAT"
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
   operands[0] = force_reg (SImode, XEXP (operands[0], 0));
   operands[2] = gen_reg_rtx (DImode);
   expand_mem_thread_fence (model);
   emit_insn (gen_atomic_storedi_1 (operands[0], operands[1], operands[2]));
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     expand_mem_thread_fence (model);
   DONE;
 })
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 97c5842..725c6fd 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -20537,12 +20537,15 @@ rs6000_pre_atomic_barrier (rtx mem, enum memmodel model)
     case MEMMODEL_RELAXED:
     case MEMMODEL_CONSUME:
     case MEMMODEL_ACQUIRE:
+    case MEMMODEL_SYNC_ACQUIRE:
       break;
     case MEMMODEL_RELEASE:
+    case MEMMODEL_SYNC_RELEASE:
     case MEMMODEL_ACQ_REL:
       emit_insn (gen_lwsync ());
       break;
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       emit_insn (gen_hwsync ());
       break;
     default:
@@ -20559,10 +20562,13 @@ rs6000_post_atomic_barrier (enum memmodel model)
     case MEMMODEL_RELAXED:
     case MEMMODEL_CONSUME:
     case MEMMODEL_RELEASE:
+    case MEMMODEL_SYNC_RELEASE:
       break;
     case MEMMODEL_ACQUIRE:
+    case MEMMODEL_SYNC_ACQUIRE:
     case MEMMODEL_ACQ_REL:
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       emit_insn (gen_isync ());
       break;
     default:
@@ -20662,8 +20668,8 @@ rs6000_expand_atomic_compare_and_swap (rtx operands[])
   oldval = operands[3];
   newval = operands[4];
   is_weak = (INTVAL (operands[5]) != 0);
-  mod_s = (enum memmodel) INTVAL (operands[6]);
-  mod_f = (enum memmodel) INTVAL (operands[7]);
+  mod_s = memmodel_from_int (INTVAL (operands[6]));
+  mod_f = memmodel_from_int (INTVAL (operands[7]));
   orig_mode = mode = GET_MODE (mem);
 
   mask = shift = NULL_RTX;
@@ -20751,12 +20757,12 @@ rs6000_expand_atomic_compare_and_swap (rtx operands[])
       emit_unlikely_jump (x, label1);
     }
 
-  if (mod_f != MEMMODEL_RELAXED)
+  if (!is_mm_relaxed (mod_f))
     emit_label (XEXP (label2, 0));
 
   rs6000_post_atomic_barrier (mod_s);
 
-  if (mod_f == MEMMODEL_RELAXED)
+  if (is_mm_relaxed (mod_f))
     emit_label (XEXP (label2, 0));
 
   if (shift)
diff --git a/gcc/config/rs6000/sync.md b/gcc/config/rs6000/sync.md
index 4364c85..8ba30b9 100644
--- a/gcc/config/rs6000/sync.md
+++ b/gcc/config/rs6000/sync.md
@@ -41,18 +41,21 @@
   [(match_operand:SI 0 "const_int_operand" "")]		;; model
   ""
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[0]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
   switch (model)
     {
     case MEMMODEL_RELAXED:
       break;
     case MEMMODEL_CONSUME:
     case MEMMODEL_ACQUIRE:
+    case MEMMODEL_SYNC_ACQUIRE:
     case MEMMODEL_RELEASE:
+    case MEMMODEL_SYNC_RELEASE:
     case MEMMODEL_ACQ_REL:
       emit_insn (gen_lwsync ());
       break;
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       emit_insn (gen_hwsync ());
       break;
     default:
@@ -144,9 +147,9 @@
   if (<MODE>mode == TImode && !TARGET_SYNC_TI)
     FAIL;
 
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
 
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     emit_insn (gen_hwsync ());
 
   if (<MODE>mode != TImode)
@@ -182,7 +185,9 @@
       break;
     case MEMMODEL_CONSUME:
     case MEMMODEL_ACQUIRE:
+    case MEMMODEL_SYNC_ACQUIRE:
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       emit_insn (gen_loadsync_<mode> (operands[0]));
       break;
     default:
@@ -209,15 +214,17 @@
   if (<MODE>mode == TImode && !TARGET_SYNC_TI)
     FAIL;
 
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
   switch (model)
     {
     case MEMMODEL_RELAXED:
       break;
     case MEMMODEL_RELEASE:
+    case MEMMODEL_SYNC_RELEASE:
       emit_insn (gen_lwsync ());
       break;
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       emit_insn (gen_hwsync ());
       break;
     default:
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 76dca0a..8544f7d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -9226,7 +9226,7 @@
 {
   /* Unless this is a SEQ_CST fence, the s390 memory model is strong
      enough not to require barriers of any kind.  */
-  if (INTVAL (operands[0]) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (memmodel_from_int (INTVAL (operands[0]))))
     {
       rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
       MEM_VOLATILE_P (mem) = 1;
@@ -9307,7 +9307,7 @@
    (match_operand:SI 2 "const_int_operand")]	;; model
   ""
 {
-  enum memmodel model = (enum memmodel) INTVAL (operands[2]);
+  enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
 
   if (MEM_ALIGN (operands[0]) < GET_MODE_BITSIZE (GET_MODE (operands[0])))
     FAIL;
@@ -9318,7 +9318,7 @@
     emit_insn (gen_atomic_storedi_1 (operands[0], operands[1]));
   else
     emit_move_insn (operands[0], operands[1]);
-  if (model == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     emit_insn (gen_mem_thread_fence (operands[2]));
   DONE;
 })
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 1fd3c1e..f938236 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -11678,9 +11678,8 @@ sparc_emit_membar_for_model (enum memmodel model,
 
   if (before_after & 1)
     {
-      if (model == MEMMODEL_RELEASE
-	  || model == MEMMODEL_ACQ_REL
-	  || model == MEMMODEL_SEQ_CST)
+      if (is_mm_release (model) || is_mm_acq_rel (model)
+	  || is_mm_seq_cst (model))
 	{
 	  if (load_store & 1)
 	    mm |= LoadLoad | StoreLoad;
@@ -11690,9 +11689,8 @@ sparc_emit_membar_for_model (enum memmodel model,
     }
   if (before_after & 2)
     {
-      if (model == MEMMODEL_ACQUIRE
-	  || model == MEMMODEL_ACQ_REL
-	  || model == MEMMODEL_SEQ_CST)
+      if (is_mm_acquire (model) || is_mm_acq_rel (model)
+	  || is_mm_seq_cst (model))
 	{
 	  if (load_store & 1)
 	    mm |= LoadLoad | LoadStore;
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 90fa13f..0ee8633 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -263,6 +263,18 @@ enum function_class {
   function_c11_misc
 };
 
+/* Suppose that higher bits are target dependent. */
+#define MEMMODEL_MASK ((1<<16)-1)
+
+/* Legacy sync operations set this upper flag in the memory model.  This allows
+   targets that need to do something stronger for sync operations to
+   differentiate with their target patterns and issue a more appropriate insn
+   sequence.  See bugzilla 65697 for background.  */
+#define MEMMODEL_SYNC (1<<15)
+
+/* Memory model without SYNC bit for targets/operations that do not care.  */
+#define MEMMODEL_BASE_MASK (MEMMODEL_SYNC-1)
+
 /* Memory model types for the __atomic* builtins. 
    This must match the order in libstdc++-v3/include/bits/atomic_base.h.  */
 enum memmodel
@@ -273,12 +285,12 @@ enum memmodel
   MEMMODEL_RELEASE = 3,
   MEMMODEL_ACQ_REL = 4,
   MEMMODEL_SEQ_CST = 5,
-  MEMMODEL_LAST = 6
+  MEMMODEL_LAST = 6,
+  MEMMODEL_SYNC_ACQUIRE = MEMMODEL_ACQUIRE | MEMMODEL_SYNC,
+  MEMMODEL_SYNC_RELEASE = MEMMODEL_RELEASE | MEMMODEL_SYNC,
+  MEMMODEL_SYNC_SEQ_CST = MEMMODEL_SEQ_CST | MEMMODEL_SYNC
 };
 
-/* Suppose that higher bits are target dependent. */
-#define MEMMODEL_MASK ((1<<16)-1)
-
 /* Support for user-provided GGC and PCH markers.  The first parameter
    is a pointer to a pointer, the second a cookie.  */
 typedef void (*gt_pointer_operator) (void *, void *);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 79559c8..4f9176e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -8423,9 +8423,9 @@ functions map any run-time value to @code{__ATOMIC_SEQ_CST} rather
 than invoke a runtime library call or inline a switch statement.  This is
 standard compliant, safe, and the simplest approach for now.
 
-The memory model parameter is a signed int, but only the lower 8 bits are
+The memory model parameter is a signed int, but only the lower 16 bits are
 reserved for the memory model.  The remainder of the signed int is reserved
-for future use and should be 0.  Use of the predefined atomic values
+for target use and should be 0.  Use of the predefined atomic values
 ensures proper usage.
 
 @deftypefn {Built-in Function} @var{type} __atomic_load_n (@var{type} *ptr, int memmodel)
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 483eacb..00ba64e 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -6323,11 +6323,14 @@ need_atomic_barrier_p (enum memmodel model, bool pre)
     case MEMMODEL_CONSUME:
       return false;
     case MEMMODEL_RELEASE:
+    case MEMMODEL_SYNC_RELEASE:
       return pre;
     case MEMMODEL_ACQUIRE:
+    case MEMMODEL_SYNC_ACQUIRE:
       return !pre;
     case MEMMODEL_ACQ_REL:
     case MEMMODEL_SEQ_CST:
+    case MEMMODEL_SYNC_SEQ_CST:
       return true;
     default:
       gcc_unreachable ();
diff --git a/gcc/optabs.c b/gcc/optabs.c
index e9dc798..2d17521 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -7178,7 +7178,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq)
   success = NULL_RTX;
   oldval = cmp_reg;
   if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg,
-				       new_reg, false, MEMMODEL_SEQ_CST,
+				       new_reg, false, MEMMODEL_SYNC_SEQ_CST,
 				       MEMMODEL_RELAXED))
     return false;
 
@@ -7239,9 +7239,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val,
      exists, and the memory model is stronger than acquire, add a release 
      barrier before the instruction.  */
 
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST
-      || (model & MEMMODEL_MASK) == MEMMODEL_RELEASE
-      || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL)
+  if (is_mm_seq_cst (model) || is_mm_release (model) || is_mm_acq_rel (model))
     expand_mem_thread_fence (model);
 
   if (icode != CODE_FOR_nothing)
@@ -7348,11 +7346,12 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
   rtx ret;
 
   /* Try an atomic_exchange first.  */
-  ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE);
+  ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_SYNC_ACQUIRE);
   if (ret)
     return ret;
 
-  ret = maybe_emit_sync_lock_test_and_set (target, mem, val, MEMMODEL_ACQUIRE);
+  ret = maybe_emit_sync_lock_test_and_set (target, mem, val,
+					   MEMMODEL_SYNC_ACQUIRE);
   if (ret)
     return ret;
 
@@ -7363,7 +7362,7 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val)
   /* If there are no other options, try atomic_test_and_set if the value
      being stored is 1.  */
   if (val == const1_rtx)
-    ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE);
+    ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_SYNC_ACQUIRE);
 
   return ret;
 }
@@ -7620,7 +7619,7 @@ expand_mem_thread_fence (enum memmodel model)
 {
   if (HAVE_mem_thread_fence)
     emit_insn (gen_mem_thread_fence (GEN_INT (model)));
-  else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
+  else if (!is_mm_relaxed (model))
     {
       if (HAVE_memory_barrier)
 	emit_insn (gen_memory_barrier ());
@@ -7644,7 +7643,7 @@ expand_mem_signal_fence (enum memmodel model)
 {
   if (HAVE_mem_signal_fence)
     emit_insn (gen_mem_signal_fence (GEN_INT (model)));
-  else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED)
+  else if (!is_mm_relaxed (model))
     {
       /* By default targets are coherent between a thread and the signal
 	 handler running on the same thread.  Thus this really becomes a
@@ -7699,7 +7698,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model)
     target = gen_reg_rtx (mode);
 
   /* For SEQ_CST, emit a barrier before the load.  */
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     expand_mem_thread_fence (model);
 
   emit_move_insn (target, mem);
@@ -7745,7 +7744,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
 	  if (maybe_expand_insn (icode, 2, ops))
 	    {
 	      /* lock_release is only a release barrier.  */
-	      if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+	      if (is_mm_seq_cst (model))
 		expand_mem_thread_fence (model);
 	      return const0_rtx;
 	    }
@@ -7772,7 +7771,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release)
   emit_move_insn (mem, val);
 
   /* For SEQ_CST, also emit a barrier after the store.  */
-  if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST)
+  if (is_mm_seq_cst (model))
     expand_mem_thread_fence (model);
 
   return const0_rtx;
diff --git a/gcc/tree.h b/gcc/tree.h
index 7e5f4b3..9fe3ce6 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4381,6 +4381,69 @@ extern void assign_assembler_name_if_neeeded (tree);
 extern void warn_deprecated_use (tree, tree);
 extern void cache_integer_cst (tree);
 
+/* Return the memory model from a host integer.  */
+static inline enum memmodel
+memmodel_from_int (unsigned HOST_WIDE_INT val)
+{
+  return (enum memmodel) (val & MEMMODEL_MASK);
+}
+
+/* Return the base memory model from a host integer.  */
+static inline enum memmodel
+memmodel_base (unsigned HOST_WIDE_INT val)
+{
+  return (enum memmodel) (val & MEMMODEL_BASE_MASK);
+}
+
+/* Return TRUE if the memory model is RELAXED.  */
+static inline bool
+is_mm_relaxed (enum memmodel model)
+{
+  return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELAXED;
+}
+
+/* Return TRUE if the memory model is CONSUME.  */
+static inline bool
+is_mm_consume (enum memmodel model)
+{
+  return (model & MEMMODEL_BASE_MASK) == MEMMODEL_CONSUME;
+}
+
+/* Return TRUE if the memory model is ACQUIRE.  */
+static inline bool
+is_mm_acquire (enum memmodel model)
+{
+  return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQUIRE;
+}
+
+/* Return TRUE if the memory model is RELEASE.  */
+static inline bool
+is_mm_release (enum memmodel model)
+{
+  return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELEASE;
+}
+
+/* Return TRUE if the memory model is ACQ_REL.  */
+static inline bool
+is_mm_acq_rel (enum memmodel model)
+{
+  return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQ_REL;
+}
+
+/* Return TRUE if the memory model is SEQ_CST.  */
+static inline bool
+is_mm_seq_cst (enum memmodel model)
+{
+  return (model & MEMMODEL_BASE_MASK) == MEMMODEL_SEQ_CST;
+}
+
+/* Return TRUE if the memory model is a SYNC variant.  */
+static inline bool
+is_mm_sync (enum memmodel model)
+{
+  return (model & MEMMODEL_SYNC);
+}
+
 /* Compare and hash for any structure which begins with a canonical
    pointer.  Assumes all pointers are interchangeable, which is sort
    of already assumed by gcc elsewhere IIRC.  */
diff --git a/gcc/tsan.c b/gcc/tsan.c
index ebafbb0..2752182 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -535,7 +535,7 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
 	  case fetch_op:
 	    last_arg = gimple_call_arg (stmt, num - 1);
 	    if (!tree_fits_uhwi_p (last_arg)
-		|| tree_to_uhwi (last_arg) > MEMMODEL_SEQ_CST)
+		|| memmodel_base (tree_to_uhwi (last_arg)) >= MEMMODEL_LAST)
 	      return;
 	    gimple_call_set_fndecl (stmt, decl);
 	    update_stmt (stmt);
@@ -600,10 +600,10 @@ instrument_builtin_call (gimple_stmt_iterator *gsi)
 	    for (j = 0; j < 6; j++)
 	      args[j] = gimple_call_arg (stmt, j);
 	    if (!tree_fits_uhwi_p (args[4])
-		|| tree_to_uhwi (args[4]) > MEMMODEL_SEQ_CST)
+		|| memmodel_base (tree_to_uhwi (args[4])) >= MEMMODEL_LAST)
 	      return;
 	    if (!tree_fits_uhwi_p (args[5])
-		|| tree_to_uhwi (args[5]) > MEMMODEL_SEQ_CST)
+		|| memmodel_base (tree_to_uhwi (args[5])) >= MEMMODEL_LAST)
 	      return;
 	    update_gimple_call (gsi, decl, 5, args[0], args[1], args[2],
 				args[4], args[5]);
-- 
1.9.1


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

* [PATCH 2/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,fetch-op builtins.
  2015-06-26 12:06 [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab
@ 2015-06-26 12:08 ` Matthew Wahab
  2015-07-02 11:14   ` James Greenhalgh
  2015-06-26 12:10 ` [PATCH 3/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,compare-and-swap builtins Matthew Wahab
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Matthew Wahab @ 2015-06-26 12:08 UTC (permalink / raw)
  To: gcc-patches

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


This patch backports the changes made to strengthen the barriers emitted for
the __sync fetch-and-op/op-and-fetch builtins.

The trunk patch submission is at
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01989.html
The commit is at https://gcc.gnu.org/ml/gcc-cvs/2015-06/msg00076.html

Tested the series for aarch64-none-linux-gnu with check-gcc

Ok for the branch?
Matthew

2015-06-26  Matthew Wahab  <matthew.wahab@arm.com>

	Backport from trunk.
	2015-06-01  Matthew Wahab  <matthew.wahab@arm.com>

	PR target/65697
	* config/aarch64/aarch64.c (aarch64_emit_post_barrier):New.
	(aarch64_split_atomic_op): Check for __sync memory models, emit
	appropriate initial loads and final barriers.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-Aarch64-5.1-Strengthen-barriers-for-sync-fetch-op-bu.patch --]
[-- Type: text/x-patch;  name=0002-Aarch64-5.1-Strengthen-barriers-for-sync-fetch-op-bu.patch, Size: 3060 bytes --]

From d6d3351b4547d0ad52e4d7e9955fafdced11491a Mon Sep 17 00:00:00 2001
From: mwahab <mwahab@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Mon, 1 Jun 2015 15:18:19 +0000
Subject: [PATCH 2/4] [Aarch64][5.1] Strengthen barriers for sync-fetch-op
 builtin.

        PR target/65697
	* config/aarch64/aarch64.c (aarch64_emit_post_barrier):New.
	(aarch64_split_atomic_op): Check for __sync memory models, emit
	appropriate initial loads and final barriers.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223983 138bc75d-0d04-0410-961f-82ee72b054a4

Conflicts:
	gcc/ChangeLog
	gcc/config/aarch64/aarch64.c

Change-Id: I45600c4dd0002b4c2d48de36d695c83581fe50da
---
 gcc/config/aarch64/aarch64.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index b8b37b8..708fc23 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -9066,6 +9066,23 @@ aarch64_expand_compare_and_swap (rtx operands[])
   emit_insn (gen_rtx_SET (VOIDmode, bval, x));
 }
 
+/* Emit a barrier, that is appropriate for memory model MODEL, at the end of a
+   sequence implementing an atomic operation.  */
+
+static void
+aarch64_emit_post_barrier (enum memmodel model)
+{
+  const enum memmodel base_model = memmodel_base (model);
+
+  if (is_mm_sync (model)
+      && (base_model == MEMMODEL_ACQUIRE
+	  || base_model == MEMMODEL_ACQ_REL
+	  || base_model == MEMMODEL_SEQ_CST))
+    {
+      emit_insn (gen_mem_thread_fence (GEN_INT (MEMMODEL_SEQ_CST)));
+    }
+}
+
 /* Split a compare and swap pattern.  */
 
 void
@@ -9128,6 +9145,8 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
 {
   machine_mode mode = GET_MODE (mem);
   machine_mode wmode = (mode == DImode ? DImode : SImode);
+  const enum memmodel model = memmodel_from_int (INTVAL (model_rtx));
+  const bool is_sync = is_mm_sync (model);
   rtx_code_label *label;
   rtx x;
 
@@ -9142,7 +9161,13 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
     old_out = new_out;
   value = simplify_gen_subreg (wmode, value, mode, 0);
 
-  aarch64_emit_load_exclusive (mode, old_out, mem, model_rtx);
+  /* The initial load can be relaxed for a __sync operation since a final
+     barrier will be emitted to stop code hoisting.  */
+ if (is_sync)
+    aarch64_emit_load_exclusive (mode, old_out, mem,
+				 GEN_INT (MEMMODEL_RELAXED));
+  else
+    aarch64_emit_load_exclusive (mode, old_out, mem, model_rtx);
 
   switch (code)
     {
@@ -9178,6 +9203,10 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
   x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
 			    gen_rtx_LABEL_REF (Pmode, label), pc_rtx);
   aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode, pc_rtx, x));
+
+  /* Emit any final barrier needed for a __sync operation.  */
+  if (is_sync)
+    aarch64_emit_post_barrier (model);
 }
 
 static void
-- 
1.9.1


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

* [PATCH 3/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,compare-and-swap builtins.
  2015-06-26 12:06 [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab
  2015-06-26 12:08 ` [PATCH 2/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,fetch-op builtins Matthew Wahab
@ 2015-06-26 12:10 ` Matthew Wahab
  2015-07-02 11:13   ` James Greenhalgh
  2015-06-26 12:21 ` [PATCH 4/4][PR target/65697][5.1][Aarch64] Backport tests for __sync_builtins Matthew Wahab
  2015-07-02 11:22 ` [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab
  3 siblings, 1 reply; 8+ messages in thread
From: Matthew Wahab @ 2015-06-26 12:10 UTC (permalink / raw)
  To: gcc-patches

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

This patch backports the changes made to strengthen the barriers emitted for
the __sync compare-and-swap builtins.

The trunk patch submission is at
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01990.html
The commit is at https://gcc.gnu.org/ml/gcc-cvs/2015-06/msg00077.html

Tested the series for aarch64-none-linux-gnu with check-gcc

Ok for the branch?
Matthew

2015-06-26  Matthew Wahab  <matthew.wahab@arm.com>

	Backport from trunk.
	2015-06-01  Matthew Wahab  <matthew.wahab@arm.com>

	PR target/65697
	* config/aarch64/aarch64.c (aarch64_split_compare_and_swap): Check
	for __sync memory models, emit initial loads and final barriers as
	appropriate.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-Aarch64-5.1-Strengthen-barriers-for-sync-compare-swa.patch --]
[-- Type: text/x-patch;  name=0003-Aarch64-5.1-Strengthen-barriers-for-sync-compare-swa.patch, Size: 2665 bytes --]

From 5fbfcc46e6eb2b8b61aa96c9c96da9a572bc4d12 Mon Sep 17 00:00:00 2001
From: mwahab <mwahab@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Mon, 1 Jun 2015 15:21:02 +0000
Subject: [PATCH 3/4] [Aarch64][5.1] Strengthen barriers for sync-compare-swap
 builtins

	PR target/65697
	* config/aarch64/aarch64.c (aarch64_split_compare_and_swap): Check
	for __sync memory models, emit initial loads and final barriers as
	appropriate.

Change-Id: I65d8000c081d582246b81c7f3892c509a64b136c
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223984 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/config/aarch64/aarch64.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 708fc23..59d2e3a 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -9093,14 +9093,18 @@ aarch64_split_compare_and_swap (rtx operands[])
   bool is_weak;
   rtx_code_label *label1, *label2;
   rtx x, cond;
+  enum memmodel model;
+  rtx model_rtx;
 
   rval = operands[0];
   mem = operands[1];
   oldval = operands[2];
   newval = operands[3];
   is_weak = (operands[4] != const0_rtx);
+  model_rtx = operands[5];
   scratch = operands[7];
   mode = GET_MODE (mem);
+  model = memmodel_from_int (INTVAL (model_rtx));
 
   label1 = NULL;
   if (!is_weak)
@@ -9110,7 +9114,13 @@ aarch64_split_compare_and_swap (rtx operands[])
     }
   label2 = gen_label_rtx ();
 
-  aarch64_emit_load_exclusive (mode, rval, mem, operands[5]);
+  /* The initial load can be relaxed for a __sync operation since a final
+     barrier will be emitted to stop code hoisting.  */
+  if (is_mm_sync (model))
+    aarch64_emit_load_exclusive (mode, rval, mem,
+				 GEN_INT (MEMMODEL_RELAXED));
+  else
+    aarch64_emit_load_exclusive (mode, rval, mem, model_rtx);
 
   cond = aarch64_gen_compare_reg (NE, rval, oldval);
   x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
@@ -9118,7 +9128,7 @@ aarch64_split_compare_and_swap (rtx operands[])
 			    gen_rtx_LABEL_REF (Pmode, label2), pc_rtx);
   aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode, pc_rtx, x));
 
-  aarch64_emit_store_exclusive (mode, scratch, mem, newval, operands[5]);
+  aarch64_emit_store_exclusive (mode, scratch, mem, newval, model_rtx);
 
   if (!is_weak)
     {
@@ -9135,6 +9145,10 @@ aarch64_split_compare_and_swap (rtx operands[])
     }
 
   emit_label (label2);
+
+  /* Emit any final barrier needed for a __sync operation.  */
+  if (is_mm_sync (model))
+    aarch64_emit_post_barrier (model);
 }
 
 /* Split an atomic operation.  */
-- 
1.9.1


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

* [PATCH 4/4][PR target/65697][5.1][Aarch64] Backport tests for __sync_builtins.
  2015-06-26 12:06 [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab
  2015-06-26 12:08 ` [PATCH 2/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,fetch-op builtins Matthew Wahab
  2015-06-26 12:10 ` [PATCH 3/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,compare-and-swap builtins Matthew Wahab
@ 2015-06-26 12:21 ` Matthew Wahab
  2015-07-02 11:13   ` James Greenhalgh
  2015-07-02 11:22 ` [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab
  3 siblings, 1 reply; 8+ messages in thread
From: Matthew Wahab @ 2015-06-26 12:21 UTC (permalink / raw)
  To: gcc-patches

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

This patch backports the tests added for the code generated by the Aarch64 backend
for the __sync builtins.

The trunk patch submission is at
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01992.html
The commit is at https://gcc.gnu.org/ml/gcc-cvs/2015-06/msg00079.html

Tested the series for aarch64-none-linux-gnu with check-gcc

Ok for the branch?
Matthew

2015-06-26  Matthew Wahab  <matthew.wahab@arm.com>

	Backport from trunk
	2015-06-01  Matthew Wahab  <matthew.wahab@arm.com>

	PR target/65697
	* gcc.target/aarch64/sync-comp-swap.c: New.
	* gcc.target/aarch64/sync-comp-swap.x: New.
	* gcc.target/aarch64/sync-op-acquire.c: New.
	* gcc.target/aarch64/sync-op-acquire.x: New.
	* gcc.target/aarch64/sync-op-full.c: New.
	* gcc.target/aarch64/sync-op-full.x: New.
	* gcc.target/aarch64/sync-op-release.c: New.
	* gcc.target/aarch64/sync-op-release.x: New.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0004-Aarch64-5.1-Add-tests-for-__sync_builtins.patch --]
[-- Type: text/x-patch;  name=0004-Aarch64-5.1-Add-tests-for-__sync_builtins.patch, Size: 6604 bytes --]

From 704058e9acd56043c3b8549c3bbe14acf1c370e3 Mon Sep 17 00:00:00 2001
From: mwahab <mwahab@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Mon, 1 Jun 2015 15:24:37 +0000
Subject: [PATCH 4/4] [Aarch64][5.1] Add tests for __sync_builtins.

	PR target/65697
	* gcc.target/aarch64/sync-comp-swap.c: New.
	* gcc.target/aarch64/sync-comp-swap.x: New.
	* gcc.target/aarch64/sync-op-acquire.c: New.
	* gcc.target/aarch64/sync-op-acquire.x: New.
	* gcc.target/aarch64/sync-op-full.c: New.
	* gcc.target/aarch64/sync-op-full.x: New.
	* gcc.target/aarch64/sync-op-release.c: New.
	* gcc.target/aarch64/sync-op-release.x: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223986 138bc75d-0d04-0410-961f-82ee72b054a4

Conflicts:
	gcc/testsuite/ChangeLog

Change-Id: I1cc83df41532588a7d91c5b021838392e5547e85
---
 gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c  |  8 +++
 gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x  | 13 ++++
 gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c |  8 +++
 gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x |  7 +++
 gcc/testsuite/gcc.target/aarch64/sync-op-full.c    |  8 +++
 gcc/testsuite/gcc.target/aarch64/sync-op-full.x    | 73 ++++++++++++++++++++++
 gcc/testsuite/gcc.target/aarch64/sync-op-release.c |  6 ++
 gcc/testsuite/gcc.target/aarch64/sync-op-release.x |  7 +++
 8 files changed, 130 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-full.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-full.x
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-release.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-release.x

diff --git a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c
new file mode 100644
index 0000000..126b997
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf" } */
+
+#include "sync-comp-swap.x"
+
+/* { dg-final { scan-assembler-times "ldxr\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 2 } } */
+/* { dg-final { scan-assembler-times "stlxr\tw\[0-9\]+, w\[0-9\]+, \\\[x\[0-9\]+\\\]" 2 } } */
+/* { dg-final { scan-assembler-times "dmb\tish" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x
new file mode 100644
index 0000000..eda52e40
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x
@@ -0,0 +1,13 @@
+int v = 0;
+
+int
+sync_bool_compare_swap (int a, int b)
+{
+  return __sync_bool_compare_and_swap (&v, &a, &b);
+}
+
+int
+sync_val_compare_swap (int a, int b)
+{
+  return __sync_val_compare_and_swap (&v, &a, &b);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c
new file mode 100644
index 0000000..2639f9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include "sync-op-acquire.x"
+
+/* { dg-final { scan-assembler-times "ldxr\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "stxr\tw\[0-9\]+, w\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
+/* { dg-final { scan-assembler-times "dmb\tish" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x
new file mode 100644
index 0000000..4c4548c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x
@@ -0,0 +1,7 @@
+int v;
+
+int
+sync_lock_test_and_set (int a)
+{
+  return __sync_lock_test_and_set (&v, a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-full.c b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c
new file mode 100644
index 0000000..10fc8fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include "sync-op-full.x"
+
+/* { dg-final { scan-assembler-times "ldxr\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 12 } } */
+/* { dg-final { scan-assembler-times "stlxr\tw\[0-9\]+, w\[0-9\]+, \\\[x\[0-9\]+\\\]" 12 } } */
+/* { dg-final { scan-assembler-times "dmb\tish" 12 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-full.x b/gcc/testsuite/gcc.target/aarch64/sync-op-full.x
new file mode 100644
index 0000000..c24223d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-op-full.x
@@ -0,0 +1,73 @@
+int v = 0;
+
+int
+sync_fetch_and_add (int a)
+{
+  return __sync_fetch_and_add (&v, a);
+}
+
+int
+sync_fetch_and_sub (int a)
+{
+  return __sync_fetch_and_sub (&v, a);
+}
+
+int
+sync_fetch_and_and (int a)
+{
+  return __sync_fetch_and_and (&v, a);
+}
+
+int
+sync_fetch_and_nand (int a)
+{
+  return __sync_fetch_and_nand (&v, a);
+}
+
+int
+sync_fetch_and_xor (int a)
+{
+  return __sync_fetch_and_xor (&v, a);
+}
+
+int
+sync_fetch_and_or (int a)
+{
+  return __sync_fetch_and_or (&v, a);
+}
+
+int
+sync_add_and_fetch (int a)
+{
+  return __sync_add_and_fetch (&v, a);
+}
+
+int
+sync_sub_and_fetch (int a)
+{
+  return __sync_sub_and_fetch (&v, a);
+}
+
+int
+sync_and_and_fetch (int a)
+{
+  return __sync_and_and_fetch (&v, a);
+}
+
+int
+sync_nand_and_fetch (int a)
+{
+  return __sync_nand_and_fetch (&v, a);
+}
+
+int
+sync_xor_and_fetch (int a)
+{
+  return __sync_xor_and_fetch (&v, a);
+}
+
+int
+sync_or_and_fetch (int a)
+{
+  return __sync_or_and_fetch (&v, a);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-release.c b/gcc/testsuite/gcc.target/aarch64/sync-op-release.c
new file mode 100644
index 0000000..d25b46f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-op-release.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include "sync-op-release.x"
+
+/* { dg-final { scan-assembler-times "stlr" 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-release.x b/gcc/testsuite/gcc.target/aarch64/sync-op-release.x
new file mode 100644
index 0000000..704bcff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sync-op-release.x
@@ -0,0 +1,7 @@
+int v;
+
+void
+sync_lock_release (void)
+{
+  __sync_lock_release (&v);
+}
-- 
1.9.1


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

* Re: [PATCH 4/4][PR target/65697][5.1][Aarch64] Backport tests for __sync_builtins.
  2015-06-26 12:21 ` [PATCH 4/4][PR target/65697][5.1][Aarch64] Backport tests for __sync_builtins Matthew Wahab
@ 2015-07-02 11:13   ` James Greenhalgh
  0 siblings, 0 replies; 8+ messages in thread
From: James Greenhalgh @ 2015-07-02 11:13 UTC (permalink / raw)
  To: Matthew Wahab; +Cc: gcc-patches

On Fri, Jun 26, 2015 at 01:10:21PM +0100, Matthew Wahab wrote:
> This patch backports the tests added for the code generated by the Aarch64 backend
> for the __sync builtins.
> 
> The trunk patch submission is at
> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01992.html
> The commit is at https://gcc.gnu.org/ml/gcc-cvs/2015-06/msg00079.html
> 
> Tested the series for aarch64-none-linux-gnu with check-gcc
> 
> Ok for the branch?
> Matthew

OK.

Thanks,
James

> 
> 2015-06-26  Matthew Wahab  <matthew.wahab@arm.com>
> 
> 	Backport from trunk
> 	2015-06-01  Matthew Wahab  <matthew.wahab@arm.com>
> 
> 	PR target/65697
> 	* gcc.target/aarch64/sync-comp-swap.c: New.
> 	* gcc.target/aarch64/sync-comp-swap.x: New.
> 	* gcc.target/aarch64/sync-op-acquire.c: New.
> 	* gcc.target/aarch64/sync-op-acquire.x: New.
> 	* gcc.target/aarch64/sync-op-full.c: New.
> 	* gcc.target/aarch64/sync-op-full.x: New.
> 	* gcc.target/aarch64/sync-op-release.c: New.
> 	* gcc.target/aarch64/sync-op-release.x: New.
> 

> From 704058e9acd56043c3b8549c3bbe14acf1c370e3 Mon Sep 17 00:00:00 2001
> From: mwahab <mwahab@138bc75d-0d04-0410-961f-82ee72b054a4>
> Date: Mon, 1 Jun 2015 15:24:37 +0000
> Subject: [PATCH 4/4] [Aarch64][5.1] Add tests for __sync_builtins.
> 
> 	PR target/65697
> 	* gcc.target/aarch64/sync-comp-swap.c: New.
> 	* gcc.target/aarch64/sync-comp-swap.x: New.
> 	* gcc.target/aarch64/sync-op-acquire.c: New.
> 	* gcc.target/aarch64/sync-op-acquire.x: New.
> 	* gcc.target/aarch64/sync-op-full.c: New.
> 	* gcc.target/aarch64/sync-op-full.x: New.
> 	* gcc.target/aarch64/sync-op-release.c: New.
> 	* gcc.target/aarch64/sync-op-release.x: New.
> 
> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223986 138bc75d-0d04-0410-961f-82ee72b054a4
> 
> Conflicts:
> 	gcc/testsuite/ChangeLog
> 
> Change-Id: I1cc83df41532588a7d91c5b021838392e5547e85
> ---
>  gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c  |  8 +++
>  gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x  | 13 ++++
>  gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c |  8 +++
>  gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x |  7 +++
>  gcc/testsuite/gcc.target/aarch64/sync-op-full.c    |  8 +++
>  gcc/testsuite/gcc.target/aarch64/sync-op-full.x    | 73 ++++++++++++++++++++++
>  gcc/testsuite/gcc.target/aarch64/sync-op-release.c |  6 ++
>  gcc/testsuite/gcc.target/aarch64/sync-op-release.x |  7 +++
>  8 files changed, 130 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-full.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-full.x
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-release.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/sync-op-release.x
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c
> new file mode 100644
> index 0000000..126b997
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fno-ipa-icf" } */
> +
> +#include "sync-comp-swap.x"
> +
> +/* { dg-final { scan-assembler-times "ldxr\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 2 } } */
> +/* { dg-final { scan-assembler-times "stlxr\tw\[0-9\]+, w\[0-9\]+, \\\[x\[0-9\]+\\\]" 2 } } */
> +/* { dg-final { scan-assembler-times "dmb\tish" 2 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x
> new file mode 100644
> index 0000000..eda52e40
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-comp-swap.x
> @@ -0,0 +1,13 @@
> +int v = 0;
> +
> +int
> +sync_bool_compare_swap (int a, int b)
> +{
> +  return __sync_bool_compare_and_swap (&v, &a, &b);
> +}
> +
> +int
> +sync_val_compare_swap (int a, int b)
> +{
> +  return __sync_val_compare_and_swap (&v, &a, &b);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c
> new file mode 100644
> index 0000000..2639f9f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include "sync-op-acquire.x"
> +
> +/* { dg-final { scan-assembler-times "ldxr\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
> +/* { dg-final { scan-assembler-times "stxr\tw\[0-9\]+, w\[0-9\]+, \\\[x\[0-9\]+\\\]" 1 } } */
> +/* { dg-final { scan-assembler-times "dmb\tish" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x
> new file mode 100644
> index 0000000..4c4548c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-acquire.x
> @@ -0,0 +1,7 @@
> +int v;
> +
> +int
> +sync_lock_test_and_set (int a)
> +{
> +  return __sync_lock_test_and_set (&v, a);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-full.c b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c
> new file mode 100644
> index 0000000..10fc8fc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-full.c
> @@ -0,0 +1,8 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include "sync-op-full.x"
> +
> +/* { dg-final { scan-assembler-times "ldxr\tw\[0-9\]+, \\\[x\[0-9\]+\\\]" 12 } } */
> +/* { dg-final { scan-assembler-times "stlxr\tw\[0-9\]+, w\[0-9\]+, \\\[x\[0-9\]+\\\]" 12 } } */
> +/* { dg-final { scan-assembler-times "dmb\tish" 12 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-full.x b/gcc/testsuite/gcc.target/aarch64/sync-op-full.x
> new file mode 100644
> index 0000000..c24223d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-full.x
> @@ -0,0 +1,73 @@
> +int v = 0;
> +
> +int
> +sync_fetch_and_add (int a)
> +{
> +  return __sync_fetch_and_add (&v, a);
> +}
> +
> +int
> +sync_fetch_and_sub (int a)
> +{
> +  return __sync_fetch_and_sub (&v, a);
> +}
> +
> +int
> +sync_fetch_and_and (int a)
> +{
> +  return __sync_fetch_and_and (&v, a);
> +}
> +
> +int
> +sync_fetch_and_nand (int a)
> +{
> +  return __sync_fetch_and_nand (&v, a);
> +}
> +
> +int
> +sync_fetch_and_xor (int a)
> +{
> +  return __sync_fetch_and_xor (&v, a);
> +}
> +
> +int
> +sync_fetch_and_or (int a)
> +{
> +  return __sync_fetch_and_or (&v, a);
> +}
> +
> +int
> +sync_add_and_fetch (int a)
> +{
> +  return __sync_add_and_fetch (&v, a);
> +}
> +
> +int
> +sync_sub_and_fetch (int a)
> +{
> +  return __sync_sub_and_fetch (&v, a);
> +}
> +
> +int
> +sync_and_and_fetch (int a)
> +{
> +  return __sync_and_and_fetch (&v, a);
> +}
> +
> +int
> +sync_nand_and_fetch (int a)
> +{
> +  return __sync_nand_and_fetch (&v, a);
> +}
> +
> +int
> +sync_xor_and_fetch (int a)
> +{
> +  return __sync_xor_and_fetch (&v, a);
> +}
> +
> +int
> +sync_or_and_fetch (int a)
> +{
> +  return __sync_or_and_fetch (&v, a);
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-release.c b/gcc/testsuite/gcc.target/aarch64/sync-op-release.c
> new file mode 100644
> index 0000000..d25b46f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-release.c
> @@ -0,0 +1,6 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +#include "sync-op-release.x"
> +
> +/* { dg-final { scan-assembler-times "stlr" 1 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/sync-op-release.x b/gcc/testsuite/gcc.target/aarch64/sync-op-release.x
> new file mode 100644
> index 0000000..704bcff
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sync-op-release.x
> @@ -0,0 +1,7 @@
> +int v;
> +
> +void
> +sync_lock_release (void)
> +{
> +  __sync_lock_release (&v);
> +}
> -- 
> 1.9.1
> 

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

* Re: [PATCH 3/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,compare-and-swap builtins.
  2015-06-26 12:10 ` [PATCH 3/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,compare-and-swap builtins Matthew Wahab
@ 2015-07-02 11:13   ` James Greenhalgh
  0 siblings, 0 replies; 8+ messages in thread
From: James Greenhalgh @ 2015-07-02 11:13 UTC (permalink / raw)
  To: Matthew Wahab; +Cc: gcc-patches

On Fri, Jun 26, 2015 at 01:08:50PM +0100, Matthew Wahab wrote:
> This patch backports the changes made to strengthen the barriers emitted for
> the __sync compare-and-swap builtins.
> 
> The trunk patch submission is at
> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01990.html
> The commit is at https://gcc.gnu.org/ml/gcc-cvs/2015-06/msg00077.html
> 
> Tested the series for aarch64-none-linux-gnu with check-gcc
> 
> Ok for the branch?
> Matthew

OK.

Thanks,
James

> 
> 2015-06-26  Matthew Wahab  <matthew.wahab@arm.com>
> 
> 	Backport from trunk.
> 	2015-06-01  Matthew Wahab  <matthew.wahab@arm.com>
> 
> 	PR target/65697
> 	* config/aarch64/aarch64.c (aarch64_split_compare_and_swap): Check
> 	for __sync memory models, emit initial loads and final barriers as
> 	appropriate.
> 
> 

> From 5fbfcc46e6eb2b8b61aa96c9c96da9a572bc4d12 Mon Sep 17 00:00:00 2001
> From: mwahab <mwahab@138bc75d-0d04-0410-961f-82ee72b054a4>
> Date: Mon, 1 Jun 2015 15:21:02 +0000
> Subject: [PATCH 3/4] [Aarch64][5.1] Strengthen barriers for sync-compare-swap
>  builtins
> 
> 	PR target/65697
> 	* config/aarch64/aarch64.c (aarch64_split_compare_and_swap): Check
> 	for __sync memory models, emit initial loads and final barriers as
> 	appropriate.
> 
> Change-Id: I65d8000c081d582246b81c7f3892c509a64b136c
> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223984 138bc75d-0d04-0410-961f-82ee72b054a4
> ---
>  gcc/config/aarch64/aarch64.c | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index 708fc23..59d2e3a 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -9093,14 +9093,18 @@ aarch64_split_compare_and_swap (rtx operands[])
>    bool is_weak;
>    rtx_code_label *label1, *label2;
>    rtx x, cond;
> +  enum memmodel model;
> +  rtx model_rtx;
>  
>    rval = operands[0];
>    mem = operands[1];
>    oldval = operands[2];
>    newval = operands[3];
>    is_weak = (operands[4] != const0_rtx);
> +  model_rtx = operands[5];
>    scratch = operands[7];
>    mode = GET_MODE (mem);
> +  model = memmodel_from_int (INTVAL (model_rtx));
>  
>    label1 = NULL;
>    if (!is_weak)
> @@ -9110,7 +9114,13 @@ aarch64_split_compare_and_swap (rtx operands[])
>      }
>    label2 = gen_label_rtx ();
>  
> -  aarch64_emit_load_exclusive (mode, rval, mem, operands[5]);
> +  /* The initial load can be relaxed for a __sync operation since a final
> +     barrier will be emitted to stop code hoisting.  */
> +  if (is_mm_sync (model))
> +    aarch64_emit_load_exclusive (mode, rval, mem,
> +				 GEN_INT (MEMMODEL_RELAXED));
> +  else
> +    aarch64_emit_load_exclusive (mode, rval, mem, model_rtx);
>  
>    cond = aarch64_gen_compare_reg (NE, rval, oldval);
>    x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
> @@ -9118,7 +9128,7 @@ aarch64_split_compare_and_swap (rtx operands[])
>  			    gen_rtx_LABEL_REF (Pmode, label2), pc_rtx);
>    aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode, pc_rtx, x));
>  
> -  aarch64_emit_store_exclusive (mode, scratch, mem, newval, operands[5]);
> +  aarch64_emit_store_exclusive (mode, scratch, mem, newval, model_rtx);
>  
>    if (!is_weak)
>      {
> @@ -9135,6 +9145,10 @@ aarch64_split_compare_and_swap (rtx operands[])
>      }
>  
>    emit_label (label2);
> +
> +  /* Emit any final barrier needed for a __sync operation.  */
> +  if (is_mm_sync (model))
> +    aarch64_emit_post_barrier (model);
>  }
>  
>  /* Split an atomic operation.  */
> -- 
> 1.9.1
> 

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

* Re: [PATCH 2/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,fetch-op builtins.
  2015-06-26 12:08 ` [PATCH 2/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,fetch-op builtins Matthew Wahab
@ 2015-07-02 11:14   ` James Greenhalgh
  0 siblings, 0 replies; 8+ messages in thread
From: James Greenhalgh @ 2015-07-02 11:14 UTC (permalink / raw)
  To: Matthew Wahab; +Cc: gcc-patches

On Fri, Jun 26, 2015 at 01:07:09PM +0100, Matthew Wahab wrote:
> 
> This patch backports the changes made to strengthen the barriers emitted for
> the __sync fetch-and-op/op-and-fetch builtins.
> 
> The trunk patch submission is at
> https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01989.html
> The commit is at https://gcc.gnu.org/ml/gcc-cvs/2015-06/msg00076.html
> 
> Tested the series for aarch64-none-linux-gnu with check-gcc
> 
> Ok for the branch?
> Matthew

OK.

Thanks,
James

> 
> 2015-06-26  Matthew Wahab  <matthew.wahab@arm.com>
> 
> 	Backport from trunk.
> 	2015-06-01  Matthew Wahab  <matthew.wahab@arm.com>
> 
> 	PR target/65697
> 	* config/aarch64/aarch64.c (aarch64_emit_post_barrier):New.
> 	(aarch64_split_atomic_op): Check for __sync memory models, emit
> 	appropriate initial loads and final barriers.
> 

> From d6d3351b4547d0ad52e4d7e9955fafdced11491a Mon Sep 17 00:00:00 2001
> From: mwahab <mwahab@138bc75d-0d04-0410-961f-82ee72b054a4>
> Date: Mon, 1 Jun 2015 15:18:19 +0000
> Subject: [PATCH 2/4] [Aarch64][5.1] Strengthen barriers for sync-fetch-op
>  builtin.
> 
>         PR target/65697
> 	* config/aarch64/aarch64.c (aarch64_emit_post_barrier):New.
> 	(aarch64_split_atomic_op): Check for __sync memory models, emit
> 	appropriate initial loads and final barriers.
> 
> git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223983 138bc75d-0d04-0410-961f-82ee72b054a4
> 
> Conflicts:
> 	gcc/ChangeLog
> 	gcc/config/aarch64/aarch64.c
> 
> Change-Id: I45600c4dd0002b4c2d48de36d695c83581fe50da
> ---
>  gcc/config/aarch64/aarch64.c | 31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
> 
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index b8b37b8..708fc23 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -9066,6 +9066,23 @@ aarch64_expand_compare_and_swap (rtx operands[])
>    emit_insn (gen_rtx_SET (VOIDmode, bval, x));
>  }
>  
> +/* Emit a barrier, that is appropriate for memory model MODEL, at the end of a
> +   sequence implementing an atomic operation.  */
> +
> +static void
> +aarch64_emit_post_barrier (enum memmodel model)
> +{
> +  const enum memmodel base_model = memmodel_base (model);
> +
> +  if (is_mm_sync (model)
> +      && (base_model == MEMMODEL_ACQUIRE
> +	  || base_model == MEMMODEL_ACQ_REL
> +	  || base_model == MEMMODEL_SEQ_CST))
> +    {
> +      emit_insn (gen_mem_thread_fence (GEN_INT (MEMMODEL_SEQ_CST)));
> +    }
> +}
> +
>  /* Split a compare and swap pattern.  */
>  
>  void
> @@ -9128,6 +9145,8 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
>  {
>    machine_mode mode = GET_MODE (mem);
>    machine_mode wmode = (mode == DImode ? DImode : SImode);
> +  const enum memmodel model = memmodel_from_int (INTVAL (model_rtx));
> +  const bool is_sync = is_mm_sync (model);
>    rtx_code_label *label;
>    rtx x;
>  
> @@ -9142,7 +9161,13 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
>      old_out = new_out;
>    value = simplify_gen_subreg (wmode, value, mode, 0);
>  
> -  aarch64_emit_load_exclusive (mode, old_out, mem, model_rtx);
> +  /* The initial load can be relaxed for a __sync operation since a final
> +     barrier will be emitted to stop code hoisting.  */
> + if (is_sync)
> +    aarch64_emit_load_exclusive (mode, old_out, mem,
> +				 GEN_INT (MEMMODEL_RELAXED));
> +  else
> +    aarch64_emit_load_exclusive (mode, old_out, mem, model_rtx);
>  
>    switch (code)
>      {
> @@ -9178,6 +9203,10 @@ aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem,
>    x = gen_rtx_IF_THEN_ELSE (VOIDmode, x,
>  			    gen_rtx_LABEL_REF (Pmode, label), pc_rtx);
>    aarch64_emit_unlikely_jump (gen_rtx_SET (VOIDmode, pc_rtx, x));
> +
> +  /* Emit any final barrier needed for a __sync operation.  */
> +  if (is_sync)
> +    aarch64_emit_post_barrier (model);
>  }
>  
>  static void
> -- 
> 1.9.1
> 

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

* Re: [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64
  2015-06-26 12:06 [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab
                   ` (2 preceding siblings ...)
  2015-06-26 12:21 ` [PATCH 4/4][PR target/65697][5.1][Aarch64] Backport tests for __sync_builtins Matthew Wahab
@ 2015-07-02 11:22 ` Matthew Wahab
  3 siblings, 0 replies; 8+ messages in thread
From: Matthew Wahab @ 2015-07-02 11:22 UTC (permalink / raw)
  To: gcc-patches

The first patch was approved on the gcc list: 
https://gcc.gnu.org/ml/gcc/2015-07/msg00028.html

Matthew

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

end of thread, other threads:[~2015-07-02 11:22 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-26 12:06 [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab
2015-06-26 12:08 ` [PATCH 2/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,fetch-op builtins Matthew Wahab
2015-07-02 11:14   ` James Greenhalgh
2015-06-26 12:10 ` [PATCH 3/4][PR target/65697][5.1][Aarch64] Backport stronger barriers for __sync,compare-and-swap builtins Matthew Wahab
2015-07-02 11:13   ` James Greenhalgh
2015-06-26 12:21 ` [PATCH 4/4][PR target/65697][5.1][Aarch64] Backport tests for __sync_builtins Matthew Wahab
2015-07-02 11:13   ` James Greenhalgh
2015-07-02 11:22 ` [PATCH 1/4][PR target/65697][5.1] Backport stronger barriers for GCC,__sync builtins on Aarch64 Matthew Wahab

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