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