[PATCH 1/5] sparc: Convert to mem_thread_fence.

Richard Henderson rth@redhat.com
Thu Nov 17 21:08:00 GMT 2011


---
 gcc/config/sparc/sparc-protos.h |    2 +
 gcc/config/sparc/sparc.c        |   45 +++++++++++++++++++++++++++++++
 gcc/config/sparc/sync.md        |   55 ++++++++++++++++++++++++++++++++------
 3 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index ccf20b1..fbb2ae8 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -111,4 +111,6 @@ extern bool sparc_expand_conditional_move (enum machine_mode, rtx *);
 extern void sparc_expand_vcond (enum machine_mode, rtx *, int, int);
 #endif /* RTX_CODE */
 
+extern void sparc_emit_membar_for_model (enum memmodel, int, int);
+
 #endif /* __SPARC_PROTOS_H__ */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 55759a0..2de6587 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -10849,6 +10849,51 @@ sparc_mangle_type (const_tree type)
 }
 #endif
 
+/* Expand a membar instruction for various use cases.  Both the LOAD_STORE
+   and BEFORE_AFTER arguments of the form X_Y.  They are two-bit masks where
+   bit 0 indicates that X is true, and bit 1 indicates Y is true.  */
+
+void
+sparc_emit_membar_for_model (enum memmodel model,
+			     int load_store, int before_after)
+{
+  /* Bits for the MEMBAR mmask field.  */
+  const int LoadLoad = 1;
+  const int StoreLoad = 2;
+  const int LoadStore = 4;
+  const int StoreStore = 8;
+
+  int mm = 0;
+
+  if (before_after & 1)
+    {
+      if (model == MEMMODEL_ACQUIRE
+          || model == MEMMODEL_ACQ_REL
+          || model == MEMMODEL_SEQ_CST)
+	{
+	  if (load_store & 1)
+	    mm |= LoadLoad | LoadStore;
+	  if (load_store & 2)
+	    mm |= StoreLoad | StoreStore;
+	}
+    }
+  if (before_after & 2)
+    {
+      if (model == MEMMODEL_RELEASE
+	  || model == MEMMODEL_ACQ_REL
+	  || model == MEMMODEL_SEQ_CST)
+	{
+	  if (load_store & 1)
+	    mm |= LoadLoad | StoreLoad;
+	  if (load_store & 2)
+	    mm |= LoadStore | StoreStore;
+	}
+    }
+
+  if (mm)
+    emit_insn (gen_membar (GEN_INT (mm)));
+}
+
 /* Expand code to perform a 8 or 16-bit compare and swap by doing 32-bit
    compare and swap on the word containing the byte or half-word.  */
 
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md
index a7380ab..f564fbf 100644
--- a/gcc/config/sparc/sync.md
+++ b/gcc/config/sparc/sync.md
@@ -1,5 +1,5 @@
 ;; GCC machine description for SPARC synchronization instructions.
-;; Copyright (C) 2005, 2007, 2009, 2010
+;; Copyright (C) 2005, 2007, 2009, 2010, 2011
 ;; Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
@@ -23,13 +23,32 @@
 (define_mode_iterator I48MODE [SI (DI "TARGET_ARCH64 || TARGET_V8PLUS")])
 (define_mode_attr modesuffix [(SI "") (DI "x")])
 
+(define_expand "mem_thread_fence"
+  [(match_operand:SI 0 "const_int_operand")]
+  "TARGET_V8 || TARGET_V9"
+{
+  enum memmodel model = (enum memmodel) INTVAL (operands[0]);
+  sparc_emit_membar_for_model (model, 3, 3);
+  DONE;
+})
+
 (define_expand "memory_barrier"
-  [(set (match_dup 0)
-	(unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
+  [(const_int 0)]
+  "TARGET_V8 || TARGET_V9"
+{
+  sparc_emit_membar_for_model (MEMMODEL_SEQ_CST, 3, 3);
+  DONE;
+})
+
+(define_expand "membar"
+  [(set (match_dup 1)
+	(unspec:BLK [(match_dup 1)
+		     (match_operand:SI 0 "const_int_operand")]
+		    UNSPEC_MEMBAR))]
   "TARGET_V8 || TARGET_V9"
 {
-  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
-  MEM_VOLATILE_P (operands[0]) = 1;
+  operands[1] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+  MEM_VOLATILE_P (operands[1]) = 1;
 })
 
 ;; In V8, loads are blocking and ordered wrt earlier loads, i.e. every load
@@ -37,22 +56,40 @@
 ;; In PSO, stbar orders the stores (membar #StoreStore).
 ;; In TSO, ldstub orders the stores wrt subsequent loads (membar #StoreLoad).
 ;; The combination of the three yields a full memory barrier in all cases.
+
+(define_insn "*membar_storestore"
+  [(set (match_operand:BLK 0 "" "")
+	(unspec:BLK [(match_dup 0) (const_int 8)] UNSPEC_MEMBAR))]
+  "TARGET_V8"
+  "stbar"
+  [(set_attr "type" "multi")])
+
+(define_insn "*membar_storeload"
+  [(set (match_operand:BLK 0 "" "")
+	(unspec:BLK [(match_dup 0) (const_int 2)] UNSPEC_MEMBAR))]
+  "TARGET_V8"
+  "ldstub\t[%%sp-1], %%g0"
+  [(set_attr "type" "multi")])
+
 (define_insn "*membar_v8"
   [(set (match_operand:BLK 0 "" "")
-	(unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
+	(unspec:BLK [(match_dup 0) (match_operand:SI 1 "const_int_operand")]
+		    UNSPEC_MEMBAR))]
   "TARGET_V8"
   "stbar\n\tldstub\t[%%sp-1], %%g0"
   [(set_attr "type" "multi")
    (set_attr "length" "2")])
 
-;; membar #StoreStore | #LoadStore | #StoreLoad | #LoadLoad
 (define_insn "*membar"
   [(set (match_operand:BLK 0 "" "")
-	(unspec:BLK [(match_dup 0)] UNSPEC_MEMBAR))]
+	(unspec:BLK [(match_dup 0) (match_operand:SI 1 "const_int_operand")]
+		    UNSPEC_MEMBAR))]
   "TARGET_V9"
-  "membar\t15"
+  "membar\t%1"
   [(set_attr "type" "multi")])
 
+;;;;;;;;
+
 (define_expand "sync_compare_and_swap<mode>"
   [(match_operand:I12MODE 0 "register_operand" "")
    (match_operand:I12MODE 1 "memory_operand" "")
-- 
1.7.4.4



More information about the Gcc-patches mailing list