From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 127783 invoked by alias); 1 Sep 2015 15:04:40 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 127706 invoked by uid 89); 1 Sep 2015 15:04:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL,BAYES_00,SPF_PASS autolearn=ham version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (146.101.78.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 01 Sep 2015 15:04:36 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-19-FWskDUElR7WD9Kw0WevQpQ-1; Tue, 01 Sep 2015 16:04:32 +0100 Received: from [10.2.207.50] ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 1 Sep 2015 16:04:31 +0100 Message-ID: <55E5BE7F.2040600@arm.com> Date: Tue, 01 Sep 2015 15:04:00 -0000 From: Kyrill Tkachov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: GCC Patches CC: Marcus Shawcroft , Richard Earnshaw , Ramana Radhakrishnan , James Greenhalgh Subject: [PATCH][optabs][ifcvt][1/3] Define negcc, notcc optabs X-MC-Unique: FWskDUElR7WD9Kw0WevQpQ-1 Content-Type: multipart/mixed; boundary="------------000009010907010104030807" X-IsSubscribed: yes X-SW-Source: 2015-09/txt/msg00069.txt.bz2 This is a multi-part message in MIME format. --------------000009010907010104030807 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Content-length: 1087 Hi all, This first patch introduces the negcc and notcc optabs that should expand t= o a conditional negate or a conditional bitwise complement operation. These are used in ifcvt.c to transform code of the form: if (test) x =3D -A; else x =3D A; into: x =3D A; if (test) x =3D -x; where the "if (test) x =3D -x;" is implemented using the negcc (or notcc in= the ~x case) if such an optab is available. If such an optab is not implemented then no = transformation is performed. Thus, without patches 2/3 and 3/3 this patch does not impact= behaviour on any target. Bootstrapped and tested as part of the series on arm, aarch64, x86_64. Ok for trunk? Thanks, Kyrill 2015-09-01 Kyrylo Tkachov * ifcvt.c (noce_try_inverse_constants): New function. (noce_process_if_block): Call it. * optabs.h (emit_conditional_neg_or_complement): Declare prototype. * optabs.def (negcc_optab, notcc_optab): Declare. * optabs.c (emit_conditional_neg_or_complement): New function. * doc/tm.texi (Standard Names): Document negcc, notcc names. --------------000009010907010104030807 Content-Type: text/x-patch; name=negnotcc-optabs.patch Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="negnotcc-optabs.patch" Content-length: 6895 commit a2183218070ed5f2dca0a9651fdb08ce134ba8ee Author: Kyrylo Tkachov Date: Thu Aug 13 18:14:52 2015 +0100 [optabs][ifcvt][1/3] Define negcc, notcc optabs diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 0bffdc6..5038269 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -5791,6 +5791,21 @@ move operand 2 or (operands 2 + operand 3) into oper= and 0 according to the comparison in operand 1. If the comparison is false, operand 2 is moved i= nto operand 0, otherwise (operand 2 + operand 3) is moved. =20 +@cindex @code{neg@var{mode}cc} instruction pattern +@item @samp{neg@var{mode}cc} +Similar to @samp{mov@var{mode}cc} but for conditional negation. Condition= ally +move the negation of operand 2 operand 3 into operand 0 according to the +comparison in operand 1. If the comparison is true, the negation of opera= nd 2 +is moved into operand 0, otherwise operand 3 is moved. + +@cindex @code{not@var{mode}cc} instruction pattern +@item @samp{not@var{mode}cc} +Similar to @samp{neg@var{mode}cc} but for conditional complement. +Conditionally move the bitwise complement of operand 2 operand 3 into oper= and 0 +according to the comparison in operand 1. If the comparison is true, +the complement of operand 2 is moved into operand 0, otherwise operand 3 is +moved. + @cindex @code{cstore@var{mode}4} instruction pattern @item @samp{cstore@var{mode}4} Store zero or nonzero in operand 0 according to whether a comparison diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index d3b244c..aabbde8 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -1187,6 +1187,88 @@ noce_try_store_flag (struct noce_if_info *if_info) } } =20 + +/* Convert "if (test) x =3D -A; else x =3D A" into + x =3D A; if (test) x =3D -x if the machine can do the + conditional negate form of this cheaply. + Try this before noce_try_cmove that will just load the + immediates into two registers and do a conditional select + between them. If the target has a conditional negate or + conditional invert operation we can save a potentially + expensive constant synthesis. */ + +static bool +noce_try_inverse_constants (struct noce_if_info *if_info) +{ + if (!noce_simple_bbs (if_info)) + return false; + + if (!CONST_INT_P (if_info->a) + || !CONST_INT_P (if_info->b) + || !REG_P (if_info->x)) + return false; + + machine_mode mode =3D GET_MODE (if_info->x); + + /* If the branch is cheaper than two instructions then this is + unlikely to be beneficial. */ + if (if_info->branch_cost < 2) + return false; + + HOST_WIDE_INT val_a =3D INTVAL (if_info->a); + HOST_WIDE_INT val_b =3D INTVAL (if_info->b); + + rtx cond =3D if_info->cond; + + rtx x =3D if_info->x; + rtx target; + + start_sequence (); + + rtx_code code; + if (val_a =3D=3D -val_b) + code =3D NEG; + else if (val_a =3D=3D ~val_b) + code =3D NOT; + else + { + end_sequence (); + return false; + } + + rtx tmp =3D gen_reg_rtx (mode); + noce_emit_move_insn (tmp, if_info->a); + + target =3D emit_conditional_neg_or_complement (x, code, mode, cond, tmp,= tmp); + + if (target) + { + rtx_insn *seq =3D get_insns (); + + if (!seq) + { + end_sequence (); + return false; + } + + if (target !=3D if_info->x) + noce_emit_move_insn (if_info->x, target); + + seq =3D end_ifcvt_sequence (if_info); + + if (!seq) + return false; + + emit_insn_before_setloc (seq, if_info->jump, + INSN_LOCATION (if_info->insn_a)); + return true; + } + + end_sequence (); + return false; +} + + /* Convert "if (test) x =3D a; else x =3D b", for A and B constant. Also allow A =3D y + c1, B =3D y + c2, with a common y between A and B. */ @@ -3198,6 +3280,8 @@ noce_process_if_block (struct noce_if_info *if_info) goto success; if (noce_try_abs (if_info)) goto success; + if (noce_try_inverse_constants (if_info)) + goto success; if (!targetm.have_conditional_execution () && noce_try_store_flag_constants (if_info)) goto success; diff --git a/gcc/optabs.c b/gcc/optabs.c index 97c1d38..dd3ba30 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4595,6 +4595,56 @@ emit_conditional_move (rtx target, enum rtx_code cod= e, rtx op0, rtx op1, return NULL_RTX; } =20 + +/* Emit a conditional negate or bitwise complement using the + negcc or notcc optabs if available. Return NULL_RTX if such operations + are not available. Otherwise return the RTX holding the result. + TARGET is the desired destination of the result. COMP is the comparison + on which to negate. If COND is true move into TARGET the negation + or bitwise complement of OP1. Otherwise move OP2 into TARGET. + CODE is either NEG or NOT. MODE is the machine mode in which the + operation is performed. */ + +rtx +emit_conditional_neg_or_complement (rtx target, rtx_code code, + machine_mode mode, rtx cond, rtx op1, + rtx op2) +{ + optab op =3D unknown_optab; + if (code =3D=3D NEG) + op =3D negcc_optab; + else if (code =3D=3D NOT) + op =3D notcc_optab; + else + gcc_unreachable (); + + insn_code icode =3D direct_optab_handler (op, mode); + + if (icode =3D=3D CODE_FOR_nothing) + return NULL_RTX; + + if (!target) + target =3D gen_reg_rtx (mode); + + rtx_insn *last =3D get_last_insn (); + struct expand_operand ops[4]; + + create_output_operand (&ops[0], target, mode); + create_fixed_operand (&ops[1], cond); + create_input_operand (&ops[2], op1, mode); + create_input_operand (&ops[3], op2, mode); + + if (maybe_expand_insn (icode, 4, ops)) + { + if (ops[0].value !=3D target) + convert_move (target, ops[0].value, false); + + return target; + } + delete_insns_since (last); + return NULL_RTX; +} + /* Return nonzero if a conditional move of mode MODE is supported. =20 This function is for combine so it can tell whether an insn that looks diff --git a/gcc/optabs.def b/gcc/optabs.def index 888b21c..6fad6d9 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -183,6 +183,8 @@ OPTAB_D (reload_out_optab, "reload_out$a") =20 OPTAB_DC(cbranch_optab, "cbranch$a4", COMPARE) OPTAB_D (addcc_optab, "add$acc") +OPTAB_D (negcc_optab, "neg$acc") +OPTAB_D (notcc_optab, "not$acc") OPTAB_D (movcc_optab, "mov$acc") OPTAB_D (cmov_optab, "cmov$a6") OPTAB_D (cstore_optab, "cstore$a4") diff --git a/gcc/optabs.h b/gcc/optabs.h index 95f5cbc..dbb73d1 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -368,6 +368,10 @@ extern void emit_indirect_jump (rtx); rtx emit_conditional_move (rtx, enum rtx_code, rtx, rtx, machine_mode, rtx, rtx, machine_mode, int); =20 +/* Emit a conditional negate or bitwise complement operation. */ +rtx emit_conditional_neg_or_complement (rtx, rtx_code, machine_mode, rtx, + rtx, rtx); + /* Return nonzero if the conditional move is supported. */ int can_conditionally_move_p (machine_mode mode); =20 --------------000009010907010104030807--