From patchwork Thu Aug 29 06:50:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1978251 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=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 [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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WvX3v2GbXz1yfn for ; Thu, 29 Aug 2024 16:50:51 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 19234385E45C for ; Thu, 29 Aug 2024 06:50:49 +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 1B82C3858D39 for ; Thu, 29 Aug 2024 06:50:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1B82C3858D39 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 1B82C3858D39 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=1724914230; cv=none; b=ZgDv6geZaKVBaVfsfnILykxjSM4qQgrrNX/tifAe96SjLpMcvv6OhuALk/GWTfwfBQc+N86fKg7bq1WL0CN7QntegYXuaY4yUwCb8vjvUqFhdOhYqVMCoATWUsWGXkC7VejrZ1aPxwcC8uMMQifJmdB86QPS0bvf9rceieJARk0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1724914230; c=relaxed/simple; bh=vXMx84wIqcfWltHH/8R0YcttEV4kCSvhwC+Ns/nAnyk=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=UMLN9aYcal7wfEJ2Z5bPCIkrw5UAgoDZUsEABjyn08oOosfGxp0zICBh25y4KPaTgPLq945lRs9kNBOFrFXsEim9fDOr02ylxk+YwnQ6+i5/6qmsOt4N0cUhrIkTridqn0aIDXKF/SDFHvNmlMczsLGhlIGX68G3Jz9glUTWjus= 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 0A2E2DA7 for ; Wed, 28 Aug 2024 23:50:54 -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 746C23F73B for ; Wed, 28 Aug 2024 23:50:27 -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] Allow subregs around constant displacements [PR116516] Date: Thu, 29 Aug 2024 07:50:26 +0100 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Spam-Status: No, score=-18.8 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 a regression introduced by g:708ee71808ea61758e73. x86_64 allows addresses of the form: (zero_extend:DI (subreg:SI (symbol_ref:DI "foo") 0)) Before the previous patch, a lax SUBREG check meant that we would treat the subreg as a base and reload it into a base register. But that wasn't what the target was expecting. Instead we should treat "foo" as a constant displacement, to match: leal foo, After the patch, we recognised that "foo" isn't a base register, but ICEd on it rather than handling it as a displacement. With or without the recent patches, if the address had instead been: (zero_extend:DI (subreg:SI (plus:DI (reg:DI R) (symbol_ref:DI "foo") 0))) then we would have treated "foo" as the displacement and R as the base or index, as expected. The problem was that the code that does this was rejecting all subregs of objects, rather than just subregs of variable objects. Tested on aarch64-linux-gnu and x86_64-linux-gnu. OK to install? Richard gcc/ PR middle-end/116516 * rtlanal.cc (strip_address_mutations): Allow subregs around constant displacements. gcc/testsuite/ PR middle-end/116516 * gcc.c-torture/compile/pr116516.c: New test. --- gcc/rtlanal.cc | 28 ++++++++++++++++--- .../gcc.c-torture/compile/pr116516.c | 10 +++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr116516.c diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc index 8afbb32f220..cb0c0c0d719 100644 --- a/gcc/rtlanal.cc +++ b/gcc/rtlanal.cc @@ -6467,10 +6467,30 @@ strip_address_mutations (rtx *loc, enum rtx_code *outer_code) /* (and ... (const_int -X)) is used to align to X bytes. */ loc = &XEXP (*loc, 0); else if (code == SUBREG - && !OBJECT_P (SUBREG_REG (*loc)) - && subreg_lowpart_p (*loc)) - /* (subreg (operator ...) ...) inside and is used for mode - conversion too. */ + && (!OBJECT_P (SUBREG_REG (*loc)) + || CONSTANT_P (SUBREG_REG (*loc))) + && subreg_lowpart_p (*loc)) + /* (subreg (operator ...) ...) inside AND is used for mode + conversion too. It is also used for load-address operations + in which an extension can be done for free, such as: + + (zero_extend:DI + (subreg:SI (plus:DI (reg:DI R) (symbol_ref:DI "foo") 0))) + + The latter usage also covers subregs of plain "displacements", + such as: + + (zero_extend:DI (subreg:SI (symbol_ref:DI "foo") 0)) + + The inner address should then be the symbol_ref, not the subreg, + similarly to the plus case above. + + In contrast, the subreg in: + + (zero_extend:DI (subreg:SI (reg:DI R) 0)) + + should be treated as the base, since it should be replaced by + an SImode hard register during register allocation. */ loc = &SUBREG_REG (*loc); else return loc; diff --git a/gcc/testsuite/gcc.c-torture/compile/pr116516.c b/gcc/testsuite/gcc.c-torture/compile/pr116516.c new file mode 100644 index 00000000000..c423ebfef5c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr116516.c @@ -0,0 +1,10 @@ +extern void my_func (int); +typedef struct { + int var; +} info_t; +extern void *_data_offs; +void test() +{ + info_t *info = (info_t *) ((void *)((void *)1) + ((unsigned int)&_data_offs)); + my_func(info->var == 0); +}