Commit 470b6e51 by Richard Henderson Committed by Richard Henderson

sparc: Convert to atomic_compare_and_swap.

        * config/sparc/constraints.md ("w"): New.
        * config/sparc/predicates.md (mem_noofs_operand): New.
        * config/sparc/sparc.c (sparc_expand_compare_and_swap_12): Make static.
        Generate the boolean result of the atomic_compare_exchange.
        (sparc_expand_compare_and_swap): New.
        * config/sparc/sync.md (atomic_compare_and_swap<I>): New.
        (atomic_compare_and_swap<I48MODE>_1): Rename from
        *sync_compare_and_swap<I48MODE>, use mem_noofs_operand.
        (*atomic_compare_and_swapdi_v8plus): Rename from
        *sync_compare_and_swapdi_v8plus, use mem_noofs_operand.
        (sync_compare_and_swap<I12MODE>): Remove.
        (sync_compare_and_swap<I48MODE>): Remove.

From-SVN: r181851
parent cfe8fee7
2011-11-30 Richard Henderson <rth@redhat.com>
* config/sparc/constraints.md ("w"): New.
* config/sparc/predicates.md (mem_noofs_operand): New.
* config/sparc/sparc.c (sparc_expand_compare_and_swap_12): Make static.
Generate the boolean result of the atomic_compare_exchange.
(sparc_expand_compare_and_swap): New.
* config/sparc/sync.md (atomic_compare_and_swap<I>): New.
(atomic_compare_and_swap<I48MODE>_1): Rename from
*sync_compare_and_swap<I48MODE>, use mem_noofs_operand.
(*atomic_compare_and_swapdi_v8plus): Rename from
*sync_compare_and_swapdi_v8plus, use mem_noofs_operand.
(sync_compare_and_swap<I12MODE>): Remove.
(sync_compare_and_swap<I48MODE>): Remove.
2011-11-30 Richard Henderson <rth@redhat.com>
* config/sparc/predicates.md (register_or_v9_zero_operand): New.
* config/sparc/sparc.md (UNSPEC_ATOMIC): New.
* config/sparc/sync.md (atomic_load<I>): New.
......@@ -19,7 +19,7 @@
;;; Unused letters:
;;; AB
;;; a jkl q tuvwxyz
;;; a jkl q tuv xyz
;; Register constraints
......@@ -44,6 +44,9 @@
(define_register_constraint "h" "(TARGET_V9 && TARGET_V8PLUS ? I64_REGS : NO_REGS)"
"64-bit global or out register in V8+ mode")
(define_memory_constraint "w"
"A memory with only a base register"
(match_operand 0 "mem_noofs_operand"))
;; Floating-point constant constraints
......
......@@ -471,6 +471,10 @@
(match_test "call_address_operand (XEXP (op, 0), mode)")))
(define_predicate "mem_noofs_operand"
(and (match_code "mem")
(match_code "reg" "0")))
;; Predicates for operators.
;; Return true if OP is a comparison operator. This allows the use of
......
......@@ -104,7 +104,7 @@ extern int v9_regcmp_p (enum rtx_code);
32 bits of REG are 0 before INSN. */
extern int sparc_check_64 (rtx, rtx);
extern rtx gen_df_reg (rtx, int);
extern void sparc_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
extern void sparc_expand_compare_and_swap (rtx op[]);
extern void sparc_expand_vector_init (rtx, rtx);
extern void sparc_expand_vec_perm_bmask(enum machine_mode, rtx);
extern bool sparc_expand_conditional_move (enum machine_mode, rtx *);
......
......@@ -10899,8 +10899,9 @@ sparc_emit_membar_for_model (enum memmodel model,
/* 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. */
void
sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
static void
sparc_expand_compare_and_swap_12 (rtx bool_result, rtx result, rtx mem,
rtx oldval, rtx newval)
{
rtx addr1 = force_reg (Pmode, XEXP (mem, 0));
rtx addr = gen_reg_rtx (Pmode);
......@@ -10925,7 +10926,7 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER);
MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
val = force_reg (SImode, memsi);
val = copy_to_reg (memsi);
emit_insn (gen_rtx_SET (VOIDmode, off,
gen_rtx_XOR (SImode, off,
......@@ -10971,7 +10972,9 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
emit_insn (gen_rtx_SET (VOIDmode, newvalue,
gen_rtx_IOR (SImode, newv, val)));
emit_insn (gen_sync_compare_and_swapsi (res, memsi, oldvalue, newvalue));
emit_move_insn (bool_result, const1_rtx);
emit_insn (gen_atomic_compare_and_swapsi_1 (res, memsi, oldvalue, newvalue));
emit_cmp_and_jump_insns (res, oldvalue, EQ, NULL, SImode, 0, end_label);
......@@ -10979,6 +10982,8 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
res)));
emit_move_insn (bool_result, const0_rtx);
cc = gen_compare_reg_1 (NE, resv, val);
emit_insn (gen_rtx_SET (VOIDmode, val, resv));
......@@ -10997,6 +11002,49 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
}
/* Expand code to perform a compare-and-swap. */
void
sparc_expand_compare_and_swap (rtx operands[])
{
rtx bval, retval, mem, oldval, newval;
enum machine_mode mode;
enum memmodel model;
bval = operands[0];
retval = operands[1];
mem = operands[2];
oldval = operands[3];
newval = operands[4];
model = (enum memmodel) INTVAL (operands[6]);
mode = GET_MODE (mem);
sparc_emit_membar_for_model (model, 3, 1);
if (reg_overlap_mentioned_p (retval, oldval))
oldval = copy_to_reg (oldval);
if (mode == QImode || mode == HImode)
sparc_expand_compare_and_swap_12 (bval, retval, mem, oldval, newval);
else
{
rtx (*gen) (rtx, rtx, rtx, rtx);
rtx x;
if (mode == SImode)
gen = gen_atomic_compare_and_swapsi_1;
else
gen = gen_atomic_compare_and_swapdi_1;
emit_insn (gen (retval, mem, oldval, newval));
x = emit_store_flag (bval, EQ, retval, oldval, mode, 1, 1);
if (x != bval)
convert_move (bval, x, 1);
}
sparc_emit_membar_for_model (model, 3, 2);
}
void
sparc_expand_vec_perm_bmask (enum machine_mode vmode, rtx sel)
{
......
......@@ -161,55 +161,49 @@
[(set_attr "type" "store,store,fpstore")
(set_attr "cpu_feature" "v9,*,*")])
;;;;;;;;
(define_expand "sync_compare_and_swap<mode>"
[(match_operand:I12MODE 0 "register_operand" "")
(match_operand:I12MODE 1 "memory_operand" "")
(match_operand:I12MODE 2 "register_operand" "")
(match_operand:I12MODE 3 "register_operand" "")]
"TARGET_V9"
(define_expand "atomic_compare_and_swap<mode>"
[(match_operand:SI 0 "register_operand" "") ;; bool output
(match_operand:I 1 "register_operand" "") ;; val output
(match_operand:I 2 "mem_noofs_operand" "") ;; memory
(match_operand:I 3 "register_operand" "") ;; expected
(match_operand:I 4 "register_operand" "") ;; desired
(match_operand:SI 5 "const_int_operand" "") ;; is_weak
(match_operand:SI 6 "const_int_operand" "") ;; mod_s
(match_operand:SI 7 "const_int_operand" "")] ;; mod_f
"TARGET_V9 && (<MODE>mode != DImode || TARGET_ARCH64 || TARGET_V8PLUS)"
{
sparc_expand_compare_and_swap_12 (operands[0], operands[1],
operands[2], operands[3]);
sparc_expand_compare_and_swap (operands);
DONE;
})
(define_expand "sync_compare_and_swap<mode>"
(define_expand "atomic_compare_and_swap<mode>_1"
[(parallel
[(set (match_operand:I48MODE 0 "register_operand" "")
(match_operand:I48MODE 1 "memory_operand" ""))
(match_operand:I48MODE 1 "mem_noofs_operand" ""))
(set (match_dup 1)
(unspec_volatile:I48MODE
[(match_operand:I48MODE 2 "register_operand" "")
(match_operand:I48MODE 3 "register_operand" "")]
UNSPECV_CAS))])]
"TARGET_V9"
{
if (!REG_P (XEXP (operands[1], 0)))
{
rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
operands[1] = replace_equiv_address (operands[1], addr);
}
emit_insn (gen_memory_barrier ());
})
"")
(define_insn "*sync_compare_and_swap<mode>"
(define_insn "*atomic_compare_and_swap<mode>_1"
[(set (match_operand:I48MODE 0 "register_operand" "=r")
(mem:I48MODE (match_operand 1 "register_operand" "r")))
(set (mem:I48MODE (match_dup 1))
(match_operand:I48MODE 1 "mem_noofs_operand" "+w"))
(set (match_dup 1)
(unspec_volatile:I48MODE
[(match_operand:I48MODE 2 "register_operand" "r")
(match_operand:I48MODE 3 "register_operand" "0")]
UNSPECV_CAS))]
"TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
"cas<modesuffix>\t[%1], %2, %0"
"cas<modesuffix>\t%1, %2, %0"
[(set_attr "type" "multi")])
(define_insn "*sync_compare_and_swapdi_v8plus"
(define_insn "*atomic_compare_and_swapdi_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h")
(mem:DI (match_operand 1 "register_operand" "r")))
(set (mem:DI (match_dup 1))
(match_operand:DI 1 "mem_noofs_operand" "+w"))
(set (match_dup 1)
(unspec_volatile:DI
[(match_operand:DI 2 "register_operand" "h")
(match_operand:DI 3 "register_operand" "0")]
......@@ -224,12 +218,14 @@
output_asm_insn ("srl\t%L2, 0, %L2", operands);
output_asm_insn ("sllx\t%H2, 32, %H3", operands);
output_asm_insn ("or\t%L2, %H3, %H3", operands);
output_asm_insn ("casx\t[%1], %H3, %L3", operands);
output_asm_insn ("casx\t%1, %H3, %L3", operands);
return "srlx\t%L3, 32, %H3";
}
[(set_attr "type" "multi")
(set_attr "length" "8")])
;;;;;;;;
(define_expand "sync_lock_test_and_set<mode>"
[(match_operand:I12MODE 0 "register_operand" "")
(match_operand:I12MODE 1 "memory_operand" "")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment