From patchwork Tue Apr 9 01:56:04 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Miller X-Patchwork-Id: 234931 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 775F92C009E for ; Tue, 9 Apr 2013 11:56:18 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :message-id:to:cc:subject:from:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=saql1u0WwCwa+aa7 04YHQ4f/dDtbjpisHOOVKn3A+fAXRMwJLroNlbFAE2SZjPkdKUe1jvj+jmyukxLd zIOob3Nx/ftMljXnTpXi0GR8i/Mr//rK4+rTMSJueU6VUmG+IPfSFdd+WKetESwt DVCDav99Sj44JgHpmWHqEnN9iNM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :message-id:to:cc:subject:from:mime-version:content-type :content-transfer-encoding; s=default; bh=e08EN2hjeV7UIWL4cujg2z RZQ4A=; b=LaeonCOr6rlvYs6YGYPjoE17+x65abCfDPqTFbF50DX7FwFyNlFkM0 Bm4/8anIWxXk/EqIhyhI+EsXdnJZHM6pMbw359MMHGHG0fF6Usvf3/IkAKMj8szV csToilOIFEtBSk6jyVrrOfGVpWDt1FlTUWmEfyvDzjEsOqmJxDgrw= Received: (qmail 6462 invoked by alias); 9 Apr 2013 01:56:11 -0000 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 Received: (qmail 6353 invoked by uid 89); 9 Apr 2013 01:56:11 -0000 X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, TW_QS, TW_XF autolearn=no version=3.3.1 Received: from shards.monkeyblade.net (HELO shards.monkeyblade.net) (149.20.54.216) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Tue, 09 Apr 2013 01:56:09 +0000 Received: from localhost (cpe-66-108-118-205.nyc.res.rr.com [66.108.118.205]) (Authenticated sender: davem-davemloft) by shards.monkeyblade.net (Postfix) with ESMTPSA id 03B895839B7; Mon, 8 Apr 2013 18:56:06 -0700 (PDT) Date: Mon, 08 Apr 2013 21:56:04 -0400 (EDT) Message-Id: <20130408.215604.2064843235368371573.davem@davemloft.net> To: gcc-patches@gcc.gnu.org CC: ebotcazou@adacore.com Subject: [PATCH] Improve cstore code generation on 64-bit sparc. From: David Miller Mime-Version: 1.0 One major suboptimal area of the sparc back end is cstore generation on 64-bit. Due to the way arguments and return values of functions must be promoted, the ideal mode for cstore's result would be DImode. But this hasn't been done because of a fundamental limitation of the cstore patterns. They require a fixed mode be used for the boolean result value. I've decided to work around this by building a target hook which specifies the type to use for conditional store results, and then I use a special predicate for operans 0 in the cstore expanders so that they still match even when we use DImode. The default version of the target hook just does what it does now, so no other target should be impacted by this at all. Regstrapped on 32-bit sparc-linux-gnu and I've run the testsuite with "-m64" to validate the 64-bit side. Any major objections? gcc/ * target.def (cstore_mode): New hook. * target.h: Include insn-codes.h * targhooks.c: Likewise. (default_cstore_mode): New function. * targhooks.h: Declare it. * doc/tm.texi.in: New hook slot for TARGET_CSTORE_MODE. * doc/tm.texi: Rebuild. * expmed.c (emit_cstore): Obtain cstore boolean result mode using target hook, rather than inspecting the insn_data. * config/sparc/sparc.c (sparc_cstore_mode): New function. (TARGET_CSTORE_MODE): Redefine. (emit_scc_insn): When TARGET_ARCH64, emit new 64-bit boolean result patterns. * config/sparc/predicates.md (cstore_result_operand): New special predicate. * config/sparc/sparc.md (cstoresi4, cstoredi4, cstore4): Use it for operand 0. (*seqsi_special): Rewrite using 'P' mode iterator on operand 0. (*snesi_special): Likewise. (*snesi_zero): Likewise. (*seqsi_zero): Likewise. (*sltu_insn): Likewise. (*sgeu_insn): Likewise. (*seqdi_special): Make operand 0 and comparison operation be of DImode. (*snedi_special): Likewise. (*snedi_special_vis3): Likewise. (*neg_snesi_zero): Rename to *neg_snesisi_zero. (*neg_snesi_sign_extend): Rename to *neg_snesidi_zero. (*snesi_zero_extend): Delete, covered by 'P' mode iterator. (*neg_seqsi_zero): Rename to *neg_seqsisi_zero. (*neg_seqsi_sign_extend): Rename to *neg_seqsidi_zero. (*seqsi_zero_extend): Delete, covered by 'P' mode iterator. (*sltu_extend_sp64): Likewise. (*neg_sltu_insn): Rename to *neg_sltusi_insn. (*neg_sltu_extend_sp64): Rename to *neg_sltudi_insn. (*sgeu_extend_sp64): Delete, covered by 'P' mode iterator. (*neg_sgeu_insn): Rename to *neg_sgeusi_insn. (*neg_sgeu_extend_sp64): Rename to *neg_sgeudi_insn. gcc/testsuite/ * gcc.target/sparc/setcc-4.c: New test. * gcc.target/sparc/setcc-5.c: New test. --- gcc/config/sparc/predicates.md | 5 ++ gcc/config/sparc/sparc.c | 23 +++++- gcc/config/sparc/sparc.md | 137 ++++++++++--------------------- gcc/doc/tm.texi | 4 + gcc/doc/tm.texi.in | 2 + gcc/expmed.c | 2 +- gcc/target.def | 10 +++ gcc/target.h | 1 + gcc/targhooks.c | 9 ++ gcc/targhooks.h | 1 + gcc/testsuite/gcc.target/sparc/setcc-4.c | 44 ++++++++++ gcc/testsuite/gcc.target/sparc/setcc-5.c | 42 ++++++++++ 12 files changed, 183 insertions(+), 97 deletions(-) create mode 100644 gcc/testsuite/gcc.target/sparc/setcc-4.c create mode 100644 gcc/testsuite/gcc.target/sparc/setcc-5.c diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md index b8524e5..073bce2 100644 --- a/gcc/config/sparc/predicates.md +++ b/gcc/config/sparc/predicates.md @@ -265,6 +265,11 @@ (ior (match_test "register_operand (op, SImode)") (match_test "TARGET_ARCH64 && register_operand (op, DImode)"))) +;; Return true if OP is an integer register of the appropriate mode +;; for a cstore result. +(define_special_predicate "cstore_result_operand" + (match_test "register_operand (op, TARGET_ARCH64 ? DImode : SImode)")) + ;; Return true if OP is a floating point condition code register. (define_predicate "fcc_register_operand" (match_code "reg") diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 3e98325..4a73c73 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -597,6 +597,7 @@ static void sparc_print_operand_address (FILE *, rtx); static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t, enum machine_mode, secondary_reload_info *); +static enum machine_mode sparc_cstore_mode (enum insn_code icode); #ifdef SUBTARGET_ATTRIBUTE_TABLE /* Table of valid machine attributes. */ @@ -802,6 +803,9 @@ char sparc_hard_reg_printed[8]; #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 0xff +#undef TARGET_CSTORE_MODE +#define TARGET_CSTORE_MODE sparc_cstore_mode + struct gcc_target targetm = TARGET_INITIALIZER; static void @@ -2572,7 +2576,11 @@ emit_scc_insn (rtx operands[]) { if (GET_MODE (x) == SImode) { - rtx pat = gen_seqsi_special (operands[0], x, y); + rtx pat; + if (TARGET_ARCH64) + pat = gen_seqsidi_special (operands[0], x, y); + else + pat = gen_seqsisi_special (operands[0], x, y); emit_insn (pat); return true; } @@ -2588,7 +2596,11 @@ emit_scc_insn (rtx operands[]) { if (GET_MODE (x) == SImode) { - rtx pat = gen_snesi_special (operands[0], x, y); + rtx pat; + if (TARGET_ARCH64) + pat = gen_snesidi_special (operands[0], x, y); + else + pat = gen_snesisi_special (operands[0], x, y); emit_insn (pat); return true; } @@ -2631,7 +2643,7 @@ emit_scc_insn (rtx operands[]) || (!TARGET_VIS3 && code == GEU)) { emit_insn (gen_rtx_SET (VOIDmode, operands[0], - gen_rtx_fmt_ee (code, SImode, + gen_rtx_fmt_ee (code, GET_MODE (operands[0]), gen_compare_reg_1 (code, x, y), const0_rtx))); return true; @@ -12104,4 +12116,9 @@ sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2) return true; } +static enum machine_mode sparc_cstore_mode (enum insn_code icode ATTRIBUTE_UNUSED) +{ + return (TARGET_ARCH64 ? DImode : SImode); +} + #include "gt-sparc.h" diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 933991c..936873c 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -615,11 +615,14 @@ ;; Next come the scc insns. +;; Note that the boolean result (operand 0) takes on DImode +;; (not SImode) when TARGET_ARCH64. + (define_expand "cstoresi4" [(use (match_operator 1 "comparison_operator" [(match_operand:SI 2 "compare_operand" "") (match_operand:SI 3 "arith_operand" "")])) - (clobber (match_operand:SI 0 "register_operand"))] + (clobber (match_operand:SI 0 "cstore_result_operand"))] "" { if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx) @@ -631,7 +634,7 @@ [(use (match_operator 1 "comparison_operator" [(match_operand:DI 2 "compare_operand" "") (match_operand:DI 3 "arith_operand" "")])) - (clobber (match_operand:SI 0 "register_operand"))] + (clobber (match_operand:SI 0 "cstore_result_operand"))] "TARGET_ARCH64" { if (GET_CODE (operands[2]) == ZERO_EXTRACT && operands[3] != const0_rtx) @@ -643,7 +646,7 @@ [(use (match_operator 1 "comparison_operator" [(match_operand:F 2 "register_operand" "") (match_operand:F 3 "register_operand" "")])) - (clobber (match_operand:SI 0 "register_operand"))] + (clobber (match_operand:SI 0 "cstore_result_operand"))] "TARGET_FPU" { if (emit_scc_insn (operands)) DONE; else FAIL; }) @@ -652,12 +655,12 @@ ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they ;; generate addcc/subcc instructions. -(define_expand "seqsi_special" +(define_expand "seqsi_special" [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" ""))) - (parallel [(set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_dup 3) (const_int 0))) + (parallel [(set (match_operand:P 0 "register_operand" "") + (eq:P (match_dup 3) (const_int 0))) (clobber (reg:CC CC_REG))])] "" { operands[3] = gen_reg_rtx (SImode); }) @@ -666,17 +669,17 @@ [(set (match_dup 3) (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:SI 0 "register_operand" "") - (eq:SI (match_dup 3) (const_int 0)))] + (set (match_operand:DI 0 "register_operand" "") + (eq:DI (match_dup 3) (const_int 0)))] "TARGET_ARCH64" { operands[3] = gen_reg_rtx (DImode); }) -(define_expand "snesi_special" +(define_expand "snesi_special" [(set (match_dup 3) (xor:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" ""))) - (parallel [(set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 3) (const_int 0))) + (parallel [(set (match_operand:P 0 "register_operand" "") + (ne:P (match_dup 3) (const_int 0))) (clobber (reg:CC CC_REG))])] "" { operands[3] = gen_reg_rtx (SImode); }) @@ -685,8 +688,8 @@ [(set (match_dup 3) (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) - (set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 3) (const_int 0)))] + (set (match_operand:DI 0 "register_operand" "") + (ne:DI (match_dup 3) (const_int 0)))] "TARGET_ARCH64 && ! TARGET_VIS3" { operands[3] = gen_reg_rtx (DImode); }) @@ -694,8 +697,8 @@ [(set (match_dup 3) (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) - (parallel [(set (match_operand:SI 0 "register_operand" "") - (ne:SI (match_dup 3) (const_int 0))) + (parallel [(set (match_operand:DI 0 "register_operand" "") + (ne:DI (match_dup 3) (const_int 0))) (clobber (reg:CCX CC_REG))])] "TARGET_ARCH64 && TARGET_VIS3" { operands[3] = gen_reg_rtx (DImode); }) @@ -708,9 +711,9 @@ ;; them to always use the splits below so the results can be ;; scheduled. -(define_insn_and_split "*snesi_zero" - [(set (match_operand:SI 0 "register_operand" "=r") - (ne:SI (match_operand:SI 1 "register_operand" "r") +(define_insn_and_split "*snesi_zero" + [(set (match_operand:P 0 "register_operand" "=r") + (ne:P (match_operand:SI 1 "register_operand" "r") (const_int 0))) (clobber (reg:CC CC_REG))] "" @@ -718,11 +721,11 @@ "" [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1)) (const_int 0))) - (set (match_dup 0) (ltu:SI (reg:CC CC_REG) (const_int 0)))] + (set (match_dup 0) (ltu:P (reg:CC CC_REG) (const_int 0)))] "" [(set_attr "length" "2")]) -(define_insn_and_split "*neg_snesi_zero" +(define_insn_and_split "*neg_snesisi_zero" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (ne:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))) @@ -736,35 +739,16 @@ "" [(set_attr "length" "2")]) -(define_insn_and_split "*snesi_zero_extend" +(define_insn_and_split "*neg_snesidi_zero" [(set (match_operand:DI 0 "register_operand" "=r") - (ne:DI (match_operand:SI 1 "register_operand" "r") - (const_int 0))) + (neg:DI (ne:DI (match_operand:SI 1 "register_operand" "r") + (const_int 0)))) (clobber (reg:CC CC_REG))] "TARGET_ARCH64" "#" - "&& 1" - [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0) - (match_dup 1)) - (const_int 0))) - (set (match_dup 0) (zero_extend:DI (plus:SI (plus:SI (const_int 0) - (const_int 0)) - (ltu:SI (reg:CC_NOOV CC_REG) - (const_int 0)))))] "" - [(set_attr "length" "2")]) - -(define_insn_and_split "*neg_snesi_sign_extend" - [(set (match_operand:DI 0 "register_operand" "=r") - (neg:DI (ne:DI (match_operand:SI 1 "register_operand" "r") - (const_int 0)))) - (clobber (reg:CC CC_REG))] - "TARGET_ARCH64" - "#" - "&& 1" - [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0) - (match_dup 1)) - (const_int 0))) + [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1)) + (const_int 0))) (set (match_dup 0) (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0)))))] "" @@ -843,9 +827,9 @@ "" [(set_attr "length" "2")]) -(define_insn_and_split "*seqsi_zero" - [(set (match_operand:SI 0 "register_operand" "=r") - (eq:SI (match_operand:SI 1 "register_operand" "r") +(define_insn_and_split "*seqsi_zero" + [(set (match_operand:P 0 "register_operand" "=r") + (eq:P (match_operand:SI 1 "register_operand" "r") (const_int 0))) (clobber (reg:CC CC_REG))] "" @@ -853,11 +837,11 @@ "" [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1)) (const_int 0))) - (set (match_dup 0) (geu:SI (reg:CC CC_REG) (const_int 0)))] + (set (match_dup 0) (geu:P (reg:CC CC_REG) (const_int 0)))] "" [(set_attr "length" "2")]) -(define_insn_and_split "*neg_seqsi_zero" +(define_insn_and_split "*neg_seqsisi_zero" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (eq:SI (match_operand:SI 1 "register_operand" "r") (const_int 0)))) @@ -871,25 +855,7 @@ "" [(set_attr "length" "2")]) -(define_insn_and_split "*seqsi_zero_extend" - [(set (match_operand:DI 0 "register_operand" "=r") - (eq:DI (match_operand:SI 1 "register_operand" "r") - (const_int 0))) - (clobber (reg:CC CC_REG))] - "TARGET_ARCH64" - "#" - "&& 1" - [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0) - (match_dup 1)) - (const_int 0))) - (set (match_dup 0) (zero_extend:DI (minus:SI (minus:SI (const_int 0) - (const_int -1)) - (ltu:SI (reg:CC_NOOV CC_REG) - (const_int 0)))))] - "" - [(set_attr "length" "2")]) - -(define_insn_and_split "*neg_seqsi_sign_extend" +(define_insn_and_split "*neg_seqsidi_zero" [(set (match_operand:DI 0 "register_operand" "=r") (neg:DI (eq:DI (match_operand:SI 1 "register_operand" "r") (const_int 0)))) @@ -1021,9 +987,9 @@ ;; ??? The addx/subx insns use the 32 bit carry flag so there are no DImode ;; versions for v9. -(define_insn "*sltu_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (ltu:SI (reg:CC CC_REG) (const_int 0)))] +(define_insn "*sltu_insn" + [(set (match_operand:P 0 "register_operand" "=r") + (ltu:P (reg:CC CC_REG) (const_int 0)))] "" "addx\t%%g0, 0, %0" [(set_attr "type" "ialuX")]) @@ -1042,28 +1008,20 @@ "addxc\t%%g0, %%g0, %0" [(set_attr "type" "ialuX")]) -(define_insn "*sltu_extend_sp64" - [(set (match_operand:DI 0 "register_operand" "=r") - (ltu:DI (reg:CC CC_REG) (const_int 0)))] - "TARGET_ARCH64" - "addx\t%%g0, 0, %0" - [(set_attr "type" "ialuX")]) - -(define_insn "*neg_sltu_insn" +(define_insn "*neg_sltusi_insn" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0))))] "" "subx\t%%g0, 0, %0" [(set_attr "type" "ialuX")]) -(define_insn "*neg_sltu_extend_sp64" +(define_insn "*neg_sltudi_insn" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0)))))] "TARGET_ARCH64" "subx\t%%g0, 0, %0" [(set_attr "type" "ialuX")]) -;; ??? Combine should canonicalize these next two to the same pattern. (define_insn "*neg_sltu_minus_x" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0))) @@ -1080,28 +1038,21 @@ "subx\t%%g0, %1, %0" [(set_attr "type" "ialuX")]) -(define_insn "*sgeu_insn" - [(set (match_operand:SI 0 "register_operand" "=r") - (geu:SI (reg:CC CC_REG) (const_int 0)))] +(define_insn "*sgeu_insn" + [(set (match_operand:P 0 "register_operand" "=r") + (geu:P (reg:CC CC_REG) (const_int 0)))] "" "subx\t%%g0, -1, %0" [(set_attr "type" "ialuX")]) -(define_insn "*sgeu_extend_sp64" - [(set (match_operand:DI 0 "register_operand" "=r") - (geu:DI (reg:CC CC_REG) (const_int 0)))] - "TARGET_ARCH64" - "subx\t%%g0, -1, %0" - [(set_attr "type" "ialuX")]) - -(define_insn "*neg_sgeu_insn" +(define_insn "*neg_sgeusi_insn" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0))))] "" "addx\t%%g0, -1, %0" [(set_attr "type" "ialuX")]) -(define_insn "*neg_sgeu_extend_sp64" +(define_insn "*neg_sgeudi_insn" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0)))))] "TARGET_ARCH64" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 6395b4b..f6c59f9 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2905,6 +2905,10 @@ A target hook which returns true if an address with the same structure can have This hook defines a class of registers which could be used for spilling pseudos of the given mode and class, or @code{NO_REGS} if only memory should be used. Not defining this hook is equivalent to returning @code{NO_REGS} for all inputs. @end deftypefn +@deftypefn {Target Hook} {enum machine_mode} TARGET_CSTORE_MODE (enum insn_code @var{icode}) +This hook defines the machine mode to use for the boolean result of conditional store patterns. The ICODE argument is the instruction code for the cstore being performed. Not definiting this hook is the same as accepting the mode encoded into operand 0 of the cstore expander patterns. +@end deftypefn + @node Old Constraints @section Obsolete Macros for Defining Constraints @cindex defining constraints, obsolete method diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 91a756c..2d4b98a 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -2873,6 +2873,8 @@ as below: @hook TARGET_SPILL_CLASS +@hook TARGET_CSTORE_MODE + @node Old Constraints @section Obsolete Macros for Defining Constraints @cindex defining constraints, obsolete method diff --git a/gcc/expmed.c b/gcc/expmed.c index d66c6e6..3c3a179 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -5081,7 +5081,7 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code, { struct expand_operand ops[4]; rtx op0, last, comparison, subtarget; - enum machine_mode result_mode = insn_data[(int) icode].operand[0].mode; + enum machine_mode result_mode = targetm.cstore_mode (icode); last = get_last_insn (); x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp); diff --git a/gcc/target.def b/gcc/target.def index 3ad5870..db74273 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2457,6 +2457,16 @@ DEFHOOK reg_class_t, (reg_class_t, enum machine_mode), NULL) +DEFHOOK +(cstore_mode, + "This hook defines the machine mode to use for the boolean result of\ + conditional store patterns. The ICODE argument is the instruction code\ + for the cstore being performed. Not definiting this hook is the same\ + as accepting the mode encoded into operand 0 of the cstore expander\ + patterns.", + enum machine_mode, (enum insn_code icode), + default_cstore_mode) + /* True if a structure, union or array with MODE containing FIELD should be accessed using BLKmode. */ DEFHOOK diff --git a/gcc/target.h b/gcc/target.h index c868118..405e292 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -49,6 +49,7 @@ #define GCC_TARGET_H #include "insn-modes.h" +#include "insn-codes.h" #ifdef ENABLE_CHECKING diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 85436ac..80b4aa6 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "tree-flow.h" #include "tree-ssa-alias.h" +#include "insn-codes.h" bool @@ -1537,6 +1538,14 @@ default_pch_valid_p (const void *data_p, size_t len) return NULL; } +/* Default version of cstore_mode. */ + +enum machine_mode +default_cstore_mode (enum insn_code icode) +{ + return insn_data[(int) icode].operand[0].mode; +} + /* Default version of member_type_forces_blk. */ bool diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 0837c09..ce10ebc 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -195,4 +195,5 @@ extern const char *default_pch_valid_p (const void *, size_t); extern void default_asm_output_ident_directive (const char*); +extern enum machine_mode default_cstore_mode (enum insn_code); extern bool default_member_type_forces_blk (const_tree, enum machine_mode); diff --git a/gcc/testsuite/gcc.target/sparc/setcc-4.c b/gcc/testsuite/gcc.target/sparc/setcc-4.c new file mode 100644 index 0000000..ffa4ee0 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/setcc-4.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O1 -mno-vis3" } */ + +long neq (long a, long b) +{ + return a != b; +} + +long eq (long a, long b) +{ + return a == b; +} + +long lt (unsigned long a, unsigned long b) +{ + return a < b; +} + +long leq (unsigned long a, unsigned long b) +{ + return a <= b; +} + +long geq (unsigned long a, unsigned long b) +{ + return a >= b; +} + +long gt (unsigned long a, unsigned long b) +{ + return a > b; +} + +/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ +/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ +/* { dg-final { scan-assembler-times "movrne\t%" 1 } } */ +/* { dg-final { scan-assembler-times "movre\t%" 1 } } */ +/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */ +/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */ +/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */ +/* { dg-final { scan-assembler-times "movgu\t%" 1 } } */ +/* { dg-final { scan-assembler-not "sra\t%" } } */ +/* { dg-final { scan-assembler-not "and\t%" } } */ diff --git a/gcc/testsuite/gcc.target/sparc/setcc-5.c b/gcc/testsuite/gcc.target/sparc/setcc-5.c new file mode 100644 index 0000000..58f1ee3 --- /dev/null +++ b/gcc/testsuite/gcc.target/sparc/setcc-5.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O1 -mvis3" } */ + +long neq (long a, long b) +{ + return a != b; +} + +long eq (long a, long b) +{ + return a == b; +} + +long lt (unsigned long a, unsigned long b) +{ + return a < b; +} + +long leq (unsigned long a, unsigned long b) +{ + return a <= b; +} + +long geq (unsigned long a, unsigned long b) +{ + return a >= b; +} + +long gt (unsigned long a, unsigned long b) +{ + return a > b; +} + +/* { dg-final { scan-assembler-times "xor\t%" 2 } } */ +/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */ +/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */ +/* { dg-final { scan-assembler-times "movre\t%" 1 } } */ +/* { dg-final { scan-assembler-times "movleu\t%" 1 } } */ +/* { dg-final { scan-assembler-times "movgeu\t%" 1 } } */ +/* { dg-final { scan-assembler-not "sra\t%" } } */ +/* { dg-final { scan-assembler-not "and\t%" } } */