--- gcc/config/sparc/sparc-opts.h | 10 ++++++++ gcc/config/sparc/sparc.c | 48 ++++++++++++++++++++++++++++++++++++++++- gcc/config/sparc/sparc.opt | 22 ++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletions(-)
diff --git a/gcc/config/sparc/sparc-opts.h b/gcc/config/sparc/sparc-opts.h index 266cb14..34a1955 100644 --- a/gcc/config/sparc/sparc-opts.h +++ b/gcc/config/sparc/sparc-opts.h @@ -47,4 +47,14 @@ enum processor_type { PROCESSOR_NATIVE }; +/* Sparc system memory model. See Appendix D in the SparcV9 manual + for formal specification, and Appendix J for more discussion. */ +enum memory_order { + MO_DEFAULT, /* Uninitialized. */ + MO_RMO, /* Relaxed Memory Order. */ + MO_PSO, /* Partial Store Order. */ + MO_TSO, /* Total Store Order. */ + MO_SC /* Sequential Consistency. */ +}; + #endif diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index d75fc1a..788063d 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -1160,6 +1160,17 @@ sparc_option_override (void) gcc_unreachable (); }; + if (sparc_memory_order == MO_DEFAULT) + { + /* Choose the most relaxed model for the processor. */ + if (TARGET_V9) + sparc_memory_order = MO_RMO; + else if (TARGET_V8) + sparc_memory_order = MO_PSO; + else + sparc_memory_order = MO_SC; + } + #ifdef TARGET_DEFAULT_LONG_DOUBLE_128 if (!(target_flags_explicit & MASK_LONG_DOUBLE_128)) target_flags |= MASK_LONG_DOUBLE_128; @@ -10863,7 +10874,39 @@ sparc_emit_membar_for_model (enum memmodel model, const int LoadStore = 4; const int StoreStore = 8; - int mm = 0; + int mm = 0, implied = 0; + + switch (sparc_memory_order) + { + case MO_SC: + /* Sequential Consistency. All memory transactions are immediately + visible in sequential execution order. No barriers needed. */ + return; + + case MO_TSO: + /* Total Store Ordering: all memory transactions with store semantics + are followed by an implied StoreStore. */ + implied |= StoreStore; + /* FALLTHRU */ + + case MO_PSO: + /* Partial Store Ordering: all memory transactions with load semantics + are followed by an implied LoadLoad | LoadStore. */ + implied |= LoadLoad | LoadStore; + + /* If we're not looking for a raw barrer (before+after), then atomic + operations get the benefit of being both load and store. */ + if (load_store == 3 && before_after == 2) + implied |= StoreLoad | StoreStore; + /* FALLTHRU */ + + case MO_RMO: + /* Relaxed Memory Ordering: no implicit bits. */ + break; + + default: + gcc_unreachable (); + } if (before_after & 1) { @@ -10890,6 +10933,9 @@ sparc_emit_membar_for_model (enum memmodel model, } } + /* Remove the bits implied by the system memory model. */ + mm &= ~implied; + if (mm) emit_insn (gen_membar (GEN_INT (mm))); } diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index cb807fd..e913612 100644 --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -215,3 +215,25 @@ Mask(V9) Mask(DEPRECATED_V8_INSNS) ;; Generate code that uses the V8 instructions deprecated ;; in the V9 architecture. + +mmmodel= +Target RejectNegative Joined Var(sparc_memory_order) Enum(sparc_memory_order) Init(MO_DEFAULT) +Specify the memory model in effect for the program. + +Enum +Name(sparc_memory_order) Type(enum memory_order) + +EnumValue +Enum(sparc_memory_order) String(default) Value(MO_DEFAULT) + +EnumValue +Enum(sparc_memory_order) String(rmo) Value(MO_RMO) + +EnumValue +Enum(sparc_memory_order) String(pso) Value(MO_PSO) + +EnumValue +Enum(sparc_memory_order) String(tso) Value(MO_TSO) + +EnumValue +Enum(sparc_memory_order) String(sc) Value(MO_SC) -- 1.7.4.4