From patchwork Wed Jan 9 15:03:01 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nick Clifton X-Patchwork-Id: 210720 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 55C042C0090 for ; Thu, 10 Jan 2013 02:07:04 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1358348824; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: From:To:Subject:Date:Message-ID:MIME-Version:Content-Type: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=nseYm9eDqKpkviWJunvS U/i2Fj0=; b=AOPo4JBYQk8E8YOL/EMLDB9LMke69ix8JM6CUofdWs1/OHvxRh+t lByoP8XUMDYYvTLTZOuJe8bfOH3CLOYfdsXyLrz0qIWKmdfhSdQaAlGS50DvBBS0 q70zxg72C5HJxMpeJ1tQyx1HR1E0nBzeRcXD3KCUYc/2MflC3xD/MlY= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:From:To:Subject:Date:Message-ID:MIME-Version:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=djutZpACS90tS0cydN5xyrgn29Je9wliA1DwTeyO6gU4prCxffC31a34j+rK3o QoO+O0ugC325/DG/8VUeu4lueJoyZpX5FSBaW7mWIf4S7O9saXtLtjw93kVbPBZe gPR9pi8hSEDJG+lFkX6adhGHVbAGo5+j1DZTH/VwkYLbw=; Received: (qmail 31923 invoked by alias); 9 Jan 2013 15:06:46 -0000 Received: (qmail 31791 invoked by uid 22791); 9 Jan 2013 15:06:44 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 09 Jan 2013 15:06:36 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r09F6Z4E032018 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 9 Jan 2013 10:06:35 -0500 Received: from Cadeux.redhat.com (vpn1-5-109.ams2.redhat.com [10.36.5.109]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r09F6Vk5016684 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO) for ; Wed, 9 Jan 2013 10:06:33 -0500 From: Nick Clifton To: gcc-patches@gcc.gnu.org Subject: Commit: V850: Fix floating point comparisons, branches and conditional stores Date: Wed, 09 Jan 2013 15:03:01 +0000 Message-ID: <87ehhubdqy.fsf@redhat.com> MIME-Version: 1.0 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 Hi Guys, I am checking in the patch below to fix the V850's floating point comparison patterns, which was inverted in many places. The also includes a contribution from Nguyen Duy Dat at Renesas which adds floating point conditional store patterns and floating point conditional branch patterns. Tested with no regressions on a v850e2v3-elf toolchain. Cheers Nick gcc/ChangeLog 2013-01-09 Nguyen Duy Dat Nick Clifton * config/v850/v850.md (cbranchsf4): New pattern. (cstoresf4): New pattern. (cbranchdf4): New pattern. (cstoredf4): New pattern. (movsicc): Disallow floating point comparisons. (cmpsf_le_insn): Fix order of operators. (cmpsf_lt_insn): Likewise. (cmpsf_eq_insn): Likewise. (cmpdf_le_insn): Likewise. (cmpdf_lt_insn): Likewise. (cmpdf_eq_insn): Likewise. (cmpsf_ge_insn): Use LE comparison. (cmpdf_ge_insn): Likewise. (cmpsf_gt_insn): Use LT comparison. (cmpdf_gt_insn): Likewise. (cmpsf_ne_insn): Delete pattern. (cmpdf_ne_insn): Delete pattern. * config/v850/v850.c (v850_gen_float_compare): Use gen_cmpdf_eq_insn for NE comparison. (v850_float_z_comparison_operator) (v850_float_nz_comparison_operator): Move from here ... * config/v850/predicates.md: ... to here. Move GT and GE comparisons into v850_float_z_comparison_operator. * config/v850/v850-protos.h (v850_float_z_comparison_operator): Delete prototype. (v850_float_nz_comparison_operator): Likewise. Index: gcc/config/v850/predicates.md =================================================================== --- gcc/config/v850/predicates.md (revision 195050) +++ gcc/config/v850/predicates.md (working copy) @@ -497,3 +497,68 @@ return op == CONST0_RTX(mode); }) + +;; Return true if the floating point comparison operation +;; given produces a canonical answer. +(define_predicate "v850_float_z_comparison_operator" + (match_code "lt,le,eq,gt,ge") +{ + enum rtx_code code = GET_CODE (op); + + if (GET_RTX_CLASS (code) != RTX_COMPARE + && GET_RTX_CLASS (code) != RTX_COMM_COMPARE) + return 0; + + if (mode != GET_MODE (op) && mode != VOIDmode) + return 0; + + if ((GET_CODE (XEXP (op, 0)) != REG + || REGNO (XEXP (op, 0)) != CC_REGNUM) + || XEXP (op, 1) != const0_rtx) + return 0; + + if (GET_MODE (XEXP (op, 0)) == CC_FPU_LTmode) + return code == LT; + if (GET_MODE (XEXP (op, 0)) == CC_FPU_LEmode) + return code == LE; + if (GET_MODE (XEXP (op, 0)) == CC_FPU_EQmode) + return code == EQ; + if (GET_MODE (XEXP (op, 0)) == CC_FPU_GTmode) + return code == GT; + if (GET_MODE (XEXP (op, 0)) == CC_FPU_GEmode) + return code == GE; + + /* Note we do not accept CC_FPU_NEmode here. See + v850_float_nz_comparison for the reason why. */ + return 0; +}) + +;; Return true if the floating point comparison operation +;; given produces an inverted answer. +(define_predicate "v850_float_nz_comparison_operator" + (match_code "ne") +{ + enum rtx_code code = GET_CODE (op); + + /* The V850E2V3 does not have a floating point NZ comparison operator. + Instead it is implemented as an EQ comparison and this function ensures + that the branch_nz_normal and set_nz_insn patterns are used to examine + (and invert) the result of the floating point comparison. */ + + if (GET_RTX_CLASS (code) != RTX_COMPARE + && GET_RTX_CLASS (code) != RTX_COMM_COMPARE) + return 0; + + if (mode != GET_MODE (op) && mode != VOIDmode) + return 0; + + if ((GET_CODE (XEXP (op, 0)) != REG + || REGNO (XEXP (op, 0)) != CC_REGNUM) + || XEXP (op, 1) != const0_rtx) + return 0; + + if (GET_MODE (XEXP (op, 0)) == CC_FPU_NEmode) + return code == NE; + + return 0; +}) Index: gcc/config/v850/v850-protos.h =================================================================== --- gcc/config/v850/v850-protos.h (revision 195050) +++ gcc/config/v850/v850-protos.h (working copy) @@ -40,8 +40,6 @@ extern char * construct_dispose_instruction (rtx); extern char * construct_prepare_instruction (rtx); extern int ep_memory_operand (rtx, enum machine_mode, int); -extern int v850_float_z_comparison_operator (rtx, enum machine_mode); -extern int v850_float_nz_comparison_operator (rtx, enum machine_mode); extern rtx v850_gen_compare (enum rtx_code, enum machine_mode, rtx, rtx); extern enum machine_mode v850_gen_float_compare (enum rtx_code, Index: gcc/config/v850/v850.c =================================================================== --- gcc/config/v850/v850.c (revision 195050) +++ gcc/config/v850/v850.c (working copy) @@ -898,61 +898,6 @@ return ""; } -/* Generate comparison code. */ -int -v850_float_z_comparison_operator (rtx op, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (op); - - if (GET_RTX_CLASS (code) != RTX_COMPARE - && GET_RTX_CLASS (code) != RTX_COMM_COMPARE) - return 0; - - if (mode != GET_MODE (op) && mode != VOIDmode) - return 0; - - if ((GET_CODE (XEXP (op, 0)) != REG - || REGNO (XEXP (op, 0)) != CC_REGNUM) - || XEXP (op, 1) != const0_rtx) - return 0; - - if (GET_MODE (XEXP (op, 0)) == CC_FPU_LTmode) - return code == LT; - if (GET_MODE (XEXP (op, 0)) == CC_FPU_LEmode) - return code == LE; - if (GET_MODE (XEXP (op, 0)) == CC_FPU_EQmode) - return code == EQ; - - return 0; -} - -int -v850_float_nz_comparison_operator (rtx op, enum machine_mode mode) -{ - enum rtx_code code = GET_CODE (op); - - if (GET_RTX_CLASS (code) != RTX_COMPARE - && GET_RTX_CLASS (code) != RTX_COMM_COMPARE) - return 0; - - if (mode != GET_MODE (op) && mode != VOIDmode) - return 0; - - if ((GET_CODE (XEXP (op, 0)) != REG - || REGNO (XEXP (op, 0)) != CC_REGNUM) - || XEXP (op, 1) != const0_rtx) - return 0; - - if (GET_MODE (XEXP (op, 0)) == CC_FPU_GTmode) - return code == GT; - if (GET_MODE (XEXP (op, 0)) == CC_FPU_GEmode) - return code == GE; - if (GET_MODE (XEXP (op, 0)) == CC_FPU_NEmode) - return code == NE; - - return code == GT || code == GE || code == NE; -} - enum machine_mode v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) { @@ -998,17 +943,18 @@ case GT: emit_insn (gen_cmpdf_gt_insn (op0, op1)); break; + case NE: + /* Note: There is no NE comparison operator. So we + perform an EQ comparison and invert the branch. + See v850_float_nz_comparison for how this is done. */ case EQ: emit_insn (gen_cmpdf_eq_insn (op0, op1)); break; - case NE: - emit_insn (gen_cmpdf_ne_insn (op0, op1)); - break; default: - abort (); + gcc_unreachable (); } } - else if (GET_MODE(v850_compare_op0) == SFmode) + else if (GET_MODE (v850_compare_op0) == SFmode) { switch (cond) { @@ -1024,20 +970,19 @@ case GT: emit_insn (gen_cmpsf_gt_insn(op0, op1)); break; + case NE: + /* Note: There is no NE comparison operator. So we + perform an EQ comparison and invert the branch. + See v850_float_nz_comparison for how this is done. */ case EQ: emit_insn (gen_cmpsf_eq_insn(op0, op1)); break; - case NE: - emit_insn (gen_cmpsf_ne_insn(op0, op1)); - break; default: - abort (); + gcc_unreachable (); } } else - { - abort (); - } + gcc_unreachable (); return v850_select_cc_mode (cond, op0, op1); } Index: gcc/config/v850/v850.md =================================================================== --- gcc/config/v850/v850.md (revision 195050) +++ gcc/config/v850/v850.md (working copy) @@ -405,6 +405,114 @@ [(set_attr "length" "2,2") (set_attr "cc" "compare")]) +(define_expand "cbranchsf4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:SF 1 "register_operand") + (match_operand:SF 2 "register_operand")]) + (label_ref (match_operand 3 "")) + (pc))) + (clobber (cc0))] + "TARGET_V850E2V3" +{ + v850_compare_op0 = operands[1]; + v850_compare_op1 = operands[2]; + + enum rtx_code cond = GET_CODE(operands[0]); + enum machine_mode mode; + rtx fcc_reg; + rtx cc_reg; + rtx tmp; + + if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT) + FAIL; + + mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1); + fcc_reg = gen_rtx_REG (mode, FCC_REGNUM); + cc_reg = gen_rtx_REG (mode, CC_REGNUM); + emit_insn(gen_rtx_SET (mode, cc_reg, fcc_reg)); + tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, + gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); + DONE; +}) + +(define_insn "cstoresf4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:SF 2 "register_operand" "r") + (match_operand:SF 3 "register_operand" "r")]))] + "TARGET_V850E2V3" +{ + if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) + return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf nz, %0"; + if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE) + return "cmpf.s %c1, %z2, %z3 ; trfsr ; setf z, %0"; + if (GET_CODE (operands[1]) == EQ) + return "cmpf.s eq, %z2, %z3 ; trfsr ; setf z, %0"; + if (GET_CODE (operands[1]) == NE) + return "cmpf.s neq, %z2, %z3 ; trfsr ; setf nz, %0"; + gcc_unreachable (); +} + [(set_attr "length" "12") + (set_attr "type" "fpu")] +) + +(define_expand "cbranchdf4" + [(set (pc) + (if_then_else (match_operator 0 "ordered_comparison_operator" + [(match_operand:DF 1 "even_reg_operand") + (match_operand:DF 2 "even_reg_operand")]) + (label_ref (match_operand 3 "")) + (pc))) + (clobber (cc0))] + "TARGET_V850E2V3" +{ + v850_compare_op0 = operands[1]; + v850_compare_op1 = operands[2]; + + enum rtx_code cond = GET_CODE(operands[0]); + enum machine_mode mode; + rtx fcc_reg; + rtx cc_reg; + rtx tmp; + + if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT) + FAIL; + + mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1); + fcc_reg = gen_rtx_REG (mode, FCC_REGNUM); + cc_reg = gen_rtx_REG (mode, CC_REGNUM); + emit_insn(gen_rtx_SET (mode, cc_reg, fcc_reg)); + tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); + tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, + gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx); + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp)); + DONE; +}) + +(define_insn "cstoredf4" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operator:SI 1 "ordered_comparison_operator" + [(match_operand:DF 2 "even_reg_operand" "r") + (match_operand:DF 3 "even_reg_operand" "r")]))] + "TARGET_V850E2V3" +{ + if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) + return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf nz, %0"; + if (GET_CODE (operands[1]) == LT || GET_CODE (operands[1]) == LE) + return "cmpf.d %c1, %z2, %z3 ; trfsr ; setf z, %0"; + if (GET_CODE (operands[1]) == EQ) + return "cmpf.d eq, %z2, %z3 ; trfsr ; setf z ,%0"; + if (GET_CODE (operands[1]) == NE) + return "cmpf.d neq, %z2, %z3 ; trfsr ; setf nz, %0"; + gcc_unreachable (); +} + [(set_attr "length" "12") + (set_attr "type" "fpu")] +) + (define_expand "cmpsf" [(set (reg:CC CC_REGNUM) (compare (match_operand:SF 0 "register_operand" "r") @@ -940,6 +1048,11 @@ (match_operand:SI 3 "reg_or_const_operand" "rI")))] "(TARGET_V850E || TARGET_V850E2_ALL)" { + /* Make sure that we have an integer comparison... */ + if (GET_MODE (XEXP (operands[1], 0)) != CCmode + && GET_MODE (XEXP (operands[1], 0)) != SImode) + FAIL; + if ((GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT)) { @@ -2210,7 +2323,7 @@ (compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] "TARGET_USE_FPU" - "cmpf.s le,%z1,%z0" + "cmpf.s le, %z0, %z1" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2220,7 +2333,7 @@ (compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] "TARGET_USE_FPU" - "cmpf.s lt,%z1,%z0" + "cmpf.s lt, %z0, %z1" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2230,7 +2343,7 @@ (compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] "TARGET_USE_FPU" - "cmpf.s ge,%z1,%z0" + "cmpf.s le, %z1, %z0" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2240,7 +2353,7 @@ (compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] "TARGET_USE_FPU" - "cmpf.s gt,%z1,%z0" + "cmpf.s lt, %z1, %z0" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2250,21 +2363,11 @@ (compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] "TARGET_USE_FPU" - "cmpf.s eq,%z1,%z0" + "cmpf.s eq, %z0, %z1" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) -(define_insn "cmpsf_ne_insn" - [(set (reg:CC_FPU_NE FCC_REGNUM) - (compare:CC_FPU_NE (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" - "cmpf.s neq,%z1,%z0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit") - (set_attr "type" "fpu")]) - ; DF (define_insn "cmpdf_le_insn" @@ -2272,7 +2375,7 @@ (compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] "TARGET_USE_FPU" - "cmpf.d le,%z1,%z0" + "cmpf.d le, %z0, %z1" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2282,7 +2385,7 @@ (compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] "TARGET_USE_FPU" - "cmpf.d lt,%z1,%z0" + "cmpf.d lt, %z0, %z1" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2292,7 +2395,7 @@ (compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] "TARGET_USE_FPU" - "cmpf.d ge,%z1,%z0" + "cmpf.d le, %z1, %z0" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2300,9 +2403,9 @@ (define_insn "cmpdf_gt_insn" [(set (reg:CC_FPU_GT FCC_REGNUM) (compare:CC_FPU_GT (match_operand:DF 0 "even_reg_operand" "r") - (match_operand:DF 1 "even_reg_operand" "r")))] + (match_operand:DF 1 "even_reg_operand" "r")))] "TARGET_USE_FPU" - "cmpf.d gt,%z1,%z0" + "cmpf.d lt, %z1, %z0" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) @@ -2312,22 +2415,11 @@ (compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] "TARGET_USE_FPU" - "cmpf.d eq,%z1,%z0" + "cmpf.d eq, %z0, %z1" [(set_attr "length" "4") (set_attr "cc" "none_0hit") (set_attr "type" "fpu")]) -(define_insn "cmpdf_ne_insn" - [(set (reg:CC_FPU_NE FCC_REGNUM) - (compare:CC_FPU_NE (match_operand:DF 0 "even_reg_operand" "r") - (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" - "cmpf.d neq,%z1,%z0" - [(set_attr "length" "4") - (set_attr "cc" "none_0hit") - (set_attr "type" "fpu")]) - - ;; ;; Transfer a v850e2v3 fcc to the Z bit of CC0 (this is necessary to do a ;; conditional branch based on a floating-point compare)