From patchwork Thu Mar 9 12:09:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1754598 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=Zkaj0iGS; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PXSgM5nCrz1yWl for ; Thu, 9 Mar 2023 23:10:23 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 89B7B385842A for ; Thu, 9 Mar 2023 12:10:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 89B7B385842A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1678363821; bh=T+ycLooeOpXMPuqKfHIjGZoFyYghpMQIk+6ZKUZ6lTI=; h=To:Cc:Subject:References:Date:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=Zkaj0iGSCfLRokAuez4fGVLZUFZW0XW6r4jxpWq8RwXMwEr51JEiLZuD06l1JGuDp xN5d0XjNCilIW12mD5m1MZnVcAdT8CRX4nhPKQS0nbFdaoR5n3e/C8YGGP/Jvw3Ia5 EmAhEe3AwlxkUgtLaevUHZ3EhN5FR/w+u//o4Hlc= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id B98093858D33 for ; Thu, 9 Mar 2023 12:10:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B98093858D33 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 C2FC44B3; Thu, 9 Mar 2023 04:10:44 -0800 (PST) Received: from localhost (e121540-lin.manchester.arm.com [10.32.110.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id D06363F67D; Thu, 9 Mar 2023 04:10:00 -0800 (PST) To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, segher@kernel.crashing.org, richard.sandiford@arm.com Cc: segher@kernel.crashing.org Subject: [PATCH v2 1/2] combine: Split code out of make_compound_operation_int References: Date: Thu, 09 Mar 2023 12:09:59 +0000 In-Reply-To: (Richard Sandiford's message of "Thu, 09 Mar 2023 12:08:33 +0000") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Spam-Status: No, score=-33.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Richard Sandiford via Gcc-patches From: Richard Sandiford Reply-To: Richard Sandiford Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" This patch just splits some code out of make_compound_operation_int into a new function called make_compound_operation_and. It is a prerequisite for the fix for PR106594. It might (or might not) make sense to put more of the existing "and" handling into the new function, so that the subreg+lshiftrt case can be handled through recursion rather than duplication. But that's certainly not necessary to fix the bug, so is at best stage 1 material. No behavioural change intended. gcc/ * combine.cc (make_compound_operation_and): New function, split out from... (make_compound_operation_int): ...here. --- gcc/combine.cc | 84 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/gcc/combine.cc b/gcc/combine.cc index 053879500b7..7d446d02cb4 100644 --- a/gcc/combine.cc +++ b/gcc/combine.cc @@ -7952,6 +7952,56 @@ extract_left_shift (scalar_int_mode mode, rtx x, int count) return 0; } +/* A subroutine of make_compound_operation_int. Try to combine an outer + AND of X and MASK with a partnering inner operation to form a compound + operation. Return the new X on success, otherwise return null. + + MODE is the mode of X. IN_CODE is as for make_compound_operation. + NEXT_CODE is the value of IN_CODE that should be used for (recursive) + calls to make_compound_operation. */ + +static rtx +make_compound_operation_and (scalar_int_mode mode, rtx x, + unsigned HOST_WIDE_INT mask, + rtx_code in_code, rtx_code next_code) +{ + switch (GET_CODE (x)) + { + case SUBREG: + /* If the operand is a paradoxical subreg of a register or memory + and MASK (limited to the smaller mode) has only zero bits where + the sub expression has known zero bits, this can be expressed as + a zero_extend. */ + { + rtx sub = XEXP (x, 0); + machine_mode sub_mode = GET_MODE (sub); + int sub_width; + if ((REG_P (sub) || MEM_P (sub)) + && GET_MODE_PRECISION (sub_mode).is_constant (&sub_width) + && sub_width < GET_MODE_PRECISION (mode)) + { + unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (sub_mode); + unsigned HOST_WIDE_INT submask; + + /* The shifted AND constant with all the known zero + bits set. */ + submask = mask | ~nonzero_bits (sub, sub_mode); + if ((submask & mode_mask) == mode_mask) + { + rtx new_rtx = make_compound_operation (sub, next_code); + return make_extraction (mode, new_rtx, 0, 0, sub_width, + 1, 0, in_code == COMPARE); + } + } + break; + } + + default: + break; + } + return NULL_RTX; +} + /* Subroutine of make_compound_operation. *X_PTR is the rtx at the current level of the expression and MODE is its mode. IN_CODE is as for make_compound_operation. *NEXT_CODE_PTR is the value of IN_CODE @@ -8184,36 +8234,10 @@ make_compound_operation_int (scalar_int_mode mode, rtx *x_ptr, make_compound_operation (XEXP (x, 0), next_code), i, NULL_RTX, 1, 1, 0, 1); - - /* If the one operand is a paradoxical subreg of a register or memory and - the constant (limited to the smaller mode) has only zero bits where - the sub expression has known zero bits, this can be expressed as - a zero_extend. */ - else if (GET_CODE (XEXP (x, 0)) == SUBREG) - { - rtx sub; - - sub = XEXP (XEXP (x, 0), 0); - machine_mode sub_mode = GET_MODE (sub); - int sub_width; - if ((REG_P (sub) || MEM_P (sub)) - && GET_MODE_PRECISION (sub_mode).is_constant (&sub_width) - && sub_width < mode_width) - { - unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (sub_mode); - unsigned HOST_WIDE_INT mask; - - /* original AND constant with all the known zero bits set */ - mask = UINTVAL (XEXP (x, 1)) | (~nonzero_bits (sub, sub_mode)); - if ((mask & mode_mask) == mode_mask) - { - new_rtx = make_compound_operation (sub, next_code); - new_rtx = make_extraction (mode, new_rtx, 0, 0, sub_width, - 1, 0, in_code == COMPARE); - } - } - } - + else + new_rtx = make_compound_operation_and (mode, XEXP (x, 0), + UINTVAL (XEXP (x, 1)), + in_code, next_code); break; case LSHIFTRT: From patchwork Thu Mar 9 12:10:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1754599 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=ZaX+73C3; dkim-atps=neutral Received: from sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4PXShL3WH1z1yWl for ; Thu, 9 Mar 2023 23:11:14 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 30E043858284 for ; Thu, 9 Mar 2023 12:11:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 30E043858284 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1678363872; bh=zR30jfDn7k9288H6eSCcnjTClomdntGEOhhbQPZBscM=; h=To:Cc:Subject:References:Date:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=ZaX+73C3M/Y8InWniX4QSDwDb+WFyKsJR2pOIPrFMIDiysVfUkFE2ong3Y6PeixlS SgZ1EptIYswKLQOg1qYRrGeV7yYOQ187FZI+Llq5fUcaVDY1Ak7Kqk3CzYPSXw+9+S L33ZBRe12HBSw45gENY003ArSS5CdDGeLwjy3bmw= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id F3BB23858002 for ; Thu, 9 Mar 2023 12:10:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F3BB23858002 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 352934B3; Thu, 9 Mar 2023 04:11:36 -0800 (PST) Received: from localhost (e121540-lin.manchester.arm.com [10.32.110.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4230C3F67D; Thu, 9 Mar 2023 04:10:52 -0800 (PST) To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, segher@kernel.crashing.org, richard.sandiford@arm.com Cc: segher@kernel.crashing.org Subject: [PATCH v2 2/2] combine: Try harder to form zero_extends [PR106594] References: Date: Thu, 09 Mar 2023 12:10:51 +0000 In-Reply-To: (Richard Sandiford's message of "Thu, 09 Mar 2023 12:08:33 +0000") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Spam-Status: No, score=-33.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Richard Sandiford via Gcc-patches From: Richard Sandiford Reply-To: Richard Sandiford Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" g:c23a9c87cc62bd177fd0d4db6ad34b34e1b9a31f uses nonzero_bits information to convert sign_extends into zero_extends. That change is semantically correct in itself, but for the testcase in the PR, it leads to a series of unfortunate events, as described below. We try to combine: Trying 24 -> 25: 24: r116:DI=sign_extend(r115:SI) REG_DEAD r115:SI 25: r117:SI=[r116:DI*0x4+r118:DI] REG_DEAD r116:DI REG_EQUAL [r116:DI*0x4+`constellation_64qam'] which previously succeeded, giving: (set (reg:SI 117 [ constellation_64qam[_5] ]) (mem/u:SI (plus:DI (mult:DI (sign_extend:DI (reg:SI 115)) (const_int 4 [0x4])) (reg/f:DI 118)) [1 constellation_64qam[_5]+0 S4 A32])) However, nonzero_bits can tell that only the low 6 bits of r115 can be nonzero. The commit above therefore converts the sign_extend to a zero_extend. Using the same nonzero_bits information, we then "expand" the zero_extend to: (and:DI (subreg:DI (reg:SI r115) 0) (const_int 63)) Substituting into the mult gives the unsimplified expression: (mult:DI (and:DI (subreg:DI (reg:SI r115) 0) (const_int 63)) (const_int 4)) The simplification rules for mult convert this to an ashift by 2. Then, this rule in simplify_shift_const_1: /* If we have (shift (logical)), move the logical to the outside to allow it to possibly combine with another logical and the shift to combine with another shift. This also canonicalizes to what a ZERO_EXTRACT looks like. Also, some machines have (and (shift)) insns. */ moves the shift inside the "and", so that the expression becomes: (and:DI (ashift:DI (subreg:DI (reg:SI r115) 0) (const_int 2)) (const_int 252)) We later recanonicalise to a mult (since this is an address): (and:DI (mult:DI (subreg:DI (reg:SI r115) 0) (const_int 4)) (const_int 252)) But we fail to transform this back to the natural substitution: (mult:DI (zero_extend:DI (reg:SI r115)) (const_int 4)) There are several other cases in which make_compound_operation needs to look more than one level down in order to complete a compound operation. For example: (a) the ashiftrt handling uses extract_left_shift to look through things like logic ops in order to find a partnering ashift operation (b) the "and" handling looks through subregs, xors and iors to find a partnerning lshiftrt This patch takes the same approach for mult. gcc/ PR rtl-optimization/106594 * combine.cc (make_compound_operation_and): Look through multiplications by a power of two. gcc/testsuite/ * gcc.target/aarch64/pr106594.c: New test. --- gcc/combine.cc | 17 +++++++++++++++++ gcc/testsuite/gcc.target/aarch64/pr106594.c | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/pr106594.c diff --git a/gcc/combine.cc b/gcc/combine.cc index 7d446d02cb4..36d04ad6703 100644 --- a/gcc/combine.cc +++ b/gcc/combine.cc @@ -7996,6 +7996,23 @@ make_compound_operation_and (scalar_int_mode mode, rtx x, break; } + case MULT: + /* Recurse through a power of 2 multiplication (as can be found + in an address), using the relationship: + + (and (mult X 2**N1) N2) == (mult (and X (lshifrt N2 N1)) 2**N1). */ + if (CONST_INT_P (XEXP (x, 1)) + && pow2p_hwi (INTVAL (XEXP (x, 1)))) + { + int shift = exact_log2 (INTVAL (XEXP (x, 1))); + rtx sub = make_compound_operation_and (mode, XEXP (x, 0), + mask >> shift, in_code, + next_code); + if (sub) + return gen_rtx_MULT (mode, sub, XEXP (x, 1)); + } + break; + default: break; } diff --git a/gcc/testsuite/gcc.target/aarch64/pr106594.c b/gcc/testsuite/gcc.target/aarch64/pr106594.c new file mode 100644 index 00000000000..beda8e050a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr106594.c @@ -0,0 +1,20 @@ +/* { dg-options "-O2" } */ + +extern const int constellation_64qam[64]; + +void foo(int nbits, + const char *p_src, + int *p_dst) { + + while (nbits > 0U) { + char first = *p_src++; + + char index1 = ((first & 0x3) << 4) | (first >> 4); + + *p_dst++ = constellation_64qam[index1]; + + nbits--; + } +} + +/* { dg-final { scan-assembler {ldr\tw[0-9]+, \[x[0-9]+, w[0-9]+, [su]xtw #?2\]} } } */