From patchwork Thu Aug 22 08:46:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1975359 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=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WqGzR5znwz1yYZ for ; Thu, 22 Aug 2024 18:47:15 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0C0E43870C00 for ; Thu, 22 Aug 2024 08:47:14 +0000 (GMT) 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 585813870C16 for ; Thu, 22 Aug 2024 08:46:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 585813870C16 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 585813870C16 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1724316416; cv=none; b=XH4wsk8qfEfi/FKjg6Op9cPc76+xMGvo7EWwnHdGTiAAqWfAoL2+EmByq1HG2X05y0/K+ZNUZE9txsLlPB9HDf20zQr5enfNU1kV9myry6v2FaHFsJyBnTmgIHmGSTObR/ENJeZ8JVmdhrcNQsnBZjnj7+ahMj8H/r1JLLG681c= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1724316416; c=relaxed/simple; bh=AKV4HN1Dd8So9COHMw/YQhmcPxkwUtRiNR0XUyWrPPc=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Hnxz07pcXEZcCKBDMrICM7YwIww7fEgdYOtDaFTEnLXDjFZXd/LjlAYL4dZqeWGzOOfQvs8NbkZ4uRXAj7WJ0ycLinIZAqafp0JQ1zuSB2oGqwcozb9YSIYwqFqWcNK8Fd0qH6LUBHJYmGRPRYO4fiPHgrq6kHhVbRH+j6csnGE= ARC-Authentication-Results: i=1; server2.sourceware.org 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 14449DA7 for ; Thu, 22 Aug 2024 01:47:18 -0700 (PDT) Received: from localhost (e121540-lin.manchester.arm.com [10.32.110.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 9B0F03F66E for ; Thu, 22 Aug 2024 01:46:51 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [PATCH] Handle arithmetic on eliminated address indices [PR116413] Date: Thu, 22 Aug 2024 09:46:50 +0100 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Spam-Status: No, score=-18.9 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, T_SCC_BODY_TEXT_LINE 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch fixes gcc.c-torture/compile/opout.c for m68k with LRA enabled. The test has: ... z (a, b) { return (int) &a + (int) &b + (int) x + (int) z; } so it adds the address of two incoming arguments. This ends up being treated as an LEA in which the "index" is the incoming argument pointer, which the LEA multiplies by 2. The incoming argument pointer is then eliminated, leading to: (plus:SI (plus:SI (ashift:SI (plus:SI (reg/f:SI 24 %argptr) (const_int -4 [0xfffffffffffffffc])) (const_int 1 [0x1])) (reg/f:SI 41 [ _6 ])) (const_int 20 [0x14])) In the address_info scheme, the innermost plus has to be treated as the index "term", since that's the thing that's subject to index_reg_class. Tested on aarch64-linux-gnu, powerpc64le-linux-gnu, and x86_64-linux-gnu. Also tested by building at least one target per CPU directory and checking that there were no asm changes or new ICEs when compiling gcc.c-torture, gcc.dg, and g++.dg at -Os. OK to install? Richard gcc/ PR middle-end/116413 * rtl.h (address_info): Update commentary. * rtlanal.cc (valid_base_or_index_term_p): New function, split out from... (get_base_term, get_index_term): ...here. Handle elimination PLUSes. --- gcc/rtl.h | 14 ++++++++++++-- gcc/rtlanal.cc | 29 +++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/gcc/rtl.h b/gcc/rtl.h index 2370d608161..1ef6432fd9c 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2225,11 +2225,21 @@ struct address_info { reloading. - *BASE is a variable expression representing a base address. - It contains exactly one REG, SUBREG or MEM, pointed to by BASE_TERM. + It contains exactly one "term", pointed to by BASE_TERM. + This term can be one of the following: + + (1) a REG, or a SUBREG of a REG + (2) an eliminated REG (a PLUS of (1) and a constant) + (3) a MEM, or a SUBREG of a MEM + (4) a SCRATCH + + This term is the one that base_reg_class constrains. - *INDEX is a variable expression representing an index value. It may be a scaled expression, such as a MULT. It has exactly - one REG, SUBREG or MEM, pointed to by INDEX_TERM. + one "term", pointed to by INDEX_TERM. The possible terms are + the same as for BASE. This term is the one that index_reg_class + constrains. - *DISP is a constant, possibly mutated. DISP_TERM points to the unmutated RTX_CONST_OBJ. */ diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc index 71207ee4f41..8afbb32f220 100644 --- a/gcc/rtlanal.cc +++ b/gcc/rtlanal.cc @@ -6494,6 +6494,25 @@ binary_scale_code_p (enum rtx_code code) || code == ROTATERT); } +/* Return true if X appears to be a valid base or index term. */ +static bool +valid_base_or_index_term_p (rtx x) +{ + if (GET_CODE (x) == SCRATCH) + return true; + /* Handle what appear to be eliminated forms of a register. If we reach + here, the elimination occurs outside of the outermost PLUS tree, + and so the elimination offset cannot be treated as a displacement + of the main address. Instead, we need to treat the whole PLUS as + the base or index term. The address can only be made legitimate by + reloading the PLUS. */ + if (GET_CODE (x) == PLUS && CONST_SCALAR_INT_P (XEXP (x, 1))) + x = XEXP (x, 0); + if (GET_CODE (x) == SUBREG) + x = SUBREG_REG (x); + return REG_P (x) || MEM_P (x); +} + /* If *INNER can be interpreted as a base, return a pointer to the inner term (see address_info). Return null otherwise. */ @@ -6502,10 +6521,7 @@ get_base_term (rtx *inner) { if (GET_CODE (*inner) == LO_SUM) inner = strip_address_mutations (&XEXP (*inner, 0)); - if (REG_P (*inner) - || MEM_P (*inner) - || GET_CODE (*inner) == SUBREG - || GET_CODE (*inner) == SCRATCH) + if (valid_base_or_index_term_p (*inner)) return inner; return 0; } @@ -6519,10 +6535,7 @@ get_index_term (rtx *inner) /* At present, only constant scales are allowed. */ if (binary_scale_code_p (GET_CODE (*inner)) && CONSTANT_P (XEXP (*inner, 1))) inner = strip_address_mutations (&XEXP (*inner, 0)); - if (REG_P (*inner) - || MEM_P (*inner) - || GET_CODE (*inner) == SUBREG - || GET_CODE (*inner) == SCRATCH) + if (valid_base_or_index_term_p (*inner)) return inner; return 0; }