From patchwork Fri Oct 18 19:48:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Richard Earnshaw \(lists\)" X-Patchwork-Id: 176970 Delivered-To: patch@linaro.org Received: by 2002:ac9:3c86:0:0:0:0:0 with SMTP id w6csp1296972ocf; Fri, 18 Oct 2019 13:00:27 -0700 (PDT) X-Google-Smtp-Source: APXvYqxDyHEJbXjYf5SabRhToliOFnyoA8yGM2lulPiHXg5XLw3K6UB6mLW1jMOepHxEGhtAk2e+ X-Received: by 2002:aa7:d8d5:: with SMTP id k21mr8756889eds.286.1571428827807; Fri, 18 Oct 2019 13:00:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1571428827; cv=none; d=google.com; s=arc-20160816; b=ibc4/5Qq6GNVd09TQpKL5x6OrOdytJOGowhkkE9M6NzrTfojzFPxnSiTlSFe7RBHBe BNIcLPFrl2sUaEPwCYAhLxg/1nsStYf97AWBk4KDdS8auPe+pgphjXZ7Le3Y6ZBFpXqR xmRILpMNhboQBoG7owRS5aN3NvO3qxPmlHav1rOMqRS8zbPWDFU+AGNzKCUxtO+Dk9md TPFfNhTIsuAjgbTVOKlP/JE6zZ9t07xC1IUiN1ChF/XfUaOOpnltZGtHcTNbfnQeEw6t voHwk8PGIwjP9whqlVcAltS84zeYf5H8/fbyw7ViYpH1gwO6kW4mmmZzfeiKqDXfl1xU laXw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:delivered-to:sender:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature; bh=0EmXPiG/SukcgZl3asrRfP3DU33SrPQA8pBh0VhUDkI=; b=h7kBwH2A5FUyNU8pcvVmbBFj8ciMbdBaHm7+1FFi45fRMHF1PPIFb2FUdhmElxSF02 dGO4ciTJ6kluncDom+wVCM6MIW/2PVVope3+rV1U9nx84N2ZaGpFuW6eZWwVX8Iv0YAf 1hurHaL1P9IsC8AfTLy2ibb0Yo3Djofz1857r+lOG69yTAiHyY618ZmIMEnMzjznqSt4 gqHpbcjIfEPuQrLRL4xCQrsknqewt2W0dZAw5yOmhxxCOaDI9UYdBrf/awcoEN8fL3/Z aIBXznlbpIXnpXgcmVEMZS4/2Um2kHadPa23aolSrmMQzlq2GsIQwh0e4pH8tdl/2Sw6 agGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=cp7YqReo; spf=pass (google.com: domain of gcc-patches-return-511336-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-511336-patch=linaro.org@gcc.gnu.org" Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id c38si4701294eda.46.2019.10.18.13.00.27 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Oct 2019 13:00:27 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-511336-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=cp7YqReo; spf=pass (google.com: domain of gcc-patches-return-511336-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="gcc-patches-return-511336-patch=linaro.org@gcc.gnu.org" DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type; q=dns; s=default; b=p4bVMN6fWXPQlMYg oUweG/mBsXaSjHWleAeYGt8DzxfAh/2KQz7VWllYaSaeigYMR4mYA1aoucodt9fx 5g+unps21Zkc7KdhXY8eVrJusQp98JjgHzvatpMKX3d3qNjxDuM2NwGkXBFwqu9l xrP07jj605HTzCgWE2UuuHM3uEU= 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:from :to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type; s=default; bh=dbk6QRmJRQZZh9tpH19S4a jw91o=; b=cp7YqReoiAAUL+zP4Rv9nSr/3C9pslOiqWvv89TKYA4agrnj/Bal2N +f73CqlUaSEA1nttWPLZ5CQ+AA4rZG3KUJWQ0TdJt6d7bJy2PnmI/zE+9OYzm1c+ RLbiga9srd097pS5ECXV8Hm7qwUeZnPz6ZrUUBujNq/vg86mw32fE= Received: (qmail 121980 invoked by alias); 18 Oct 2019 19:56:37 -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 115975 invoked by uid 89); 18 Oct 2019 19:55:52 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=flexible X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (209.51.188.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 18 Oct 2019 19:55:50 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iLYLc-00059z-SH for gcc-patches@gcc.gnu.org; Fri, 18 Oct 2019 15:55:42 -0400 Received: from [217.140.110.172] (port=42746 helo=foss.arm.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1iLYLc-000549-In for gcc-patches@gcc.gnu.org; Fri, 18 Oct 2019 15:55:40 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 11E9B16F2; Fri, 18 Oct 2019 12:49:22 -0700 (PDT) Received: from eagle.buzzard.freeserve.co.uk (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 934FA3F6C4; Fri, 18 Oct 2019 12:49:21 -0700 (PDT) From: Richard Earnshaw To: gcc-patches@gcc.gnu.org Cc: Richard Earnshaw Subject: [PATCH 14/29] [arm] Early split simple DImode equality comparisons Date: Fri, 18 Oct 2019 20:48:45 +0100 Message-Id: <20191018194900.34795-15-Richard.Earnshaw@arm.com> In-Reply-To: <20191018194900.34795-1-Richard.Earnshaw@arm.com> References: <20191018194900.34795-1-Richard.Earnshaw@arm.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 217.140.110.172 This is the first step of early splitting all the DImode comparison operations. We start by factoring the DImode handling out of arm_gen_compare_reg into its own function. Simple DImode equality comparisions (such as equality with zero, or equality with a constant that is zero in one of the two word values that it comprises) can be done using a single subtract followed by an ORRS instruction. This avoids the need for conditional execution. For example, (r0 != 5) can be written as SUB Rt, R0, #5 ORRS Rt, Rt, R1 The ORRS is now expanded using an SImode pattern that already exists in the MD file and this gives the register allocator more freedom to select registers (consecutive pairs are no-longer required). Furthermore, we can then delete the arm_cmpdi_zero pattern as it is no-longer required. We use SUB for the value adjustment as this has a generally more flexible range of immediates than XOR and what's more has the opportunity to be relaxed in thumb2 to a 16-bit SUBS instruction. * config/arm/arm.c (arm_select_cc_mode): For DImode equality tests return CC_Zmode if comparing against a constant where one word is zero. (arm_gen_compare_reg): Split DImode handling to ... (arm_gen_dicompare_reg): ... here. Handle equality comparisons against simple constants. * config/arm/arm.md (arm_cmpdi_zero): Delete pattern. --- gcc/config/arm/arm.c | 87 +++++++++++++++++++++++++++++++++---------- gcc/config/arm/arm.md | 11 ------ 2 files changed, 68 insertions(+), 30 deletions(-) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index e33b6b14d28..64367b42332 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -15350,8 +15350,14 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) case EQ: case NE: /* A DImode comparison against zero can be implemented by - or'ing the two halves together. */ - if (y == const0_rtx) + or'ing the two halves together. We can also handle + immediates where one word of that value is zero by + subtracting the non-zero word from the corresponding word + in the other register and then ORRing it with the other + word. */ + if (CONST_INT_P (y) + && ((UINTVAL (y) & 0xffffffff) == 0 + || (UINTVAL (y) >> 32) == 0)) return CC_Zmode; /* We can do an equality test in three Thumb instructions. */ @@ -15393,37 +15399,64 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) return CCmode; } -/* X and Y are two things to compare using CODE. Emit the compare insn and - return the rtx for register 0 in the proper mode. FP means this is a - floating point compare: I don't think that it is needed on the arm. */ -rtx -arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y, rtx scratch) +/* X and Y are two (DImode) things to compare for the condition CODE. Emit + the sequence of instructions needed to generate a suitable condition + code register. Return the CC register result. */ +static rtx +arm_gen_dicompare_reg (rtx_code code, rtx x, rtx y, rtx scratch) { - machine_mode mode; - rtx cc_reg; - int dimode_comparison = GET_MODE (x) == DImode || GET_MODE (y) == DImode; + /* We don't currently handle DImode in thumb1, but rely on libgcc. */ + gcc_assert (TARGET_32BIT); /* We might have X as a constant, Y as a register because of the predicates used for cmpdi. If so, force X to a register here. */ - if (dimode_comparison && !REG_P (x)) + if (!REG_P (x)) x = force_reg (DImode, x); - mode = SELECT_CC_MODE (code, x, y); - cc_reg = gen_rtx_REG (mode, CC_REGNUM); + machine_mode mode = SELECT_CC_MODE (code, x, y); + rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM); - if (dimode_comparison - && mode != CC_CZmode) + if (mode != CC_CZmode) { rtx clobber, set; /* To compare two non-zero values for equality, XOR them and then compare against zero. Not used for ARM mode; there CC_CZmode is cheaper. */ - if (mode == CC_Zmode && y != const0_rtx) + if (mode == CC_Zmode) { - gcc_assert (!reload_completed); - x = expand_binop (DImode, xor_optab, x, y, NULL_RTX, 0, OPTAB_WIDEN); - y = const0_rtx; + mode = CC_NOOVmode; + PUT_MODE (cc_reg, mode); + if (y != const0_rtx) + { + gcc_assert (CONST_INT_P (y)); + rtx xlo, xhi, ylo, yhi; + arm_decompose_di_binop (x, y, &xlo, &xhi, &ylo, &yhi); + if (!scratch) + scratch = gen_reg_rtx (SImode); + if (ylo == const0_rtx) + { + yhi = GEN_INT (-INTVAL(yhi)); + if (!arm_add_operand (yhi, SImode)) + yhi = force_reg (SImode, yhi); + emit_insn (gen_addsi3 (scratch, xhi, yhi)); + y = xlo; + } + else + { + gcc_assert (yhi == const0_rtx); + ylo = GEN_INT (-INTVAL(ylo)); + if (!arm_add_operand (ylo, SImode)) + ylo = force_reg (SImode, ylo); + emit_insn (gen_addsi3 (scratch, xlo, ylo)); + y = xhi; + } + x = gen_rtx_IOR (SImode, scratch, y); + y = const0_rtx; + } + else + x = gen_rtx_IOR (SImode, gen_lowpart (SImode, x), + gen_highpart (SImode, x)); } /* A scratch register is required. */ @@ -15442,6 +15475,22 @@ arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y, rtx scratch) return cc_reg; } +/* X and Y are two things to compare using CODE. Emit the compare insn and + return the rtx for register 0 in the proper mode. */ +rtx +arm_gen_compare_reg (rtx_code code, rtx x, rtx y, rtx scratch) +{ + if (GET_MODE (x) == DImode || GET_MODE (y) == DImode) + return arm_gen_dicompare_reg (code, x, y, scratch); + + machine_mode mode = SELECT_CC_MODE (code, x, y); + rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM); + + emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y)); + + return cc_reg; +} + /* Generate a sequence of insns that will generate the correct return address mask depending on the physical architecture that the program is running on. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 613f50ae5f0..a6b0c196c58 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -6518,17 +6518,6 @@ (define_insn_and_split "*arm_cmpdi_unsigned" (set_attr "type" "multiple")] ) -(define_insn "*arm_cmpdi_zero" - [(set (reg:CC_Z CC_REGNUM) - (compare:CC_Z (match_operand:DI 0 "s_register_operand" "r") - (const_int 0))) - (clobber (match_scratch:SI 1 "=r"))] - "TARGET_32BIT" - "orrs%?\\t%1, %Q0, %R0" - [(set_attr "conds" "set") - (set_attr "type" "logics_reg")] -) - ; This insn allows redundant compares to be removed by cse, nothing should ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that ; is deleted later on. The match_dup will match the mode here, so that