From patchwork Tue Sep 1 15:04:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyrylo Tkachov X-Patchwork-Id: 52933 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f71.google.com (mail-la0-f71.google.com [209.85.215.71]) by patches.linaro.org (Postfix) with ESMTPS id D249A2127E for ; Tue, 1 Sep 2015 15:05:08 +0000 (UTC) Received: by lamp12 with SMTP id p12sf1150512lam.2 for ; Tue, 01 Sep 2015 08:05:07 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:mailing-list:precedence:list-id :list-unsubscribe:list-archive:list-post:list-help:sender :delivered-to:message-id:date:from:user-agent:mime-version:to:cc :subject:content-type:x-original-sender :x-original-authentication-results; bh=K/Glm1Dy/cJ/VRAy6IfcfdYfCgUrqaBE9K0zagCsNKQ=; b=XYJG0bCvjRC8waLGSPU+KU4B9bwR7Bix//sBCysU06Vj8fnbM+hfIufDNahz8Qhi+n CQpVD5GKG7p4txmoN9UJB5L8fGDEC1bvXBw0k0NtkXdHUPCEqyQfjSPZHDfusKVREizH mSKvy58v44AM+5eczARqSvRzhsQeaF7DYLIt4W6/kZo3vWU2ujYeHj3C93c59Tk98SEM rMrGxW9ZRe6EwWVenqu4LgALMYUJkJIV+lPZj3sEb6u8x+eHsb5VEX36UeMcVXpdn6xp 6XdO1Q1LXmpHzYdeRezBfOD/hoeFnlFMtgwM5SdXKECyR/+BzdN1BFKkUCLNbFGn1Luk UdIQ== X-Gm-Message-State: ALoCoQmXeRQXiyQeFm2RAlWXH+dsKl5Yj1BOhANt8qQjir/bwrdvrIoyCJESdggGKxzioQVHc7Fu X-Received: by 10.112.189.105 with SMTP id gh9mr7797413lbc.16.1441119907829; Tue, 01 Sep 2015 08:05:07 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.6.196 with SMTP id d4ls663212laa.91.gmail; Tue, 01 Sep 2015 08:05:07 -0700 (PDT) X-Received: by 10.152.236.39 with SMTP id ur7mr12966293lac.21.1441119907555; Tue, 01 Sep 2015 08:05:07 -0700 (PDT) Received: from mail-la0-x22e.google.com (mail-la0-x22e.google.com. [2a00:1450:4010:c03::22e]) by mx.google.com with ESMTPS id b6si16630256lab.123.2015.09.01.08.05.07 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 01 Sep 2015 08:05:07 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c03::22e as permitted sender) client-ip=2a00:1450:4010:c03::22e; Received: by laeb10 with SMTP id b10so1756962lae.1 for ; Tue, 01 Sep 2015 08:05:07 -0700 (PDT) X-Received: by 10.152.21.196 with SMTP id x4mr12862270lae.117.1441119906322; Tue, 01 Sep 2015 08:05:06 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.164.42 with SMTP id yn10csp598817lbb; Tue, 1 Sep 2015 08:05:03 -0700 (PDT) X-Received: by 10.68.163.5 with SMTP id ye5mr46704102pbb.120.1441119903058; Tue, 01 Sep 2015 08:05:03 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id ph2si12990631pac.118.2015.09.01.08.05.02 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 01 Sep 2015 08:05:03 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-406444-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 127783 invoked by alias); 1 Sep 2015 15:04:40 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list 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 127706 invoked by uid 89); 1 Sep 2015 15:04:40 -0000 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 16:04:31 +0100 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 X-IsSubscribed: yes X-Original-Sender: kyrylo.tkachov@arm.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2a00:1450:4010:c03::22e as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@gcc.gnu.org X-Google-Group-Id: 836684582541 Hi all, This first patch introduces the negcc and notcc optabs that should expand to a conditional negate or a conditional bitwise complement operation. These are used in ifcvt.c to transform code of the form: if (test) x = -A; else x = A; into: x = A; if (test) x = -x; where the "if (test) x = -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. 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 operand 0 according to the comparison in operand 1. If the comparison is false, operand 2 is moved into operand 0, otherwise (operand 2 + operand 3) is moved. +@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. Conditionally +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 operand 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 operand 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) } } + +/* Convert "if (test) x = -A; else x = A" into + x = A; if (test) x = -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 = 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 = INTVAL (if_info->a); + HOST_WIDE_INT val_b = INTVAL (if_info->b); + + rtx cond = if_info->cond; + + rtx x = if_info->x; + rtx target; + + start_sequence (); + + rtx_code code; + if (val_a == -val_b) + code = NEG; + else if (val_a == ~val_b) + code = NOT; + else + { + end_sequence (); + return false; + } + + rtx tmp = gen_reg_rtx (mode); + noce_emit_move_insn (tmp, if_info->a); + + target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp); + + if (target) + { + rtx_insn *seq = get_insns (); + + if (!seq) + { + end_sequence (); + return false; + } + + if (target != if_info->x) + noce_emit_move_insn (if_info->x, target); + + seq = 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 = a; else x = b", for A and B constant. Also allow A = y + c1, B = 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 code, rtx op0, rtx op1, return NULL_RTX; } + +/* 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 = unknown_optab; + if (code == NEG) + op = negcc_optab; + else if (code == NOT) + op = notcc_optab; + else + gcc_unreachable (); + + insn_code icode = direct_optab_handler (op, mode); + + if (icode == CODE_FOR_nothing) + return NULL_RTX; + + if (!target) + target = gen_reg_rtx (mode); + + rtx_insn *last = 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 != 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. 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") 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); +/* 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);