From patchwork Thu Nov 17 20:37:43 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 126311 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id F13E8B7258 for ; Fri, 18 Nov 2011 07:38:33 +1100 (EST) Received: (qmail 22541 invoked by alias); 17 Nov 2011 20:38:21 -0000 Received: (qmail 22270 invoked by uid 22791); 17 Nov 2011 20:38:19 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_EG, TW_UV, TW_VW X-Spam-Check-By: sourceware.org Received: from mail-iy0-f175.google.com (HELO mail-iy0-f175.google.com) (209.85.210.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 17 Nov 2011 20:38:02 +0000 Received: by iahk25 with SMTP id k25so2904696iah.20 for ; Thu, 17 Nov 2011 12:38:02 -0800 (PST) Received: by 10.42.96.132 with SMTP id j4mr98995icn.50.1321562281475; Thu, 17 Nov 2011 12:38:01 -0800 (PST) Received: from localhost.localdomain (dhcp184-48-96-88.wmr.hon.wayport.net. [184.48.96.88]) by mx.google.com with ESMTPS id eb23sm5755730ibb.2.2011.11.17.12.37.59 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 17 Nov 2011 12:38:00 -0800 (PST) From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: davem@davemloft.net, ebotcazou@libertysurf.fr Subject: [PATCH 3/5] sparc: Convert to atomic_compare_and_swap. Date: Thu, 17 Nov 2011 10:37:43 -1000 Message-Id: <1321562265-12743-4-git-send-email-rth@redhat.com> In-Reply-To: <1321562265-12743-1-git-send-email-rth@redhat.com> References: <1321562265-12743-1-git-send-email-rth@redhat.com> X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Aid the backend with mem_noofs_operand and a constraint to match. --- 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 | 56 ++++++++++++++------------------------- 5 files changed, 81 insertions(+), 42 deletions(-) diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md index 317602c..472490f 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 43d7168..c886b86 100644 --- a/gcc/config/sparc/predicates.md +++ b/gcc/config/sparc/predicates.md @@ -467,6 +467,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 fbb2ae8..153c061 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 2de6587..d75fc1a 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -10897,8 +10897,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); @@ -10923,7 +10924,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, @@ -10969,7 +10970,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); @@ -10977,6 +10980,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)); @@ -10995,6 +11000,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 7c151c1..d38a828 100644 --- a/gcc/config/sparc/sync.md +++ b/gcc/config/sparc/sync.md @@ -147,55 +147,37 @@ [(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" "")] +(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" { - 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" - [(parallel - [(set (match_operand:I48MODE 0 "register_operand" "") - (match_operand:I48MODE 1 "memory_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")] @@ -210,12 +192,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" "")