From patchwork Thu Aug 19 23:18:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roger Sayle X-Patchwork-Id: 1518865 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: 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: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nextmovesoftware.com header.i=@nextmovesoftware.com header.a=rsa-sha256 header.s=default header.b=iZYM7O9u; 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GrLL01WWhz9sWw for ; Fri, 20 Aug 2021 09:18:30 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C87BC388B82F for ; Thu, 19 Aug 2021 23:18:27 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from server.nextmovesoftware.com (server.nextmovesoftware.com [162.254.253.69]) by sourceware.org (Postfix) with ESMTPS id 73870384F038 for ; Thu, 19 Aug 2021 23:18:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 73870384F038 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=nextmovesoftware.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nextmovesoftware.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=nextmovesoftware.com; s=default; h=Content-Type:MIME-Version:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=VUYA4DMmJZObCCqr/D52couwAUGG+ZplaJ5/7yCi71A=; b=iZYM7O9uAtZhk0eCwmpr1IaYGK ScfV5WZ7EhSzGEX04CpSFAFA2UK40hB9DSLTf8BLC0ck1mF9iHQUEvKmfsaoRY9VW77k+hLbet1zY yqR/o+zyzFofO7ANsOB8krNrTdtbuhgu7hu5CVGbl9iV0PwXR7yYvi4B/C0tpQNvDnVeWKVDbVbAE kxvVE4fcp4WnZXTfTB6kYn99L0zowMh10KbNsi4JAp/jAgDwxddBfamOnqlETosKfqNgmOblSqzIu deyPtBBERRxKe+he/riX4C4ow+B68fHERMs37XUpJHiil7JmwXkEHxjaGbcOkHVctTSr6zgIWMQ9K pr3gAfSA==; Received: from host109-154-46-127.range109-154.btcentralplus.com ([109.154.46.127]:58838 helo=Dell) by server.nextmovesoftware.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1mGrIT-0003FB-Tm for gcc-patches@gcc.gnu.org; Thu, 19 Aug 2021 19:18:06 -0400 From: "Roger Sayle" To: "'GCC Patches'" Subject: [PATCH] Simplify (truncate:QI (subreg:SI (reg:QI x))) to (reg:QI x) Date: Fri, 20 Aug 2021 00:18:03 +0100 Message-ID: <000f01d79550$77015fa0$65041ee0$@nextmovesoftware.com> MIME-Version: 1.0 X-Mailer: Microsoft Outlook 16.0 Thread-Index: AdeVT+NcpOJ2OJT5Tj6FvKB/nZ7svg== Content-Language: en-gb X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server.nextmovesoftware.com X-AntiAbuse: Original Domain - gcc.gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - nextmovesoftware.com X-Get-Message-Sender-Via: server.nextmovesoftware.com: authenticated_id: roger@nextmovesoftware.com X-Authenticated-Sender: server.nextmovesoftware.com: roger@nextmovesoftware.com X-Source: X-Source-Args: X-Source-Dir: X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Whilst working on a backend patch, I noticed that the middle-end's RTL optimizers weren't simplifying a truncation of a paradoxical subreg extension, though it does transform closely related (more complex) expressions. The main (first) part of this patch implements this simplification, reusing much of the logic already in place. I briefly considered suggesting that it's difficult to provide a new testcase for this change, but then realized the reviewer's response would be that this type of transformation should be self-tested in simplify-rtx, so this patch adds a bunch of tests that integer extensions and truncations are simplified as expected. No good deed goes unpunished and I was equally surprised to see that we don't currently simplify/check/defend (zero_extend:SI (reg:SI)), i.e. useless no-op extensions to the same mode. So I've added some logic to simplify (or more accurately prevent us generating dubious RTL for) those. This patch has been tested on x86_64-pc-linux-gnu with make bootstrap and "make -k check" with no new failures. Ok for mainline? 2021-08-20 Roger Sayle gcc/ChangeLog * simplify-rtx.c (simplify_truncation): Generalize simplification of (truncate:A (subreg:B X)). (simplify_unary_operation_1) [FLOAT_TRUNCATE, FLOAT_EXTEND, SIGN_EXTEND, ZERO_EXTEND]: Handle cases where the operand already has the desired machine mode. (test_scalar_int_ops): Add tests that useless extensions and truncations are optimized away. (test_scalar_int_ext_ops): New self-test function to confirm that truncations of extensions are correctly simplified. (test_scalar_int_ext_ops2): New self-test function to check truncations of truncations, extensions of extensions, and truncations of extensions. (test_scalar_ops): Call the above two functions with a representative sampling of integer machine modes. Roger --- Roger Sayle NextMove Software Cambridge, UK diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index a719f57..f3df614 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -813,23 +813,49 @@ simplify_context::simplify_truncation (machine_mode mode, rtx op, return simplify_gen_unary (GET_CODE (op), mode, XEXP (XEXP (op, 0), 0), mode); - /* (truncate:A (subreg:B (truncate:C X) 0)) is - (truncate:A X). */ + /* Simplifications of (truncate:A (subreg:B X 0)). */ if (GET_CODE (op) == SUBREG && is_a (mode, &int_mode) && SCALAR_INT_MODE_P (op_mode) && is_a (GET_MODE (SUBREG_REG (op)), &subreg_mode) - && GET_CODE (SUBREG_REG (op)) == TRUNCATE && subreg_lowpart_p (op)) { - rtx inner = XEXP (SUBREG_REG (op), 0); - if (GET_MODE_PRECISION (int_mode) <= GET_MODE_PRECISION (subreg_mode)) - return simplify_gen_unary (TRUNCATE, int_mode, inner, - GET_MODE (inner)); - else - /* If subreg above is paradoxical and C is narrower - than A, return (subreg:A (truncate:C X) 0). */ - return simplify_gen_subreg (int_mode, SUBREG_REG (op), subreg_mode, 0); + /* (truncate:A (subreg:B (truncate:C X) 0)) is (truncate:A X). */ + if (GET_CODE (SUBREG_REG (op)) == TRUNCATE) + { + rtx inner = XEXP (SUBREG_REG (op), 0); + if (GET_MODE_PRECISION (int_mode) + <= GET_MODE_PRECISION (subreg_mode)) + return simplify_gen_unary (TRUNCATE, int_mode, inner, + GET_MODE (inner)); + else + /* If subreg above is paradoxical and C is narrower + than A, return (subreg:A (truncate:C X) 0). */ + return simplify_gen_subreg (int_mode, SUBREG_REG (op), + subreg_mode, 0); + } + + /* Simplifications of (truncate:A (subreg:B X:C 0)) with + paradoxical subregs (B is wider than C). */ + if (is_a (op_mode, &int_op_mode)) + { + unsigned int int_op_prec = GET_MODE_PRECISION (int_op_mode); + unsigned int subreg_prec = GET_MODE_PRECISION (subreg_mode); + if (int_op_prec > subreg_mode) + { + if (int_mode == subreg_mode) + return SUBREG_REG (op); + if (GET_MODE_PRECISION (int_mode) < subreg_prec) + return simplify_gen_unary (TRUNCATE, int_mode, + SUBREG_REG (op), subreg_mode); + } + /* Simplification of (truncate:A (subreg:B X:C 0)) where + A is narrower than B and B is narrower than C. */ + else if (int_op_prec < subreg_mode + && GET_MODE_PRECISION (int_mode) < int_op_prec) + return simplify_gen_unary (TRUNCATE, int_mode, + SUBREG_REG (op), subreg_mode); + } } /* (truncate:A (truncate:B X)) is (truncate:A X). */ @@ -1245,6 +1271,10 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, break; case FLOAT_TRUNCATE: + /* Check for useless truncation. */ + if (GET_MODE (op) == mode) + return op; + if (DECIMAL_FLOAT_MODE_P (mode)) break; @@ -1297,6 +1327,10 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, break; case FLOAT_EXTEND: + /* Check for useless extension. */ + if (GET_MODE (op) == mode) + return op; + if (DECIMAL_FLOAT_MODE_P (mode)) break; @@ -1410,6 +1444,10 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, break; case SIGN_EXTEND: + /* Check for useless extension. */ + if (GET_MODE (op) == mode) + return op; + /* (sign_extend (truncate (minus (label_ref L1) (label_ref L2)))) becomes just the MINUS if its mode is MODE. This allows folding switch statements on machines using casesi (such as @@ -1580,6 +1618,10 @@ simplify_context::simplify_unary_operation_1 (rtx_code code, machine_mode mode, break; case ZERO_EXTEND: + /* Check for useless extension. */ + if (GET_MODE (op) == mode) + return op; + /* Check for a zero extension of a subreg of a promoted variable, where the promotion is zero-extended, and the target mode is the same as the variable's promotion. */ @@ -7563,8 +7605,92 @@ test_scalar_int_ops (machine_mode mode) simplify_gen_binary (IOR, mode, and_op0_6, and_op1_6)); ASSERT_RTX_EQ (simplify_gen_binary (AND, mode, and_op0_op1, six), simplify_gen_binary (AND, mode, and_op0_6, and_op1_6)); + + /* Test useless extensions are eliminated. */ + ASSERT_RTX_EQ (op0, simplify_gen_unary (TRUNCATE, mode, op0, mode)); + ASSERT_RTX_EQ (op0, simplify_gen_unary (ZERO_EXTEND, mode, op0, mode)); + ASSERT_RTX_EQ (op0, simplify_gen_unary (SIGN_EXTEND, mode, op0, mode)); + ASSERT_RTX_EQ (op0, lowpart_subreg (mode, op0, mode)); +} + +/* Verify some simplifications of integer extension/truncation. + Machine mode BMODE is the guaranteed wider than SMODE. */ + +static void +test_scalar_int_ext_ops (machine_mode bmode, machine_mode smode) +{ + rtx sreg = make_test_reg (smode); + + /* Check truncation of extension. */ + ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, + simplify_gen_unary (ZERO_EXTEND, bmode, + sreg, smode), + bmode), + sreg); + ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, + simplify_gen_unary (SIGN_EXTEND, bmode, + sreg, smode), + bmode), + sreg); + ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, + lowpart_subreg (bmode, sreg, smode), + bmode), + sreg); } +/* Verify more simplifications of integer extension/truncation. + BMODE is wider than MMODE which is wider than SMODE. */ + +static void +test_scalar_int_ext_ops2 (machine_mode bmode, machine_mode mmode, + machine_mode smode) +{ + rtx breg = make_test_reg (bmode); + rtx mreg = make_test_reg (mmode); + rtx sreg = make_test_reg (smode); + + /* Check truncate of truncate. */ + ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, + simplify_gen_unary (TRUNCATE, mmode, + breg, bmode), + mmode), + simplify_gen_unary (TRUNCATE, smode, breg, bmode)); + + /* Check extension of extension. */ + ASSERT_RTX_EQ (simplify_gen_unary (ZERO_EXTEND, bmode, + simplify_gen_unary (ZERO_EXTEND, mmode, + sreg, smode), + mmode), + simplify_gen_unary (ZERO_EXTEND, bmode, sreg, smode)); + ASSERT_RTX_EQ (simplify_gen_unary (SIGN_EXTEND, bmode, + simplify_gen_unary (SIGN_EXTEND, mmode, + sreg, smode), + mmode), + simplify_gen_unary (SIGN_EXTEND, bmode, sreg, smode)); + ASSERT_RTX_EQ (simplify_gen_unary (SIGN_EXTEND, bmode, + simplify_gen_unary (ZERO_EXTEND, mmode, + sreg, smode), + mmode), + simplify_gen_unary (ZERO_EXTEND, bmode, sreg, smode)); + + /* Check truncation of extension. */ + ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, + simplify_gen_unary (ZERO_EXTEND, bmode, + mreg, mmode), + bmode), + simplify_gen_unary (TRUNCATE, smode, mreg, mmode)); + ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, + simplify_gen_unary (SIGN_EXTEND, bmode, + mreg, mmode), + bmode), + simplify_gen_unary (TRUNCATE, smode, mreg, mmode)); + ASSERT_RTX_EQ (simplify_gen_unary (TRUNCATE, smode, + lowpart_subreg (bmode, mreg, mmode), + bmode), + simplify_gen_unary (TRUNCATE, smode, mreg, mmode)); +} + + /* Verify some simplifications involving scalar expressions. */ static void @@ -7576,6 +7702,18 @@ test_scalar_ops () if (SCALAR_INT_MODE_P (mode) && mode != BImode) test_scalar_int_ops (mode); } + + test_scalar_int_ext_ops (HImode, QImode); + test_scalar_int_ext_ops (SImode, QImode); + test_scalar_int_ext_ops (SImode, HImode); + test_scalar_int_ext_ops (DImode, QImode); + test_scalar_int_ext_ops (DImode, HImode); + test_scalar_int_ext_ops (DImode, SImode); + + test_scalar_int_ext_ops2 (SImode, HImode, QImode); + test_scalar_int_ext_ops2 (DImode, HImode, QImode); + test_scalar_int_ext_ops2 (DImode, SImode, QImode); + test_scalar_int_ext_ops2 (DImode, SImode, HImode); } /* Test vector simplifications involving VEC_DUPLICATE in which the