The zero_or_v7_operand hack could alternately be handled by forcing MO_SC for v7 in sparc_options_override. --- gcc/config/sparc/predicates.md | 4 ++++ gcc/config/sparc/sparc.c | 14 +++++++++----- gcc/config/sparc/sync.md | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md index c886b86..81e5320 100644 --- a/gcc/config/sparc/predicates.md +++ b/gcc/config/sparc/predicates.md @@ -111,6 +111,10 @@ (define_predicate "const_double_or_vector_operand" (match_code "const_double,const_vector")) +;; Return true if OP is Zero, or if the target is V7. +(define_predicate "zero_or_v7_operand" + (ior (match_test "op == const0_rtx") + (match_test "!TARGET_V8 && !TARGET_V9"))) ;; Predicates for symbolic constants. diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 788063d..22755cb 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -10880,8 +10880,9 @@ sparc_emit_membar_for_model (enum memmodel model, { case MO_SC: /* Sequential Consistency. All memory transactions are immediately - visible in sequential execution order. No barriers needed. */ - return; + visible in sequential execution order. */ + implied = LoadLoad | StoreLoad | LoadStore | StoreStore; + break; case MO_TSO: /* Total Store Ordering: all memory transactions with store semantics @@ -10894,8 +10895,9 @@ sparc_emit_membar_for_model (enum memmodel model, 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. */ + /* Atomic operations get the benefit of being both load and store. + Be careful to only apply this after the atomic op, and not to + apply this to raw barriers (before+after == 3). */ if (load_store == 3 && before_after == 2) implied |= StoreLoad | StoreStore; /* FALLTHRU */ @@ -10936,7 +10938,9 @@ sparc_emit_membar_for_model (enum memmodel model, /* Remove the bits implied by the system memory model. */ mm &= ~implied; - if (mm) + /* For raw barriers (before+after), always emit a barrier. + This will become a compile-time barrier if needed. */ + if (mm || before_after == 3) emit_insn (gen_membar (GEN_INT (mm))); } diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md index 821d59e..bdb10b7 100644 --- a/gcc/config/sparc/sync.md +++ b/gcc/config/sparc/sync.md @@ -44,6 +44,21 @@ MEM_VOLATILE_P (operands[1]) = 1; }) +;; A compiler-only memory barrier. Generic code, when checking for the +;; existance of various named patterns, uses asm("":::"memory") when we +;; don't need an actual instruction. Here, it's easiest to pretend that +;; membar 0 is such a barrier. Further, this gives us a nice hook to +;; ignore all such barriers on Sparc V7. + +(define_insn "*membar_empty" + [(set (match_operand:BLK 0 "" "") + (unspec:BLK [(match_dup 0) (match_operand:SI 1 "zero_or_v7_operand")] + UNSPEC_MEMBAR))] + "" + "" + [(set_attr "type" "multi") + (set_attr "length" "0")]) + ;; In V8, loads are blocking and ordered wrt earlier loads, i.e. every load ;; is virtually followed by a load barrier (membar #LoadStore | #LoadLoad). ;; In PSO, stbar orders the stores (membar #StoreStore). -- 1.7.4.4