From patchwork Thu Dec 1 00:44:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 128612 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 6437DB6F69 for ; Thu, 1 Dec 2011 11:45:26 +1100 (EST) Received: (qmail 24660 invoked by alias); 1 Dec 2011 00:45:17 -0000 Received: (qmail 24632 invoked by uid 22791); 1 Dec 2011 00:45:14 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-vx0-f175.google.com (HELO mail-vx0-f175.google.com) (209.85.220.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 01 Dec 2011 00:44:54 +0000 Received: by vcbfo13 with SMTP id fo13so1089553vcb.20 for ; Wed, 30 Nov 2011 16:44:53 -0800 (PST) Received: by 10.52.173.113 with SMTP id bj17mr4056126vdc.98.1322700293178; Wed, 30 Nov 2011 16:44:53 -0800 (PST) Received: from localhost.localdomain ([173.160.232.49]) by mx.google.com with ESMTPS id c7sm4463273vdh.12.2011.11.30.16.44.51 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 30 Nov 2011 16:44:52 -0800 (PST) From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: richard.earnshaw@arm.com, ramana.radhakrishnan@arm.com, joseph@codesourcery.com Subject: [PATCH 3/5] arm: Use CC_REGNUM as success output from compare-and-swap. Date: Wed, 30 Nov 2011 16:44:07 -0800 Message-Id: <1322700249-4693-4-git-send-email-rth@redhat.com> In-Reply-To: <1322700249-4693-1-git-send-email-rth@redhat.com> References: <1322700249-4693-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 --- gcc/config/arm/arm.c | 52 +++++++++++++++++++++------------------- gcc/config/arm/arm.md | 4 +- gcc/config/arm/sync.md | 62 +++++++++++++++++++++++++---------------------- 3 files changed, 62 insertions(+), 56 deletions(-) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index da99496..c02d294 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -24562,9 +24562,9 @@ emit_unlikely_jump (rtx insn) void arm_expand_compare_and_swap (rtx operands[]) { - rtx bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f; + rtx bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f, x; enum machine_mode mode; - rtx (*gen) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx); + rtx (*gen) (rtx, rtx, rtx, rtx, rtx, rtx, rtx); bval = operands[0]; rval = operands[1]; @@ -24612,10 +24612,17 @@ arm_expand_compare_and_swap (rtx operands[]) gcc_unreachable (); } - emit_insn (gen (bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f)); + emit_insn (gen (rval, mem, oldval, newval, is_weak, mod_s, mod_f)); if (mode == QImode || mode == HImode) emit_move_insn (operands[1], gen_lowpart (mode, rval)); + + /* In all cases, we arrange for success to be signaled by Z set. + This arrangement allows for the boolean result to be used directly + in a subsequent branch, post optimization. */ + x = gen_rtx_REG (CCmode, CC_REGNUM); + x = gen_rtx_EQ (SImode, x, const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, bval, x)); } /* Split a compare and swap pattern. It is IMPLEMENTATION DEFINED whether @@ -24627,24 +24634,22 @@ arm_expand_compare_and_swap (rtx operands[]) void arm_split_compare_and_swap (rtx operands[]) { - rtx bval, rval, mem, oldval, newval; + rtx rval, mem, oldval, newval, scratch; enum machine_mode mode; enum memmodel mod_s, mod_f; bool is_weak; rtx label1, label2, x, cond; - bval = operands[0]; - rval = operands[1]; - mem = operands[2]; - oldval = operands[3]; - newval = operands[4]; - is_weak = (operands[5] != const0_rtx); - mod_s = (enum memmodel) INTVAL (operands[6]); - mod_f = (enum memmodel) INTVAL (operands[7]); + rval = operands[0]; + mem = operands[1]; + oldval = operands[2]; + newval = operands[3]; + is_weak = (operands[4] != const0_rtx); + mod_s = (enum memmodel) INTVAL (operands[5]); + mod_f = (enum memmodel) INTVAL (operands[6]); + scratch = operands[7]; mode = GET_MODE (mem); - emit_move_insn (bval, const0_rtx); - arm_pre_atomic_barrier (mod_s); label1 = NULL_RTX; @@ -24664,20 +24669,17 @@ arm_split_compare_and_swap (rtx operands[]) x = gen_cbranchsi4 (x, rval, oldval, label2); emit_unlikely_jump (x); - arm_emit_store_exclusive (mode, bval, mem, newval); + arm_emit_store_exclusive (mode, scratch, mem, newval); - /* Thumb1 does not have LDREX, so we do not need to consider that - when it comes to computing the below. */ - gcc_assert (TARGET_32BIT); + /* Weak or strong, we want EQ to be true for success, so that we + match the flags that we got from the compare above. Thus we + prefer to use TEQ instead of TST here. */ + emit_insn (gen_xorsi3_compare0_scratch (scratch, const1_rtx)); - if (is_weak) - emit_insn (gen_xorsi3 (bval, bval, const1_rtx)); - else + if (!is_weak) { - emit_insn (gen_xorsi3_compare0 (bval, bval, const1_rtx)); - - cond = gen_rtx_REG (CC_NOOVmode, CC_REGNUM); - x = gen_rtx_EQ (VOIDmode, cond, const0_rtx); + cond = gen_rtx_REG (CCmode, CC_REGNUM); + x = gen_rtx_NE (VOIDmode, cond, const0_rtx); x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, gen_rtx_LABEL_REF (Pmode, label1), pc_rtx); emit_unlikely_jump (gen_rtx_SET (VOIDmode, pc_rtx, x)); diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index f006495..b01343c 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -3062,7 +3062,7 @@ [(set_attr "length" "2") (set_attr "conds" "set")]) -(define_insn "xorsi3_compare0" +(define_insn "*xorsi3_compare0" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "arm_rhs_operand" "rI")) @@ -3074,7 +3074,7 @@ [(set_attr "conds" "set")] ) -(define_insn "*xorsi3_compare0_scratch" +(define_insn "xorsi3_compare0_scratch" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r") (match_operand:SI 1 "arm_rhs_operand" "rI")) diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md index 72e7181..492fadc 100644 --- a/gcc/config/arm/sync.md +++ b/gcc/config/arm/sync.md @@ -85,20 +85,20 @@ }) (define_insn_and_split "atomic_compare_and_swap_1" - [(set (match_operand:SI 0 "s_register_operand" "=&r") ;; bool out - (unspec_volatile:SI [(const_int 0)] VUNSPEC_ATOMIC_CAS)) - (set (match_operand:SI 1 "s_register_operand" "=&r") ;; val out + [(set (reg:CC_Z CC_REGNUM) ;; bool out + (unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ATOMIC_CAS)) + (set (match_operand:SI 0 "s_register_operand" "=&r") ;; val out (zero_extend:SI - (match_operand:NARROW 2 "mem_noofs_operand" "+Ua"))) ;; memory - (set (match_dup 2) + (match_operand:NARROW 1 "mem_noofs_operand" "+Ua"))) ;; memory + (set (match_dup 1) (unspec_volatile:NARROW - [(match_operand:SI 3 "arm_add_operand" "rIL") ;; expected - (match_operand:NARROW 4 "s_register_operand" "r") ;; 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 + [(match_operand:SI 2 "arm_add_operand" "rIL") ;; expected + (match_operand:NARROW 3 "s_register_operand" "r") ;; desired + (match_operand:SI 4 "const_int_operand") ;; is_weak + (match_operand:SI 5 "const_int_operand") ;; mod_s + (match_operand:SI 6 "const_int_operand")] ;; mod_f VUNSPEC_ATOMIC_CAS)) - (clobber (reg:CC CC_REGNUM))] + (clobber (match_scratch:SI 7 "=&r"))] "" "#" "&& reload_completed" @@ -114,19 +114,19 @@ [(SI "rIL") (DI "rDi")]) (define_insn_and_split "atomic_compare_and_swap_1" - [(set (match_operand:SI 0 "s_register_operand" "=&r") ;; bool out - (unspec_volatile:SI [(const_int 0)] VUNSPEC_ATOMIC_CAS)) - (set (match_operand:SIDI 1 "s_register_operand" "=&r") ;; val out - (match_operand:SIDI 2 "mem_noofs_operand" "+Ua")) ;; memory - (set (match_dup 2) + [(set (reg:CC_Z CC_REGNUM) ;; bool out + (unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ATOMIC_CAS)) + (set (match_operand:SIDI 0 "s_register_operand" "=&r") ;; val out + (match_operand:SIDI 1 "mem_noofs_operand" "+Ua")) ;; memory + (set (match_dup 1) (unspec_volatile:SIDI - [(match_operand:SIDI 3 "" "") ;; expect - (match_operand:SIDI 4 "s_register_operand" "r") ;; 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 + [(match_operand:SIDI 2 "" "") ;; expect + (match_operand:SIDI 3 "s_register_operand" "r") ;; desired + (match_operand:SI 4 "const_int_operand") ;; is_weak + (match_operand:SI 5 "const_int_operand") ;; mod_s + (match_operand:SI 6 "const_int_operand")] ;; mod_f VUNSPEC_ATOMIC_CAS)) - (clobber (reg:CC CC_REGNUM))] + (clobber (match_scratch:SI 7 "=&r"))] "" "#" "&& reload_completed" @@ -360,7 +360,8 @@ [(match_operand:NARROW 1 "mem_noofs_operand" "Ua")] VUNSPEC_LL)))] "TARGET_HAVE_LDREXBH" - "ldrex\t%0, %C1") + "ldrex%?\t%0, %C1" + [(set_attr "predicable" "yes")]) (define_insn "arm_load_exclusivesi" [(set (match_operand:SI 0 "s_register_operand" "=r") @@ -368,7 +369,8 @@ [(match_operand:SI 1 "mem_noofs_operand" "Ua")] VUNSPEC_LL))] "TARGET_HAVE_LDREX" - "ldrex\t%0, %C1") + "ldrex%?\t%0, %C1" + [(set_attr "predicable" "yes")]) (define_insn "arm_load_exclusivedi" [(set (match_operand:DI 0 "s_register_operand" "=r") @@ -384,8 +386,9 @@ Note that the 1st register always gets the lowest word in memory. */ gcc_assert ((REGNO (target) & 1) == 0); operands[2] = gen_rtx_REG (SImode, REGNO (target) + 1); - return "ldrexd\t%0, %2, %C1"; - }) + return "ldrexd%?\t%0, %2, %C1"; + } + [(set_attr "predicable" "yes")]) (define_insn "arm_store_exclusive" [(set (match_operand:SI 0 "s_register_operand" "=&r") @@ -405,7 +408,8 @@ Note that the 1st register always gets the lowest word in memory. */ gcc_assert ((REGNO (value) & 1) == 0 || TARGET_THUMB2); operands[3] = gen_rtx_REG (SImode, REGNO (value) + 1); - return "strexd\t%0, %2, %3, %C1"; + return "strexd%?\t%0, %2, %3, %C1"; } - return "strex\t%0, %2, %C1"; - }) + return "strex%?\t%0, %2, %C1"; + } + [(set_attr "predicable" "yes")])