From 66533357aed8bf38d40afbf4e6cd19d060cf2cd5 Mon Sep 17 00:00:00 2001 From: rth Date: Wed, 30 Nov 2011 15:53:45 +0000 Subject: [PATCH] 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): New. (atomic_compare_and_swap_1): Rename from *sync_compare_and_swap, use mem_noofs_operand. (*atomic_compare_and_swapdi_v8plus): Rename from *sync_compare_and_swapdi_v8plus, use mem_noofs_operand. (sync_compare_and_swap): Remove. (sync_compare_and_swap): Remove. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181851 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 15 +++++++++++ gcc/config/sparc/constraints.md | 5 +++- gcc/config/sparc/predicates.md | 4 +++ gcc/config/sparc/sparc-protos.h | 2 +- gcc/config/sparc/sparc.c | 56 ++++++++++++++++++++++++++++++++++++++--- gcc/config/sparc/sync.md | 52 ++++++++++++++++++-------------------- 6 files changed, 100 insertions(+), 34 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e48130eb0ee..62710969480 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,20 @@ 2011-11-30 Richard Henderson + * 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): New. + (atomic_compare_and_swap_1): Rename from + *sync_compare_and_swap, use mem_noofs_operand. + (*atomic_compare_and_swapdi_v8plus): Rename from + *sync_compare_and_swapdi_v8plus, use mem_noofs_operand. + (sync_compare_and_swap): Remove. + (sync_compare_and_swap): Remove. + +2011-11-30 Richard Henderson + * config/sparc/predicates.md (register_or_v9_zero_operand): New. * config/sparc/sparc.md (UNSPEC_ATOMIC): New. * config/sparc/sync.md (atomic_load): New. diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md index 317602c6e95..472490f2624 100644 --- a/gcc/config/sparc/constraints.md +++ b/gcc/config/sparc/constraints.md @@ -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 diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md index a9207beaadb..81e53206498 100644 --- a/gcc/config/sparc/predicates.md +++ b/gcc/config/sparc/predicates.md @@ -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 diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h index b292024bc87..52acc096ce3 100644 --- a/gcc/config/sparc/sparc-protos.h +++ b/gcc/config/sparc/sparc-protos.h @@ -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 *); diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index c5c48997d01..7db216a7c86 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -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) { diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md index e2f45968666..d7066b01a1c 100644 --- a/gcc/config/sparc/sync.md +++ b/gcc/config/sparc/sync.md @@ -161,55 +161,49 @@ [(set_attr "type" "store,store,fpstore") (set_attr "cpu_feature" "v9,*,*")]) -;;;;;;;; - -(define_expand "sync_compare_and_swap" - [(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" + [(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 != 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" +(define_expand "atomic_compare_and_swap_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" +(define_insn "*atomic_compare_and_swap_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 == SImode || TARGET_ARCH64)" - "cas\t[%1], %2, %0" + "cas\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" [(match_operand:I12MODE 0 "register_operand" "") (match_operand:I12MODE 1 "memory_operand" "") -- 2.11.0