From patchwork Sun Nov 5 18:46:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859582 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 4SNk3J2hm1z1yQL for ; Mon, 6 Nov 2023 05:46:36 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6E5DF3858422 for ; Sun, 5 Nov 2023 18:46:34 +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 D74E73858CDB for ; Sun, 5 Nov 2023 18:46:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D74E73858CDB 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 D74E73858CDB 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=1699209983; cv=none; b=HZJ6c2/I7Y4Ixg9/K10hTPlI7x4iD78QM0EuwzyoYTskULGrMtzhTy4yCSK6KpjNETa6zKb5JnG9kg616NjNVVvUV+JfN3xuQm8abKMECNgbcT+cT3dkJHmfTp3VutenPD5kccCSMJq6uFShI/3eiGC79O8ZMymzMyp9CWd2U/E= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699209983; c=relaxed/simple; bh=exSmabGHEnDNHmo4Tqso7Zpv01B77MgPy9ko2ul2j2I=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=tQ5xshM0D8VXHoOjrkeb64quGm6FgTLFbSB6DbXHQyCb2b41b5GGhRd6phBp1R5Z+nAkXYYddwq8k5x+dTl3LtwT/7OQBnt5RJBETNIO7/iU5xtq4l9xNYL6Vxv9lrU2J/CjDG2ELsVCSrNWUa3MM2gLtMunRS9ohHOWGK9d5+k= 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 57A8BC15; Sun, 5 Nov 2023 10:47:04 -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 13AC13F703; Sun, 5 Nov 2023 10:46:19 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 01/12] mode-switching: Tweak the macro/hook documentation References: Date: Sun, 05 Nov 2023 18:46:18 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.4 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 I found the documentation for the mode-switching macros/hooks a bit hard to follow at first. This patch tries to add the information that I think would have made it easier to understand. Of course, documentation preferences are personal, and so I could be changing something that others understood to something that seems impenetrable. Some notes on specific changes: - "in an optimizing compilation" didn't seem accurate; the pass is run even at -O0, and often needs to be for correctness. - "at run time" meant when the compiler was run, rather than when the compiled code was run. - Removing the list of optional macros isn't a clarification, but it means that upcoming patches don't create an absurdly long list. - I don't really understand the purpose of TARGET_MODE_PRIORITY, so I mostly left that alone. gcc/ * target.def: Tweak documentation of mode-switching hooks. * doc/tm.texi.in (OPTIMIZE_MODE_SWITCHING): Tweak documentation. (NUM_MODES_FOR_MODE_SWITCHING): Likewise. * doc/tm.texi: Regenerate. --- gcc/doc/tm.texi | 69 ++++++++++++++++++++++++++++------------------ gcc/doc/tm.texi.in | 26 +++++++++-------- gcc/target.def | 43 ++++++++++++++++++----------- 3 files changed, 84 insertions(+), 54 deletions(-) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index f7ac806ff15..759331a2c96 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10368,7 +10368,7 @@ The following macros control mode switching optimizations: @defmac OPTIMIZE_MODE_SWITCHING (@var{entity}) Define this macro if the port needs extra instructions inserted for mode -switching in an optimizing compilation. +switching. For an example, the SH4 can perform both single and double precision floating point operations, but to perform a single precision operation, @@ -10378,73 +10378,88 @@ purpose register as a scratch register, hence these FPSCR sets have to be inserted before reload, i.e.@: you cannot put this into instruction emitting or @code{TARGET_MACHINE_DEPENDENT_REORG}. -You can have multiple entities that are mode-switched, and select at run time -which entities actually need it. @code{OPTIMIZE_MODE_SWITCHING} should -return nonzero for any @var{entity} that needs mode-switching. +You can have multiple entities that are mode-switched, some of which might +only be needed conditionally. The entities are identified by their index +into the @code{NUM_MODES_FOR_MODE_SWITCHING} initializer, with the length +of the initializer determining the number of entities. + +@code{OPTIMIZE_MODE_SWITCHING} should return nonzero for any @var{entity} +that needs mode-switching. + If you define this macro, you also have to define @code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED}, @code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}. -@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT} -are optional. +The other macros in this section are optional. @end defmac @defmac NUM_MODES_FOR_MODE_SWITCHING If you define @code{OPTIMIZE_MODE_SWITCHING}, you have to define this as initializer for an array of integers. Each initializer element N refers to an entity that needs mode switching, and specifies the number -of different modes that might need to be set for this entity. -The position of the initializer in the initializer---starting counting at +of different modes that are defined for that entity. +The position of the element in the initializer---starting counting at zero---determines the integer that is used to refer to the mode-switched entity in question. -In macros that take mode arguments / yield a mode result, modes are -represented as numbers 0 @dots{} N @minus{} 1. N is used to specify that no mode -switch is needed / supplied. +Modes are represented as numbers 0 @dots{} N @minus{} 1. +In mode arguments and return values, N either represents an unknown +mode or ``no mode'', depending on context. @end defmac @deftypefn {Target Hook} void TARGET_MODE_EMIT (int @var{entity}, int @var{mode}, int @var{prev_mode}, HARD_REG_SET @var{regs_live}) Generate one or more insns to set @var{entity} to @var{mode}. @var{hard_reg_live} is the set of hard registers live at the point where the insn(s) are to be inserted. @var{prev_moxde} indicates the mode -to switch from. Sets of a lower numbered entity will be emitted before +to switch from, or is the number of modes if the previous mode is not +known. Sets of a lower numbered entity will be emitted before sets of a higher numbered entity to a mode of the same or lower priority. @end deftypefn @deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn}) @var{entity} is an integer specifying a mode-switched entity. -If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro -to return an integer value not larger than the corresponding element -in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity} -must be switched into prior to the execution of @var{insn}. +If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook +to return the mode that @var{entity} must be switched into prior to the +execution of @var{insn}, or the number of modes if @var{insn} has no +such requirement. @end deftypefn @deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn}) @var{entity} is an integer specifying a mode-switched entity. -If this macro is defined, it is evaluated for every @var{insn} during mode -switching. It determines the mode that an insn results -in (if different from the incoming mode). +If this hook is defined, it is evaluated for every @var{insn} during mode +switching. It returns the mode that @var{entity} is in after @var{insn} +has been executed. @var{mode} is the mode that @var{entity} was in +before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}. + +@var{mode} is equal to the number of modes defined for @var{entity} +if the mode before @var{insn} is unknown. The hook should likewise return +the number of modes if it does not know what mode @var{entity} has after +@var{insn}. + +Not defining the hook is equivalent to returning @var{mode}. @end deftypefn @deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity}) -If this macro is defined, it is evaluated for every @var{entity} that -needs mode switching. It should evaluate to an integer, which is a mode -that @var{entity} is assumed to be switched to at function entry. +If this hook is defined, it is evaluated for every @var{entity} that +needs mode switching. It should return the mode that @var{entity} is +guaranteed to be in on entry to the function, or the number of modes +if there is no such guarantee. If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT} must be defined. @end deftypefn @deftypefn {Target Hook} int TARGET_MODE_EXIT (int @var{entity}) -If this macro is defined, it is evaluated for every @var{entity} that -needs mode switching. It should evaluate to an integer, which is a mode -that @var{entity} is assumed to be switched to at function exit. +If this hook is defined, it is evaluated for every @var{entity} that +needs mode switching. It should return the mode that @var{entity} must +be in on return from the function, or the number of modes if there is no +such requirement. If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY} must be defined. @end deftypefn @deftypefn {Target Hook} int TARGET_MODE_PRIORITY (int @var{entity}, int @var{n}) -This macro specifies the order in which modes for @var{entity} +This hook specifies the order in which modes for @var{entity} are processed. 0 is the highest priority, @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest. -The value of the macro should be an integer designating a mode +The hook returns an integer designating a mode for @var{entity}. For any fixed @var{entity}, @code{mode_priority} (@var{entity}, @var{n}) shall be a bijection in 0 @dots{} @code{num_modes_for_mode_switching[@var{entity}] - 1}. diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 141027e0bb4..a7b7aa289d8 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -6932,7 +6932,7 @@ The following macros control mode switching optimizations: @defmac OPTIMIZE_MODE_SWITCHING (@var{entity}) Define this macro if the port needs extra instructions inserted for mode -switching in an optimizing compilation. +switching. For an example, the SH4 can perform both single and double precision floating point operations, but to perform a single precision operation, @@ -6942,27 +6942,31 @@ purpose register as a scratch register, hence these FPSCR sets have to be inserted before reload, i.e.@: you cannot put this into instruction emitting or @code{TARGET_MACHINE_DEPENDENT_REORG}. -You can have multiple entities that are mode-switched, and select at run time -which entities actually need it. @code{OPTIMIZE_MODE_SWITCHING} should -return nonzero for any @var{entity} that needs mode-switching. +You can have multiple entities that are mode-switched, some of which might +only be needed conditionally. The entities are identified by their index +into the @code{NUM_MODES_FOR_MODE_SWITCHING} initializer, with the length +of the initializer determining the number of entities. + +@code{OPTIMIZE_MODE_SWITCHING} should return nonzero for any @var{entity} +that needs mode-switching. + If you define this macro, you also have to define @code{NUM_MODES_FOR_MODE_SWITCHING}, @code{TARGET_MODE_NEEDED}, @code{TARGET_MODE_PRIORITY} and @code{TARGET_MODE_EMIT}. -@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, and @code{TARGET_MODE_EXIT} -are optional. +The other macros in this section are optional. @end defmac @defmac NUM_MODES_FOR_MODE_SWITCHING If you define @code{OPTIMIZE_MODE_SWITCHING}, you have to define this as initializer for an array of integers. Each initializer element N refers to an entity that needs mode switching, and specifies the number -of different modes that might need to be set for this entity. -The position of the initializer in the initializer---starting counting at +of different modes that are defined for that entity. +The position of the element in the initializer---starting counting at zero---determines the integer that is used to refer to the mode-switched entity in question. -In macros that take mode arguments / yield a mode result, modes are -represented as numbers 0 @dots{} N @minus{} 1. N is used to specify that no mode -switch is needed / supplied. +Modes are represented as numbers 0 @dots{} N @minus{} 1. +In mode arguments and return values, N either represents an unknown +mode or ``no mode'', depending on context. @end defmac @hook TARGET_MODE_EMIT diff --git a/gcc/target.def b/gcc/target.def index 42622177ef9..3dae33522f1 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -7020,51 +7020,62 @@ DEFHOOK "Generate one or more insns to set @var{entity} to @var{mode}.\n\ @var{hard_reg_live} is the set of hard registers live at the point where\n\ the insn(s) are to be inserted. @var{prev_moxde} indicates the mode\n\ -to switch from. Sets of a lower numbered entity will be emitted before\n\ +to switch from, or is the number of modes if the previous mode is not\n\ +known. Sets of a lower numbered entity will be emitted before\n\ sets of a higher numbered entity to a mode of the same or lower priority.", void, (int entity, int mode, int prev_mode, HARD_REG_SET regs_live), NULL) DEFHOOK (needed, "@var{entity} is an integer specifying a mode-switched entity.\n\ -If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro\n\ -to return an integer value not larger than the corresponding element\n\ -in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity}\n\ -must be switched into prior to the execution of @var{insn}.", +If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook\n\ +to return the mode that @var{entity} must be switched into prior to the\n\ +execution of @var{insn}, or the number of modes if @var{insn} has no\n\ +such requirement.", int, (int entity, rtx_insn *insn), NULL) DEFHOOK (after, "@var{entity} is an integer specifying a mode-switched entity.\n\ -If this macro is defined, it is evaluated for every @var{insn} during mode\n\ -switching. It determines the mode that an insn results\n\ -in (if different from the incoming mode).", +If this hook is defined, it is evaluated for every @var{insn} during mode\n\ +switching. It returns the mode that @var{entity} is in after @var{insn}\n\ +has been executed. @var{mode} is the mode that @var{entity} was in\n\ +before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}.\n\ +\n\ +@var{mode} is equal to the number of modes defined for @var{entity}\n\ +if the mode before @var{insn} is unknown. The hook should likewise return\n\ +the number of modes if it does not know what mode @var{entity} has after\n\ +@var{insn}.\n\ +\n\ +Not defining the hook is equivalent to returning @var{mode}.", int, (int entity, int mode, rtx_insn *insn), NULL) DEFHOOK (entry, - "If this macro is defined, it is evaluated for every @var{entity} that\n\ -needs mode switching. It should evaluate to an integer, which is a mode\n\ -that @var{entity} is assumed to be switched to at function entry.\n\ + "If this hook is defined, it is evaluated for every @var{entity} that\n\ +needs mode switching. It should return the mode that @var{entity} is\n\ +guaranteed to be in on entry to the function, or the number of modes\n\ +if there is no such guarantee.\n\ If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT}\n\ must be defined.", int, (int entity), NULL) DEFHOOK (exit, - "If this macro is defined, it is evaluated for every @var{entity} that\n\ -needs mode switching. It should evaluate to an integer, which is a mode\n\ -that @var{entity} is assumed to be switched to at function exit.\n\ + "If this hook is defined, it is evaluated for every @var{entity} that\n\ +needs mode switching. It should return the mode that @var{entity} must\n\ +be in on return from the function, or the number of modes if there is no\n\ +such requirement.\n\ If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY}\n\ must be defined.", int, (int entity), NULL) DEFHOOK (priority, - "This macro specifies the order in which modes for @var{entity}\n\ + "This hook specifies the order in which modes for @var{entity}\n\ are processed. 0 is the highest priority,\n\ @code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest.\n\ -The value of the macro should be an integer designating a mode\n\ +The hook returns an integer designating a mode\n\ for @var{entity}. For any fixed @var{entity}, @code{mode_priority}\n\ (@var{entity}, @var{n}) shall be a bijection in 0 @dots{}\n\ @code{num_modes_for_mode_switching[@var{entity}] - 1}.", From patchwork Sun Nov 5 18:46:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859583 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 4SNk3g3pvzz1yQL for ; Mon, 6 Nov 2023 05:46:55 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 952A73856961 for ; Sun, 5 Nov 2023 18:46:53 +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 555843856DDC for ; Sun, 5 Nov 2023 18:46:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 555843856DDC 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 555843856DDC 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=1699210003; cv=none; b=QevBcMCgU1yY0VBjISYe5dk7lcfEFWDaj0DusZSuDprJlJ+1wShfUf0LY9jdVbKKgL9MKfoRqkFVnCqGZXbSt69EeQeWgEYBmhiSDEuS9VXzHErKoQzakMnr1gxL+aNPEU/HfD+11He7AYPK3EKr8hMCn0RI+WRWFmW45u9GIpg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210003; c=relaxed/simple; bh=uaTo/AvwLzbmBYtyTmy6hqI/VOXIzKPDqR3Vs0yXMPA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Y5fCfQBRPaIWZf5u55QXdcbkWzjd83jTEKuRSW4/1BbEbGIdnuzjDEpvT22gvevifh4LlTLlzmtJAvYULhXFSvSRP981ddPWGf5n4whFyByesFvg7S2Ik3hU0Ot55BvPwQ+GDW8M7rj5x+SmOy2Sgbku8dd5s6Rof0NMrzeRmGk= 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 C077AC15; Sun, 5 Nov 2023 10:47:25 -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 7D86A3F703; Sun, 5 Nov 2023 10:46:41 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 02/12] mode-switching: Add note problem References: Date: Sun, 05 Nov 2023 18:46:40 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.4 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 optimize_mode_switching uses REG_DEAD notes to track register liveness, but it failed to tell DF to calculate up-to-date notes. Noticed by inspection. I don't have a testcase that fails because of this. gcc/ * mode-switching.cc (optimize_mode_switching): Call df_note_add_problem. --- I was tempted to apply this as obvious, but wasn't sure if I was missing something. gcc/mode-switching.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index c3e4d24de9b..8577069bde1 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -541,6 +541,7 @@ optimize_mode_switching (void) pre_exit = create_pre_exit (n_entities, entity_map, num_modes); } + df_note_add_problem (); df_analyze (); /* Create the bitmap vectors. */ From patchwork Sun Nov 5 18:47:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859584 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 4SNk455Vmfz1yQL for ; Mon, 6 Nov 2023 05:47:17 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CFDAC3857C40 for ; Sun, 5 Nov 2023 18:47:15 +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 9611C3857712 for ; Sun, 5 Nov 2023 18:47:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9611C3857712 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 9611C3857712 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=1699210025; cv=none; b=jwwSM1QaNSIB4gQNWU8SOcPmZFXn7Q0c1zSZTpe0qaiQHk81c8lOIQd1ZHsffy9OyVgs51b+QF3SXAyvAvUI0G3a6Yi9k1wBYnlnNsvM8oBT0qsyBVHzaL0MxFZ5m9vyT4i+eMbf9jKmoi6Jumbcl7rK/hnq8vl+lhtG63cj5Y0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210025; c=relaxed/simple; bh=A82VYLauEK1CZh3UOEP10sYo/zS/qKFUMmiJgfLQGJ4=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Hi/xtKPR4Ou4jDU0IWrvUkcVmbgN1apYARSuAF215qixTTchgjPo8NPpcLmozUw7QyiHXPw2bS4PYRulvcNqhzeqqErPFonERHSUW/Cr3hTelVff+/KVfdZTNUCeqD78wdz3mcDDX94ruo8SMnGLy5gtLZsbOc1g9zRvojlPZmQ= 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 2F213C15; Sun, 5 Nov 2023 10:47:48 -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 E00453F703; Sun, 5 Nov 2023 10:47:03 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 03/12] mode-switching: Avoid quadractic list operation References: Date: Sun, 05 Nov 2023 18:47:02 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.4 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 add_seginfo chained insn information to the end of a list by starting at the head of the list. This patch avoids the quadraticness by keeping track of the tail pointer. gcc/ * mode-switching.cc (add_seginfo): Replace head pointer with a pointer to the tail pointer. (optimize_mode_switching): Update calls accordingly. --- gcc/mode-switching.cc | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index 8577069bde1..bebe89d5fd2 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -162,23 +162,14 @@ new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET ®s_live) } /* Add a seginfo element to the end of a list. - HEAD is a pointer to the list beginning. + TAIL is a pointer to the list's null terminator. INFO is the structure to be linked in. */ static void -add_seginfo (struct bb_info *head, struct seginfo *info) +add_seginfo (struct seginfo ***tail_ptr, struct seginfo *info) { - struct seginfo *ptr; - - if (head->seginfo == NULL) - head->seginfo = info; - else - { - ptr = head->seginfo; - while (ptr->next != NULL) - ptr = ptr->next; - ptr->next = info; - } + **tail_ptr = info; + *tail_ptr = &info->next; } /* Record in LIVE that register REG died. */ @@ -574,6 +565,7 @@ optimize_mode_switching (void) Also compute the initial transparency settings. */ FOR_EACH_BB_FN (bb, cfun) { + struct seginfo **tail_ptr = &info[bb->index].seginfo; struct seginfo *ptr; int last_mode = no_mode; bool any_set_required = false; @@ -599,7 +591,7 @@ optimize_mode_switching (void) if (ins_pos != BB_END (bb)) ins_pos = NEXT_INSN (ins_pos); ptr = new_seginfo (no_mode, ins_pos, live_now); - add_seginfo (info + bb->index, ptr); + add_seginfo (&tail_ptr, ptr); for (i = 0; i < no_mode; i++) clear_mode_bit (transp[bb->index], j, i); } @@ -617,7 +609,7 @@ optimize_mode_switching (void) any_set_required = true; last_mode = mode; ptr = new_seginfo (mode, insn, live_now); - add_seginfo (info + bb->index, ptr); + add_seginfo (&tail_ptr, ptr); for (i = 0; i < no_mode; i++) clear_mode_bit (transp[bb->index], j, i); } @@ -646,7 +638,7 @@ optimize_mode_switching (void) if (!any_set_required) { ptr = new_seginfo (no_mode, BB_END (bb), live_now); - add_seginfo (info + bb->index, ptr); + add_seginfo (&tail_ptr, ptr); if (last_mode != no_mode) for (i = 0; i < no_mode; i++) clear_mode_bit (transp[bb->index], j, i); From patchwork Sun Nov 5 18:47:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859585 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 4SNk4X6hmWz1yQL for ; Mon, 6 Nov 2023 05:47:40 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BFB5D3856DE8 for ; Sun, 5 Nov 2023 18:47:38 +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 132243856DDA for ; Sun, 5 Nov 2023 18:47:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 132243856DDA 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 132243856DDA 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=1699210047; cv=none; b=nA0IUriAwJxRzEHOBTC1jWM3T7Pm5gFeTOi91eM2PM+btqT+tczt3L63mFx3SMaMp40JtrPbd/7lj6eqAgRrJs60jqVvijVLoVevnDOpe5OBQ/IgFIwPDW1mj3GCym91Cn5k1jmzITEdzhjtdCVqKfrzwFupzCAHkzlMItS8NY0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210047; c=relaxed/simple; bh=qX7WfmeLOFz9M+CPx//uY8b5+i8/WmTctH6/eTkiinE=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Np0poYQcj4D7YeHWst0ha2NtQjXQeSSoLsWwiG1fkA+xrWvKKJCwRlyUEJk02qLIdYO5wXW4FRbaTEiHpTka3T/tSuaiDgedEH2HH+MpnTxd6f8LRdYRsKL9aitTjxnkQekRp459c6abjz5iSZuBTmzstPUBofyOjYeV8qJQpG8= 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 8B76FC15; Sun, 5 Nov 2023 10:48:09 -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 486173F703; Sun, 5 Nov 2023 10:47:25 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 04/12] mode-switching: Fix the mode passed to the emit hook References: Date: Sun, 05 Nov 2023 18:47:24 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.4 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 optimize_mode_switching passes an entity's current mode (if known) to the emit hook. However, the mode that it passed ignored the effect of the after hook. Instead, the mode for the first emit call in a block was taken from the incoming mode, whereas the mode for each subsequent emit call was taken from the result of the previous call. The previous pass through the insns already calculated the correct mode, so this patch records it in the seginfo structure. (There was a 32-bit hole on 64-bit hosts, so this doesn't increase the size of the structure for them.) gcc/ * mode-switching.cc (seginfo): Add a prev_mode field. (new_seginfo): Take and initialize the prev_mode. (optimize_mode_switching): Update calls accordingly. Use the recorded modes during the emit phase, rather than computing one on the fly. --- gcc/mode-switching.cc | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index bebe89d5fd2..12ddbd6adfa 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see NEXT is the next insn in the same basic block. */ struct seginfo { + int prev_mode; int mode; rtx_insn *insn_ptr; struct seginfo *next; @@ -140,20 +141,22 @@ commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info) return need_commit; } -/* Allocate a new BBINFO structure, initialized with the MODE, INSN, - and REGS_LIVE parameters. +/* Allocate a new BBINFO structure, initialized with the PREV_MODE, MODE, + INSN, and REGS_LIVE parameters. INSN may not be a NOTE_INSN_BASIC_BLOCK, unless it is an empty basic block; that allows us later to insert instructions in a FIFO-like manner. */ static struct seginfo * -new_seginfo (int mode, rtx_insn *insn, const HARD_REG_SET ®s_live) +new_seginfo (int prev_mode, int mode, rtx_insn *insn, + const HARD_REG_SET ®s_live) { struct seginfo *ptr; gcc_assert (!NOTE_INSN_BASIC_BLOCK_P (insn) || insn == BB_END (NOTE_BASIC_BLOCK (insn))); ptr = XNEW (struct seginfo); + ptr->prev_mode = prev_mode; ptr->mode = mode; ptr->insn_ptr = insn; ptr->next = NULL; @@ -590,7 +593,7 @@ optimize_mode_switching (void) gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos)); if (ins_pos != BB_END (bb)) ins_pos = NEXT_INSN (ins_pos); - ptr = new_seginfo (no_mode, ins_pos, live_now); + ptr = new_seginfo (no_mode, no_mode, ins_pos, live_now); add_seginfo (&tail_ptr, ptr); for (i = 0; i < no_mode; i++) clear_mode_bit (transp[bb->index], j, i); @@ -606,12 +609,12 @@ optimize_mode_switching (void) if (mode != no_mode && mode != last_mode) { - any_set_required = true; - last_mode = mode; - ptr = new_seginfo (mode, insn, live_now); + ptr = new_seginfo (last_mode, mode, insn, live_now); add_seginfo (&tail_ptr, ptr); for (i = 0; i < no_mode; i++) clear_mode_bit (transp[bb->index], j, i); + any_set_required = true; + last_mode = mode; } if (targetm.mode_switching.after) @@ -637,7 +640,7 @@ optimize_mode_switching (void) mark the block as nontransparent. */ if (!any_set_required) { - ptr = new_seginfo (no_mode, BB_END (bb), live_now); + ptr = new_seginfo (last_mode, no_mode, BB_END (bb), live_now); add_seginfo (&tail_ptr, ptr); if (last_mode != no_mode) for (i = 0; i < no_mode; i++) @@ -778,9 +781,9 @@ optimize_mode_switching (void) FOR_EACH_BB_FN (bb, cfun) { struct seginfo *ptr, *next; - int cur_mode = bb_info[j][bb->index].mode_in; + struct seginfo *first = bb_info[j][bb->index].seginfo; - for (ptr = bb_info[j][bb->index].seginfo; ptr; ptr = next) + for (ptr = first; ptr; ptr = next) { next = ptr->next; if (ptr->mode != no_mode) @@ -790,14 +793,15 @@ optimize_mode_switching (void) rtl_profile_for_bb (bb); start_sequence (); + int cur_mode = (ptr == first && ptr->prev_mode == no_mode + ? bb_info[j][bb->index].mode_in + : ptr->prev_mode); + targetm.mode_switching.emit (entity_map[j], ptr->mode, cur_mode, ptr->regs_live); mode_set = get_insns (); end_sequence (); - /* modes kill each other inside a basic block. */ - cur_mode = ptr->mode; - /* Insert MODE_SET only if it is nonempty. */ if (mode_set != NULL_RTX) { From patchwork Sun Nov 5 18:47:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859586 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 4SNk4v5Fxqz1yQL for ; Mon, 6 Nov 2023 05:47:59 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C5917385840F for ; Sun, 5 Nov 2023 18:47:57 +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 658F53857B93 for ; Sun, 5 Nov 2023 18:47:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 658F53857B93 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 658F53857B93 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=1699210067; cv=none; b=s0dBHo3gSbwiiVeL5ioHy80X2CPw5bELGQBPktxTjXyo6wQ+xtbtZ0BLLFrYE4ljclMq3aQAfZO7wzOzAqAsLrZSYb1OTeoMquYqSwelnAZTmM/hzPURiIf4J4J0qPo499WhDjw9OAd8J19SEUsRDNSk2bOE3WyK6w7fPNnu7is= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210067; c=relaxed/simple; bh=9rif97TBJvNxR85aY7HPVK7rn24N56+gKilYmmnSVmI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=cA57dCukvrIrZRJCOGJxvGTyOjaL74PKGcciDsIEnzx1Fok/k48VHZWJcfH9f8EXS4yHzXOS3VZ04OEWL1TOtJ53O+cmmAVBGUczOH/cPmWHEbt46Ynb8vBcP0knTHRBRmJojCE//duXZhL1jprnZFXMXDh/EX/CspdZvEtkSr8= 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 E666DC15; Sun, 5 Nov 2023 10:48:29 -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 A35723F703; Sun, 5 Nov 2023 10:47:45 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 05/12] mode-switching: Simplify recording of transparency References: Date: Sun, 05 Nov 2023 18:47:44 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.4 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 For a given block, an entity is either transparent for all modes or for none. Each update to the transparency set therefore used a loop like: for (i = 0; i < no_mode; i++) clear_mode_bit (transp[bb->index], j, i); This patch instead starts out with a bit-per-block bitmap and updates the main bitmap at the end. This isn't much of a simplification on its own. The main purpose is to simplify later patches. gcc/ * mode-switching.cc (optimize_mode_switching): Initially compute transparency in a bit-per-block bitmap. --- gcc/mode-switching.cc | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index 12ddbd6adfa..03dd4c1ebe4 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -556,6 +556,8 @@ optimize_mode_switching (void) bitmap_vector_clear (antic, last_basic_block_for_fn (cfun)); bitmap_vector_clear (comp, last_basic_block_for_fn (cfun)); + auto_sbitmap transp_all (last_basic_block_for_fn (cfun)); + for (j = n_entities - 1; j >= 0; j--) { int e = entity_map[j]; @@ -563,6 +565,8 @@ optimize_mode_switching (void) struct bb_info *info = bb_info[j]; rtx_insn *insn; + bitmap_ones (transp_all); + /* Determine what the first use (if any) need for a mode of entity E is. This will be the mode that is anticipatable for this block. Also compute the initial transparency settings. */ @@ -595,8 +599,7 @@ optimize_mode_switching (void) ins_pos = NEXT_INSN (ins_pos); ptr = new_seginfo (no_mode, no_mode, ins_pos, live_now); add_seginfo (&tail_ptr, ptr); - for (i = 0; i < no_mode; i++) - clear_mode_bit (transp[bb->index], j, i); + bitmap_clear_bit (transp_all, bb->index); } } @@ -611,8 +614,7 @@ optimize_mode_switching (void) { ptr = new_seginfo (last_mode, mode, insn, live_now); add_seginfo (&tail_ptr, ptr); - for (i = 0; i < no_mode; i++) - clear_mode_bit (transp[bb->index], j, i); + bitmap_clear_bit (transp_all, bb->index); any_set_required = true; last_mode = mode; } @@ -643,8 +645,7 @@ optimize_mode_switching (void) ptr = new_seginfo (last_mode, no_mode, BB_END (bb), live_now); add_seginfo (&tail_ptr, ptr); if (last_mode != no_mode) - for (i = 0; i < no_mode; i++) - clear_mode_bit (transp[bb->index], j, i); + bitmap_clear_bit (transp_all, bb->index); } } if (targetm.mode_switching.entry && targetm.mode_switching.exit) @@ -667,8 +668,7 @@ optimize_mode_switching (void) an extra check in make_preds_opaque. We also need this to avoid confusing pre_edge_lcm when antic is cleared but transp and comp are set. */ - for (i = 0; i < no_mode; i++) - clear_mode_bit (transp[bb->index], j, i); + bitmap_clear_bit (transp_all, bb->index); /* Insert a fake computing definition of MODE into entry blocks which compute no mode. This represents the mode on @@ -688,6 +688,9 @@ optimize_mode_switching (void) FOR_EACH_BB_FN (bb, cfun) { + if (!bitmap_bit_p (transp_all, bb->index)) + clear_mode_bit (transp[bb->index], j, m); + if (info[bb->index].seginfo->mode == m) set_mode_bit (antic[bb->index], j, m); From patchwork Sun Nov 5 18:48:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859587 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 4SNk5L1WYtz1yQL for ; Mon, 6 Nov 2023 05:48:22 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 422943857C40 for ; Sun, 5 Nov 2023 18:48:20 +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 BB3893858414 for ; Sun, 5 Nov 2023 18:48:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BB3893858414 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 BB3893858414 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=1699210091; cv=none; b=xfA8eEgysSUC7rMC17MoDJ2SMOJdOov7uGmIojSnRHc1b2egy7JkL4zl22GuLDYaRN2txKOqppLq1PDfdjohDLFeCiwX066RNnNnMqTJ83Q2zgABlBObRDAZ6dQ/d1Bz5ZKEFw0SREpqenHUO8ib7SCpHbI1A4eYU395fMvVgU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210091; c=relaxed/simple; bh=pou0NrWb8QzfPihc+LRuguNOaybSsqUpCQs564xmjSY=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=xUDl+y3T0DCacU2t2GdZyTsb3ahLhq9LVDxeNpERa5/q2A6juI0CorYHyHwaZxbMaJkmchk4ABiK2ugkcQnVkH5NekrrwRV1Kvyl5inPfMgkiI6x+axEcl2I560SJApFm4lXMaw0FAMeWHBDehOfHbf8XH7nBpXh8yf0+3Ys6k4= 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 544D2C15; Sun, 5 Nov 2023 10:48:53 -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 109563F703; Sun, 5 Nov 2023 10:48:08 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 06/12] mode-switching: Tweak entry/exit handling References: Date: Sun, 05 Nov 2023 18:48:07 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.4 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 An entity isn't transparent in a block that requires a specific mode. optimize_mode_switching took that into account for normal insns, but didn't for the exit block. Later patches misbehaved because of this. In contrast, an entity was correctly marked as non-transparent in the entry block, but the reasoning seemed a bit convoluted. It also referred to a function that no longer exists. Since KILL = ~TRANSP, the entity is by definition not transparent in a block that defines the entity, so I think we can make it so without comment. Finally, the exit handling was nested in the entry handling, but that doesn't seem necessary. A target could say that an entity is undefined on entry but must be defined on return, on a "be liberal in what you accept, be conservative in what you do" principle. gcc/ * mode-switching.cc (optimize_mode_switching): Mark the exit block as nontransparent if it requires a specific mode. Handle the entry and exit mode as sibling rather than nested concepts. Remove outdated comment. --- gcc/mode-switching.cc | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index 03dd4c1ebe4..1145350ca26 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -650,34 +650,30 @@ optimize_mode_switching (void) } if (targetm.mode_switching.entry && targetm.mode_switching.exit) { - int mode = targetm.mode_switching.entry (e); - info[post_entry->index].mode_out = info[post_entry->index].mode_in = no_mode; - if (pre_exit) - { - info[pre_exit->index].mode_out = - info[pre_exit->index].mode_in = no_mode; - } + int mode = targetm.mode_switching.entry (e); if (mode != no_mode) { - bb = post_entry; - - /* By always making this nontransparent, we save - an extra check in make_preds_opaque. We also - need this to avoid confusing pre_edge_lcm when - antic is cleared but transp and comp are set. */ - bitmap_clear_bit (transp_all, bb->index); - /* Insert a fake computing definition of MODE into entry blocks which compute no mode. This represents the mode on entry. */ - info[bb->index].computing = mode; + info[post_entry->index].computing = mode; + bitmap_clear_bit (transp_all, post_entry->index); + } - if (pre_exit) - info[pre_exit->index].seginfo->mode = - targetm.mode_switching.exit (e); + if (pre_exit) + { + info[pre_exit->index].mode_out = + info[pre_exit->index].mode_in = no_mode; + + int mode = targetm.mode_switching.exit (e); + if (mode != no_mode) + { + info[pre_exit->index].seginfo->mode = mode; + bitmap_clear_bit (transp_all, pre_exit->index); + } } } From patchwork Sun Nov 5 18:48:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859588 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 4SNk5m5h8Pz1yQL for ; Mon, 6 Nov 2023 05:48:44 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D5F323857B93 for ; Sun, 5 Nov 2023 18:48:42 +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 9ADBA3856943 for ; Sun, 5 Nov 2023 18:48:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9ADBA3856943 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 9ADBA3856943 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=1699210112; cv=none; b=CAGJXGZu0Q/jC/3Mb9hcsRtHT1L+kwyadS6dlgt/9zMFdPyNQhP8PC7QjDTLH5mzDvC1/katlG5aXn10rkptsxzqX3Ev7P75zVw3qGREq6L67hzjjU+Bdx9tjevPGydxdnKFtVkb+ZhKuhSV9zAnLOg7hXmix3zwqPtJWhzqVFQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210112; c=relaxed/simple; bh=i5vhLQVtM7W+fzUGxizUHvdV3xavEj0J1gsNHxXqJGE=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=jj6T2qnVR4rECFYgwCX0QX1slhufj5kHzJaFUCUsX/3oZj9E8pcymu2LjORxuXucAJb/bK/d0gQC0XbHhac/MfKG/Nzwp09Fm8yrvb5zyk8Ew6JdpSnNpQPRcWmlEk3syggzqOJ1mzwGwSO2UrTipHUzLiTyI3bwfyKrHkK39Bs= 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 30C6EC15; Sun, 5 Nov 2023 10:49:15 -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 E1B7F3F703; Sun, 5 Nov 2023 10:48:30 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 07/12] mode-switching: Allow targets to set the mode for EH handlers References: Date: Sun, 05 Nov 2023 18:48:29 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.4 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 The mode-switching pass already had hooks to say what mode an entity is in on entry to a function and what mode it must be in on return. For SME, we also want to say what mode an entity is guaranteed to be in on entry to an exception handler. gcc/ * target.def (mode_switching.eh_handler): New hook. * doc/tm.texi.in (TARGET_MODE_EH_HANDLER): New @hook. * doc/tm.texi: Regenerate. * mode-switching.cc (optimize_mode_switching): Use eh_handler to get the mode on entry to an exception handler. --- gcc/doc/tm.texi | 6 ++++++ gcc/doc/tm.texi.in | 2 ++ gcc/mode-switching.cc | 5 ++++- gcc/target.def | 7 +++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 759331a2c96..1a825c5004e 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10455,6 +10455,12 @@ If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY} must be defined. @end deftypefn +@deftypefn {Target Hook} int TARGET_MODE_EH_HANDLER (int @var{entity}) +If this hook is defined, it should return the mode that @var{entity} is +guaranteed to be in on entry to an exception handler, or the number of modes +if there is no such guarantee. +@end deftypefn + @deftypefn {Target Hook} int TARGET_MODE_PRIORITY (int @var{entity}, int @var{n}) This hook specifies the order in which modes for @var{entity} are processed. 0 is the highest priority, diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index a7b7aa289d8..5360c1bb2d8 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -6979,6 +6979,8 @@ mode or ``no mode'', depending on context. @hook TARGET_MODE_EXIT +@hook TARGET_MODE_EH_HANDLER + @hook TARGET_MODE_PRIORITY @node Target Attributes diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index 1145350ca26..b8a887d81f7 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -597,7 +597,10 @@ optimize_mode_switching (void) gcc_assert (NOTE_INSN_BASIC_BLOCK_P (ins_pos)); if (ins_pos != BB_END (bb)) ins_pos = NEXT_INSN (ins_pos); - ptr = new_seginfo (no_mode, no_mode, ins_pos, live_now); + if (bb_has_eh_pred (bb) + && targetm.mode_switching.eh_handler) + last_mode = targetm.mode_switching.eh_handler (e); + ptr = new_seginfo (no_mode, last_mode, ins_pos, live_now); add_seginfo (&tail_ptr, ptr); bitmap_clear_bit (transp_all, bb->index); } diff --git a/gcc/target.def b/gcc/target.def index 3dae33522f1..a70275b8abd 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -7070,6 +7070,13 @@ If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY}\n\ must be defined.", int, (int entity), NULL) +DEFHOOK +(eh_handler, + "If this hook is defined, it should return the mode that @var{entity} is\n\ +guaranteed to be in on entry to an exception handler, or the number of modes\n\ +if there is no such guarantee.", + int, (int entity), NULL) + DEFHOOK (priority, "This hook specifies the order in which modes for @var{entity}\n\ From patchwork Sun Nov 5 18:48: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: 1859589 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 4SNk6C331mz1yQL for ; Mon, 6 Nov 2023 05:49:07 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7A57B3857006 for ; Sun, 5 Nov 2023 18:49:05 +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 C8B7E385842E for ; Sun, 5 Nov 2023 18:48:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C8B7E385842E 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 C8B7E385842E 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=1699210135; cv=none; b=CWz6zLqZWpAdc+wcFPZPxF6kRGxvV36fzzDFcqceH2bleAC7Iejia5VV6WVcXxJPVKMoFjLXqqqFzr1N+sBwVP5rKD/i1wODuNRlEXR9x//pORqZNrncSHl1TvO1ptgub3nQG55dmKMBbDoZ53CVFwLBJQhG7WAeaqdlSPdl6P8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210135; c=relaxed/simple; bh=k7ou5bD8Iw563OZKmDtnyLgeFFsCEytwIHTzMiy4ui8=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=NuDemx9pSju2zdc6hOOspFgCrxoSwOKH5TeP+rEkG7d85fy63QuJ7dn6co0Hq8yjIHGM1qZ6vLQINFkVl7XnvrIyvR5mnYKAhr49Ou5LcVOqn73+2hukl+XpHhxXtJXeQrac5Eky8rsidLt7qyKqhj0WitDWKJl+DBkLgIWfefg= 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 6ABC1C15; Sun, 5 Nov 2023 10:49:37 -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 275023F703; Sun, 5 Nov 2023 10:48:53 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 08/12] mode-switching: Pass set of live registers to the needed hook References: Date: Sun, 05 Nov 2023 18:48:51 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-22.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, T_SCC_BODY_TEXT_LINE, URIBL_BLACK 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 The emit hook already takes the set of live hard registers as input. This patch passes it to the needed hook too. SME uses this to optimise the mode choice based on whether state is live or dead. The main caller already had access to the required info, but the special handling of return values did not. gcc/ * target.def (mode_switching.needed): Add a regs_live parameter. * doc/tm.texi: Regenerate. * config/epiphany/epiphany-protos.h (epiphany_mode_needed): Update accordingly. * config/epiphany/epiphany.cc (epiphany_mode_needed): Likewise. * config/epiphany/mode-switch-use.cc (insert_uses): Likewise. * config/i386/i386.cc (ix86_mode_needed): Likewise. * config/riscv/riscv.cc (riscv_mode_needed): Likewise. * config/sh/sh.cc (sh_mode_needed): Likewise. * mode-switching.cc (optimize_mode_switching): Likewise. (create_pre_exit): Likewise, using the DF simulate functions to calculate the required information. --- gcc/config/epiphany/epiphany-protos.h | 4 +++- gcc/config/epiphany/epiphany.cc | 2 +- gcc/config/epiphany/mode-switch-use.cc | 2 +- gcc/config/i386/i386.cc | 2 +- gcc/config/riscv/riscv.cc | 2 +- gcc/config/sh/sh.cc | 4 ++-- gcc/doc/tm.texi | 5 +++-- gcc/mode-switching.cc | 14 ++++++++++++-- gcc/target.def | 5 +++-- 9 files changed, 27 insertions(+), 13 deletions(-) diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h index 72c141c1a6d..ef49a1e06a4 100644 --- a/gcc/config/epiphany/epiphany-protos.h +++ b/gcc/config/epiphany/epiphany-protos.h @@ -44,7 +44,9 @@ extern void emit_set_fp_mode (int entity, int mode, int prev_mode, #endif extern void epiphany_insert_mode_switch_use (rtx_insn *insn, int, int); extern void epiphany_expand_set_fp_mode (rtx *operands); -extern int epiphany_mode_needed (int entity, rtx_insn *insn); +#ifdef HARD_CONST +extern int epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET); +#endif extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn); extern bool epiphany_epilogue_uses (int regno); extern bool epiphany_optimize_mode_switching (int entity); diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc index a5460dbf97f..60a9b49d8a4 100644 --- a/gcc/config/epiphany/epiphany.cc +++ b/gcc/config/epiphany/epiphany.cc @@ -2400,7 +2400,7 @@ epiphany_mode_priority (int entity, int priority) } int -epiphany_mode_needed (int entity, rtx_insn *insn) +epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET) { enum attr_fp_mode mode; diff --git a/gcc/config/epiphany/mode-switch-use.cc b/gcc/config/epiphany/mode-switch-use.cc index 71530612658..183b9b7a394 100644 --- a/gcc/config/epiphany/mode-switch-use.cc +++ b/gcc/config/epiphany/mode-switch-use.cc @@ -58,7 +58,7 @@ insert_uses (void) { if (!INSN_P (insn)) continue; - mode = epiphany_mode_needed (e, insn); + mode = epiphany_mode_needed (e, insn, {}); if (mode == no_mode) continue; if (target_insert_mode_switch_use) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index fdc9362cf5b..7a5a9a966e8 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -15061,7 +15061,7 @@ ix86_i387_mode_needed (int entity, rtx_insn *insn) prior to the execution of insn. */ static int -ix86_mode_needed (int entity, rtx_insn *insn) +ix86_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET) { switch (entity) { diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 08ff05dcc3f..f915de7ed56 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -9413,7 +9413,7 @@ riscv_frm_mode_needed (rtx_insn *cur_insn, int code) prior to the execution of insn. */ static int -riscv_mode_needed (int entity, rtx_insn *insn) +riscv_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET) { int code = recog_memoized (insn); diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc index 294faf7c0c3..c363490e852 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -195,7 +195,7 @@ static int calc_live_regs (HARD_REG_SET *); static HOST_WIDE_INT rounded_frame_size (int); static bool sh_frame_pointer_required (void); static void sh_emit_mode_set (int, int, int, HARD_REG_SET); -static int sh_mode_needed (int, rtx_insn *); +static int sh_mode_needed (int, rtx_insn *, HARD_REG_SET); static int sh_mode_after (int, int, rtx_insn *); static int sh_mode_entry (int); static int sh_mode_exit (int); @@ -12531,7 +12531,7 @@ sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode, } static int -sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn) +sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn, HARD_REG_SET) { return recog_memoized (insn) >= 0 ? get_attr_fp_mode (insn) : FP_MODE_NONE; } diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 1a825c5004e..144b3f88c37 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10414,12 +10414,13 @@ known. Sets of a lower numbered entity will be emitted before sets of a higher numbered entity to a mode of the same or lower priority. @end deftypefn -@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn}) +@deftypefn {Target Hook} int TARGET_MODE_NEEDED (int @var{entity}, rtx_insn *@var{insn}, HARD_REG_SET @var{regs_live}) @var{entity} is an integer specifying a mode-switched entity. If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook to return the mode that @var{entity} must be switched into prior to the execution of @var{insn}, or the number of modes if @var{insn} has no -such requirement. +such requirement. @var{regs_live} contains the set of hard registers +that are live before @var{insn}. @end deftypefn @deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn}) diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index b8a887d81f7..c5fe90ba449 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -254,6 +254,9 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes) && GET_CODE (PATTERN (last_insn)) == USE && GET_CODE ((ret_reg = XEXP (PATTERN (last_insn), 0))) == REG) { + auto_bitmap live; + df_simulate_initialize_backwards (src_bb, live); + int ret_start = REGNO (ret_reg); int nregs = REG_NREGS (ret_reg); int ret_end = ret_start + nregs; @@ -262,6 +265,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes) bool forced_late_switch = false; rtx_insn *before_return_copy; + df_simulate_one_insn_backwards (src_bb, last_insn, live); + do { rtx_insn *return_copy = PREV_INSN (last_insn); @@ -269,6 +274,8 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes) int copy_start, copy_num; int j; + df_simulate_one_insn_backwards (src_bb, return_copy, live); + if (NONDEBUG_INSN_P (return_copy)) { /* When using SJLJ exceptions, the call to the @@ -368,11 +375,14 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes) the case for floating point on SH4 - then it might be set by an arithmetic operation that needs a different mode than the exit block. */ + HARD_REG_SET hard_regs_live; + REG_SET_TO_HARD_REG_SET (hard_regs_live, live); for (j = n_entities - 1; j >= 0; j--) { int e = entity_map[j]; int mode = - targetm.mode_switching.needed (e, return_copy); + targetm.mode_switching.needed (e, return_copy, + hard_regs_live); if (mode != num_modes[e] && mode != targetm.mode_switching.exit (e)) @@ -610,7 +620,7 @@ optimize_mode_switching (void) { if (INSN_P (insn)) { - int mode = targetm.mode_switching.needed (e, insn); + int mode = targetm.mode_switching.needed (e, insn, live_now); rtx link; if (mode != no_mode && mode != last_mode) diff --git a/gcc/target.def b/gcc/target.def index a70275b8abd..50bad184aca 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -7031,8 +7031,9 @@ DEFHOOK If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this hook\n\ to return the mode that @var{entity} must be switched into prior to the\n\ execution of @var{insn}, or the number of modes if @var{insn} has no\n\ -such requirement.", - int, (int entity, rtx_insn *insn), NULL) +such requirement. @var{regs_live} contains the set of hard registers\n\ +that are live before @var{insn}.", + int, (int entity, rtx_insn *insn, HARD_REG_SET regs_live), NULL) DEFHOOK (after, From patchwork Sun Nov 5 18:49:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859590 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 4SNk6n59ZNz1yQL for ; Mon, 6 Nov 2023 05:49:37 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BA9FA3856DD5 for ; Sun, 5 Nov 2023 18:49:35 +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 440023858422 for ; Sun, 5 Nov 2023 18:49:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 440023858422 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 440023858422 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=1699210165; cv=none; b=Lp7K3JNa2pl9G66D4Re+Dxk2ZUoaykekmtTuYcYAmkm7IeNhMeg7DOcmY5C8jybsfgF5jzAzOucw8Gk2jDL2Vsx7smFNWJ9YmBdN/CXfxFj/g7Q7olgqMm7MuVZqQCd3s/ruQUINkN6g5snWWREfIR3AmgKS+EyTXwlbBzl2bsQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210165; c=relaxed/simple; bh=TbZRlXcQykvaZnYLfa0s/H/XmiXrmUQjMGdU6HNMbSc=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=vgHt6hcpWOQKvUfntyKJSH7SnyKxS5qo+aprXRkO8zJAzrhSxZmf9OXjsvfbMLUWQ5hRXfq2i4GplcoVqLrSM9cNljlG9ZR7tADnpHWPhXvHKrq6wwB13dmNzncHZa7mxSj98sTURe2v8awSuvnstRU2tNvw45tjsijowZxHRhI= 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 D17C9C15; Sun, 5 Nov 2023 10:50:07 -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 8E48E3F703; Sun, 5 Nov 2023 10:49:23 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 09/12] mode-switching: Pass the set of live registers to the after hook References: Date: Sun, 05 Nov 2023 18:49:22 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-22.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, T_SCC_BODY_TEXT_LINE, URIBL_BLACK 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 passes the set of live hard registers to the after hook, like the previous one did for the needed hook. gcc/ * target.def (mode_switching.after): Add a regs_live parameter. * doc/tm.texi: Regenerate. * config/epiphany/epiphany-protos.h (epiphany_mode_after): Update accordingly. * config/epiphany/epiphany.cc (epiphany_mode_needed): Likewise. (epiphany_mode_after): Likewise. * config/i386/i386.cc (ix86_mode_after): Likewise. * config/riscv/riscv.cc (riscv_mode_after): Likewise. * config/sh/sh.cc (sh_mode_after): Likewise. * mode-switching.cc (optimize_mode_switching): Likewise. --- gcc/config/epiphany/epiphany-protos.h | 3 ++- gcc/config/epiphany/epiphany.cc | 5 +++-- gcc/config/i386/i386.cc | 2 +- gcc/config/riscv/riscv.cc | 2 +- gcc/config/sh/sh.cc | 5 +++-- gcc/doc/tm.texi | 4 +++- gcc/mode-switching.cc | 8 ++++---- gcc/target.def | 4 +++- 8 files changed, 20 insertions(+), 13 deletions(-) diff --git a/gcc/config/epiphany/epiphany-protos.h b/gcc/config/epiphany/epiphany-protos.h index ef49a1e06a4..ff8987ea99e 100644 --- a/gcc/config/epiphany/epiphany-protos.h +++ b/gcc/config/epiphany/epiphany-protos.h @@ -46,8 +46,9 @@ extern void epiphany_insert_mode_switch_use (rtx_insn *insn, int, int); extern void epiphany_expand_set_fp_mode (rtx *operands); #ifdef HARD_CONST extern int epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET); +extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn, + HARD_REG_SET); #endif -extern int epiphany_mode_after (int entity, int last_mode, rtx_insn *insn); extern bool epiphany_epilogue_uses (int regno); extern bool epiphany_optimize_mode_switching (int entity); extern bool epiphany_is_interrupt_p (tree); diff --git a/gcc/config/epiphany/epiphany.cc b/gcc/config/epiphany/epiphany.cc index 60a9b49d8a4..68e748c688e 100644 --- a/gcc/config/epiphany/epiphany.cc +++ b/gcc/config/epiphany/epiphany.cc @@ -2437,7 +2437,7 @@ epiphany_mode_needed (int entity, rtx_insn *insn, HARD_REG_SET) return 2; case EPIPHANY_MSW_ENTITY_ROUND_KNOWN: if (recog_memoized (insn) == CODE_FOR_set_fp_mode) - mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn); + mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn, {}); /* Fall through. */ case EPIPHANY_MSW_ENTITY_NEAREST: case EPIPHANY_MSW_ENTITY_TRUNC: @@ -2498,7 +2498,8 @@ epiphany_mode_entry_exit (int entity, bool exit) } int -epiphany_mode_after (int entity, int last_mode, rtx_insn *insn) +epiphany_mode_after (int entity, int last_mode, rtx_insn *insn, + HARD_REG_SET) { /* We have too few call-saved registers to hope to keep the masks across calls. */ diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 7a5a9a966e8..7b72aabf0da 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -15110,7 +15110,7 @@ ix86_avx_u128_mode_after (int mode, rtx_insn *insn) /* Return the mode that an insn results in. */ static int -ix86_mode_after (int entity, int mode, rtx_insn *insn) +ix86_mode_after (int entity, int mode, rtx_insn *insn, HARD_REG_SET) { switch (entity) { diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index f915de7ed56..e36b5fb9bd0 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -9514,7 +9514,7 @@ riscv_frm_mode_after (rtx_insn *insn, int mode) /* Return the mode that an insn results in. */ static int -riscv_mode_after (int entity, int mode, rtx_insn *insn) +riscv_mode_after (int entity, int mode, rtx_insn *insn, HARD_REG_SET) { switch (entity) { diff --git a/gcc/config/sh/sh.cc b/gcc/config/sh/sh.cc index c363490e852..6ec2eecf754 100644 --- a/gcc/config/sh/sh.cc +++ b/gcc/config/sh/sh.cc @@ -196,7 +196,7 @@ static HOST_WIDE_INT rounded_frame_size (int); static bool sh_frame_pointer_required (void); static void sh_emit_mode_set (int, int, int, HARD_REG_SET); static int sh_mode_needed (int, rtx_insn *, HARD_REG_SET); -static int sh_mode_after (int, int, rtx_insn *); +static int sh_mode_after (int, int, rtx_insn *, HARD_REG_SET); static int sh_mode_entry (int); static int sh_mode_exit (int); static int sh_mode_priority (int entity, int n); @@ -12537,7 +12537,8 @@ sh_mode_needed (int entity ATTRIBUTE_UNUSED, rtx_insn *insn, HARD_REG_SET) } static int -sh_mode_after (int entity ATTRIBUTE_UNUSED, int mode, rtx_insn *insn) +sh_mode_after (int entity ATTRIBUTE_UNUSED, int mode, rtx_insn *insn, + HARD_REG_SET) { if (TARGET_HITACHI && recog_memoized (insn) >= 0 && get_attr_fp_set (insn) != FP_SET_NONE) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 144b3f88c37..b730b5bf658 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10423,12 +10423,14 @@ such requirement. @var{regs_live} contains the set of hard registers that are live before @var{insn}. @end deftypefn -@deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn}) +@deftypefn {Target Hook} int TARGET_MODE_AFTER (int @var{entity}, int @var{mode}, rtx_insn *@var{insn}, HARD_REG_SET @var{regs_live}) @var{entity} is an integer specifying a mode-switched entity. If this hook is defined, it is evaluated for every @var{insn} during mode switching. It returns the mode that @var{entity} is in after @var{insn} has been executed. @var{mode} is the mode that @var{entity} was in before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}. +@var{regs_live} is the set of hard registers that are live after @var{insn} +has been executed. @var{mode} is equal to the number of modes defined for @var{entity} if the mode before @var{insn} is unknown. The hook should likewise return diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index c5fe90ba449..7a5c4993d65 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -632,10 +632,6 @@ optimize_mode_switching (void) last_mode = mode; } - if (targetm.mode_switching.after) - last_mode = targetm.mode_switching.after (e, last_mode, - insn); - /* Update LIVE_NOW. */ for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_DEAD) @@ -645,6 +641,10 @@ optimize_mode_switching (void) for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_UNUSED) reg_dies (XEXP (link, 0), &live_now); + + if (targetm.mode_switching.after) + last_mode = targetm.mode_switching.after (e, last_mode, + insn, live_now); } } diff --git a/gcc/target.def b/gcc/target.def index 50bad184aca..9b14c037d3f 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -7042,6 +7042,8 @@ If this hook is defined, it is evaluated for every @var{insn} during mode\n\ switching. It returns the mode that @var{entity} is in after @var{insn}\n\ has been executed. @var{mode} is the mode that @var{entity} was in\n\ before @var{insn} was executed, taking account of @var{TARGET_MODE_NEEDED}.\n\ +@var{regs_live} is the set of hard registers that are live after @var{insn}\n\ +has been executed.\n\ \n\ @var{mode} is equal to the number of modes defined for @var{entity}\n\ if the mode before @var{insn} is unknown. The hook should likewise return\n\ @@ -7049,7 +7051,7 @@ the number of modes if it does not know what mode @var{entity} has after\n\ @var{insn}.\n\ \n\ Not defining the hook is equivalent to returning @var{mode}.", - int, (int entity, int mode, rtx_insn *insn), NULL) + int, (int entity, int mode, rtx_insn *insn, HARD_REG_SET regs_live), NULL) DEFHOOK (entry, From patchwork Sun Nov 5 18:49:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859591 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 4SNk786x7dz1yQL for ; Mon, 6 Nov 2023 05:49:56 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DB6FD385AE41 for ; Sun, 5 Nov 2023 18:49:54 +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 AF487385701B for ; Sun, 5 Nov 2023 18:49:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AF487385701B 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 AF487385701B 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=1699210184; cv=none; b=tSBpdfJ9issUo0Nv6UTjz59GSkw93iOGAXXUimGeifFJPkFburztCgOrlL9bTJUKy9p0M6g6r6rIXfl7506T5K2VbEfZX/GlnRA1SnNTH69UsinFOTfeN9TWR+ofOQVMH6aJq7fp63zxyVSxSsC/EiXpFLfzJG+HFt3xvx5Id9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210184; c=relaxed/simple; bh=XBcUiHb7RLX8+jUUDITs7Z+kTBawIfBlGnINMFq6FVE=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=plDEbyWB02dVawc12ETMdtg/BIb1TKM8Ua7BUT9OzO6+M/y8Wk46q9Da4pU3BL/azzHw1ZIPCi9QZufPkFVcAvLe1DWwR8t8nPFcrFfkZhmX6cicd4Xf8Qn+gGEZsec85gfAULdijkpNpXJWSn/z0NYZTvm/EXfwZCaDHZT0yPs= 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 4E04EC15; Sun, 5 Nov 2023 10:50:27 -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 0A63E3F703; Sun, 5 Nov 2023 10:49:42 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 10/12] mode-switching: Use 1-based edge aux fields References: Date: Sun, 05 Nov 2023 18:49:41 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.3 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 The pass used the edge aux field to record which mode change should happen on the edge, with -1 meaning "none". It's more convenient for later patches to leave aux zero for "none", and use numbers based at 1 to record a change. gcc/ * mode-switching.cc (commit_mode_sets): Use 1-based edge aux values. --- gcc/mode-switching.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index 7a5c4993d65..1815b397dd0 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -106,10 +106,10 @@ commit_mode_sets (struct edge_list *edge_list, int e, struct bb_info *info) for (int ed = NUM_EDGES (edge_list) - 1; ed >= 0; ed--) { edge eg = INDEX_EDGE (edge_list, ed); - int mode; - if ((mode = (int)(intptr_t)(eg->aux)) != -1) + if (eg->aux) { + int mode = (int) (intptr_t) eg->aux - 1; HARD_REG_SET live_at_edge; basic_block src_bb = eg->src; int cur_mode = info[src_bb->index].mode_out; @@ -728,14 +728,12 @@ optimize_mode_switching (void) { edge eg = INDEX_EDGE (edge_list, ed); - eg->aux = (void *)(intptr_t)-1; - for (i = 0; i < no_mode; i++) { int m = targetm.mode_switching.priority (entity_map[j], i); if (mode_bit_p (insert[ed], j, m)) { - eg->aux = (void *)(intptr_t)m; + eg->aux = (void *) (intptr_t) (m + 1); break; } } From patchwork Sun Nov 5 18:50:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859592 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 4SNk7Y5LKVz1yQ5 for ; Mon, 6 Nov 2023 05:50:17 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C8C883856DF4 for ; Sun, 5 Nov 2023 18:50:15 +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 DD1DC3856DF4 for ; Sun, 5 Nov 2023 18:50:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DD1DC3856DF4 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 DD1DC3856DF4 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=1699210206; cv=none; b=tEq2qMnIQzIFcgVR+jXXS04A1i0np+4+U90sxPIDsZTaSs4bWqQkNI03hYh39TlHDbingNHRfIV3/Fh65JsLNw6m4TslT2/HeXGL7pLg3KOjir0mKqOgjMI99x9fRzjHhR559URBsLWqOyR95E50oMbiI9+Kk4OeLZW2Vs5QVm8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210206; c=relaxed/simple; bh=C/Jk5ZnD2i/cFsvXnvmTQyWPLH7L4BsIK0nLIhD6HKY=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Dso4NxNYnoob96LzV8TN7ZYz7mwhwsz73f+CZsEAJGkDAnmCRCxTwkmSMWVFn2ksmv1wenKGaAIWrdax6exeMQpnsARErMO4ZJXGUPFyd9QeHg9YSalh2X5yeDeG0mrdZlmf5B/YTl71/FNGshFK8MBpIbHfwXNa95lU46wJGpA= 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 7EC05C15; Sun, 5 Nov 2023 10:50:47 -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 3AC323F703; Sun, 5 Nov 2023 10:50:03 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 11/12] mode-switching: Add a target-configurable confluence operator References: Date: Sun, 05 Nov 2023 18:50:02 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.3 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 The mode-switching pass assumed that all of an entity's modes were mutually exclusive. However, the upcoming SME changes have an entity with some overlapping modes, so that there is sometimes a "superunion" mode that contains two given modes. We can use this relationship to pass something more helpful than "don't know" to the emit hook. This patch adds a new hook that targets can use to specify a mode confluence operator. With mutually exclusive modes, it's possible to compute a block's incoming and outgoing modes by looking at its availability sets. With the confluence operator, we instead need to solve a full dataflow problem. However, when emitting a mode transition, the upcoming SME use of mode-switching benefits from having as much information as possible about the starting mode. Calculating this information is definitely worth the compile time. The dataflow problem is written to work before and after the LCM problem has been solved. A later patch makes use of this. While there (since git blame would ping me for the reindented code), I used a lambda to avoid the cut-&-pasted loops. gcc/ * target.def (mode_switching.confluence): New hook. * doc/tm.texi (TARGET_MODE_CONFLUENCE): New @hook. * doc/tm.texi.in: Regenerate. * mode-switching.cc (confluence_info): New variable. (mode_confluence, forward_confluence_n, forward_transfer): New functions. (optimize_mode_switching): Use them to calculate mode_in when TARGET_MODE_CONFLUENCE is defined. --- gcc/doc/tm.texi | 16 ++++ gcc/doc/tm.texi.in | 2 + gcc/mode-switching.cc | 179 +++++++++++++++++++++++++++++++++++------- gcc/target.def | 17 ++++ 4 files changed, 186 insertions(+), 28 deletions(-) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index b730b5bf658..cd346538fe2 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10440,6 +10440,22 @@ the number of modes if it does not know what mode @var{entity} has after Not defining the hook is equivalent to returning @var{mode}. @end deftypefn +@deftypefn {Target Hook} int TARGET_MODE_CONFLUENCE (int @var{entity}, int @var{mode1}, int @var{mode2}) +By default, the mode-switching pass assumes that a given entity's modes +are mutually exclusive. This means that the pass can only tell +@code{TARGET_MODE_EMIT} about an entity's previous mode if all +incoming paths of execution leave the entity in the same state. + +However, some entities might have overlapping, non-exclusive modes, +so that it is sometimes possible to represent ``mode @var{mode1} or mode +@var{mode2}'' with something more specific than ``mode not known''. +If this is true for at least one entity, you should define this hook +and make it return a mode that includes @var{mode1} and @var{mode2} +as possibilities. (The mode can include other possibilities too.) +The hook should return the number of modes if no suitable mode exists +for the given arguments. +@end deftypefn + @deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity}) If this hook is defined, it is evaluated for every @var{entity} that needs mode switching. It should return the mode that @var{entity} is diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 5360c1bb2d8..ae23241ea1c 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -6975,6 +6975,8 @@ mode or ``no mode'', depending on context. @hook TARGET_MODE_AFTER +@hook TARGET_MODE_CONFLUENCE + @hook TARGET_MODE_ENTRY @hook TARGET_MODE_EXIT diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index 1815b397dd0..87b23d2c050 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -485,6 +485,101 @@ create_pre_exit (int n_entities, int *entity_map, const int *num_modes) return pre_exit; } +/* Return the confluence of modes MODE1 and MODE2 for entity ENTITY, + using NO_MODE to represent an unknown mode if nothing more precise + is available. */ + +int +mode_confluence (int entity, int mode1, int mode2, int no_mode) +{ + if (mode1 == mode2) + return mode1; + + if (mode1 != no_mode + && mode2 != no_mode + && targetm.mode_switching.confluence) + return targetm.mode_switching.confluence (entity, mode1, mode2); + + return no_mode; +} + +/* Information for the dataflow problems below. */ +struct +{ + /* Information about each basic block, indexed by block id. */ + struct bb_info *bb_info; + + /* The entity that we're processing. */ + int entity; + + /* The number of modes defined for the entity, and thus the identifier + of the "don't know" mode. */ + int no_mode; +} confluence_info; + +/* Propagate information about any mode change on edge E to the + destination block's mode_in. Return true if something changed. + + The mode_in and mode_out fields use no_mode + 1 to mean "not yet set". */ + +static bool +forward_confluence_n (edge e) +{ + /* The entry and exit blocks have no useful mode information. */ + if (e->src->index == ENTRY_BLOCK || e->dest->index == EXIT_BLOCK) + return false; + + /* We don't control mode changes across abnormal edges. */ + if (e->flags & EDGE_ABNORMAL) + return false; + + /* E->aux is nonzero if we have computed the LCM problem and scheduled + E to change the mode to E->aux - 1. Otherwise model the change + from the source to the destination. */ + struct bb_info *bb_info = confluence_info.bb_info; + int no_mode = confluence_info.no_mode; + int src_mode = bb_info[e->src->index].mode_out; + if (e->aux) + src_mode = (int) (intptr_t) e->aux - 1; + if (src_mode == no_mode + 1) + return false; + + int dest_mode = bb_info[e->dest->index].mode_in; + if (dest_mode == no_mode + 1) + { + bb_info[e->dest->index].mode_in = src_mode; + return true; + } + + int entity = confluence_info.entity; + int new_mode = mode_confluence (entity, src_mode, dest_mode, no_mode); + if (dest_mode == new_mode) + return false; + + bb_info[e->dest->index].mode_in = new_mode; + return true; +} + +/* Update block BB_INDEX's mode_out based on its mode_in. Return true if + something changed. */ + +static bool +forward_transfer (int bb_index) +{ + /* The entry and exit blocks have no useful mode information. */ + if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK) + return false; + + /* Only propagate through a block if the entity is transparent. */ + struct bb_info *bb_info = confluence_info.bb_info; + if (bb_info[bb_index].computing != confluence_info.no_mode + || bb_info[bb_index].mode_out == bb_info[bb_index].mode_in) + return false; + + bb_info[bb_index].mode_out = bb_info[bb_index].mode_in; + return true; +} + /* Find all insns that need a particular mode setting, and insert the necessary mode switches. Return true if we did work. */ @@ -568,6 +663,39 @@ optimize_mode_switching (void) auto_sbitmap transp_all (last_basic_block_for_fn (cfun)); + auto_bitmap blocks; + + /* Forward-propagate mode information through blocks where the entity + is transparent, so that mode_in describes the mode on entry to each + block and mode_out describes the mode on exit from each block. */ + auto forwprop_mode_info = [&](struct bb_info *info, + int entity, int no_mode) + { + /* Use no_mode + 1 to mean "not yet set". */ + FOR_EACH_BB_FN (bb, cfun) + { + if (bb_has_abnormal_pred (bb)) + info[bb->index].mode_in = info[bb->index].seginfo->mode; + else + info[bb->index].mode_in = no_mode + 1; + if (info[bb->index].computing != no_mode) + info[bb->index].mode_out = info[bb->index].computing; + else + info[bb->index].mode_out = no_mode + 1; + } + + confluence_info.bb_info = info; + confluence_info.entity = entity; + confluence_info.no_mode = no_mode; + + bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun)); + df_simple_dataflow (DF_FORWARD, NULL, NULL, forward_confluence_n, + forward_transfer, blocks, + df_get_postorder (DF_FORWARD), + df_get_n_blocks (DF_FORWARD)); + + }; + for (j = n_entities - 1; j >= 0; j--) { int e = entity_map[j]; @@ -721,6 +849,7 @@ optimize_mode_switching (void) for (j = n_entities - 1; j >= 0; j--) { int no_mode = num_modes[entity_map[j]]; + struct bb_info *info = bb_info[j]; /* Insert all mode sets that have been inserted by lcm. */ @@ -739,39 +868,33 @@ optimize_mode_switching (void) } } + /* mode_in and mode_out can be calculated directly from avin and + avout if all the modes are mutually exclusive. Use the target- + provided confluence function otherwise. */ + if (targetm.mode_switching.confluence) + forwprop_mode_info (info, entity_map[j], no_mode); + FOR_EACH_BB_FN (bb, cfun) { - struct bb_info *info = bb_info[j]; - int last_mode = no_mode; - - /* intialize mode in availability for bb. */ - for (i = 0; i < no_mode; i++) - if (mode_bit_p (avout[bb->index], j, i)) - { - if (last_mode == no_mode) - last_mode = i; - if (last_mode != i) + auto modes_confluence = [&](sbitmap *av) + { + for (int i = 0; i < no_mode; ++i) + if (mode_bit_p (av[bb->index], j, i)) { - last_mode = no_mode; - break; + for (int i2 = i + 1; i2 < no_mode; ++i2) + if (mode_bit_p (av[bb->index], j, i2)) + return no_mode; + return i; } - } - info[bb->index].mode_out = last_mode; + return no_mode; + }; - /* intialize mode out availability for bb. */ - last_mode = no_mode; - for (i = 0; i < no_mode; i++) - if (mode_bit_p (avin[bb->index], j, i)) - { - if (last_mode == no_mode) - last_mode = i; - if (last_mode != i) - { - last_mode = no_mode; - break; - } - } - info[bb->index].mode_in = last_mode; + /* intialize mode in/out availability for bb. */ + if (!targetm.mode_switching.confluence) + { + info[bb->index].mode_out = modes_confluence (avout); + info[bb->index].mode_in = modes_confluence (avin); + } for (i = 0; i < no_mode; i++) if (mode_bit_p (del[bb->index], j, i)) diff --git a/gcc/target.def b/gcc/target.def index 9b14c037d3f..b08ede692f1 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -7053,6 +7053,23 @@ the number of modes if it does not know what mode @var{entity} has after\n\ Not defining the hook is equivalent to returning @var{mode}.", int, (int entity, int mode, rtx_insn *insn, HARD_REG_SET regs_live), NULL) +DEFHOOK +(confluence, + "By default, the mode-switching pass assumes that a given entity's modes\n\ +are mutually exclusive. This means that the pass can only tell\n\ +@code{TARGET_MODE_EMIT} about an entity's previous mode if all\n\ +incoming paths of execution leave the entity in the same state.\n\ +\n\ +However, some entities might have overlapping, non-exclusive modes,\n\ +so that it is sometimes possible to represent ``mode @var{mode1} or mode\n\ +@var{mode2}'' with something more specific than ``mode not known''.\n\ +If this is true for at least one entity, you should define this hook\n\ +and make it return a mode that includes @var{mode1} and @var{mode2}\n\ +as possibilities. (The mode can include other possibilities too.)\n\ +The hook should return the number of modes if no suitable mode exists\n\ +for the given arguments.", + int, (int entity, int mode1, int mode2), NULL) + DEFHOOK (entry, "If this hook is defined, it is evaluated for every @var{entity} that\n\ From patchwork Sun Nov 5 18:50:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 1859593 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 4SNk7z2p8kz1yQ5 for ; Mon, 6 Nov 2023 05:50:39 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5A2C2385AE41 for ; Sun, 5 Nov 2023 18:50:37 +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 23F723857C40 for ; Sun, 5 Nov 2023 18:50:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 23F723857C40 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 23F723857C40 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=1699210226; cv=none; b=rJRsWSGYj+gm6UTZkEcjKYMK1Ziegp75LGxroF5jjDdsOBAkvP0n0QKGkyVcN8WBXkztryttrI7hrhLqqgmS48egxEQ6u/6ZHxbd1xXIBTioBGbiy8T3XVTUwCNrS6SB6n25v8d5tlhWq5YQEvHzPMHGOPXnUv7YcPeJCVt3YvQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699210226; c=relaxed/simple; bh=VPa5snu5ILkX1NAlKuaAbKw8Y9k4rKt0iyVtX0T/OtI=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=VAWiNkNjgo+QS39ErOxBlO8+Q5pxsoBFKckgPPoBs5Gauw8WsPxInZpVyXpiivSUHeQXreKZgZacgN2mN7BnDMUgOB77KZuqysKm/w9YxB/8kOJLk9Y053C7oRNNI04Hyh7nNH13tVmNu50ybOuSSvQjCRf4iD1DUiSe1QDHANs= 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 B621DC15; Sun, 5 Nov 2023 10:51:07 -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 57C373F703; Sun, 5 Nov 2023 10:50:23 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, jlaw@ventanamicro.com, richard.sandiford@arm.com Cc: jlaw@ventanamicro.com Subject: [PATCH 12/12] mode-switching: Add a backprop hook References: Date: Sun, 05 Nov 2023 18:50:22 +0000 In-Reply-To: (Richard Sandiford's message of "Sun, 05 Nov 2023 18:45:29 +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=-23.3 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 adds a way for targets to ask that selected mode changes be brought forward, through a combination of: (1) requiring a mode in blocks where the entity was previously transparent (2) pushing the transition at the head of a block onto incomging edges SME has two uses for this: - A "one-shot" entity that, for any given path of execution, either stays off or makes exactly one transition from off to on. This relies only on (1) above; see the hook description for more info. The main purpose of using mode-switching for this entity is to shrink-wrap the code that requires it. - A second entity for which all transitions must be from known modes, which is enforced using a combination of (1) and (2). More specifically, (1) looks for edges B1->B2 for which: - B2 requires a specific mode and - B1 does not guarantee a specific starting mode In this system, such an edge is only possible if the entity is transparent in B1. (1) then forces B1 to require some safe common mode. Applying this inductively means that all incoming edges are from known modes. If different edges give different starting modes, (2) pushes the transitions onto the edges themselves; this only happens if the entity is not transparent in some predecessor block. The patch also uses the back-propagation as an excuse to do a simple on-the-fly optimisation. Hopefully the comments in the patch explain things a bit better. gcc/ * target.def (mode_switching.backprop): New hook. * doc/tm.texi.in (TARGET_MODE_BACKPROP): New @hook. * doc/tm.texi: Regenerate. * mode-switching.cc (struct bb_info): Add single_succ. (confluence_info): Add transp field. (single_succ_confluence_n, single_succ_transfer): New functions. (backprop_confluence_n, backprop_transfer): Likewise. (optimize_mode_switching): Use them. Push mode transitions onto a block's incoming edges, if the backprop hook requires it. --- gcc/doc/tm.texi | 28 +++++ gcc/doc/tm.texi.in | 2 + gcc/mode-switching.cc | 272 ++++++++++++++++++++++++++++++++++++++++++ gcc/target.def | 29 +++++ 4 files changed, 331 insertions(+) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index cd346538fe2..d83ca73b1af 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10456,6 +10456,34 @@ The hook should return the number of modes if no suitable mode exists for the given arguments. @end deftypefn +@deftypefn {Target Hook} int TARGET_MODE_BACKPROP (int @var{entity}, int @var{mode1}, int @var{mode2}) +If defined, the mode-switching pass uses this hook to back-propagate mode +requirements through blocks that have no mode requirements of their own. +Specifically, @var{mode1} is the mode that @var{entity} has on exit +from a block B1 (say) and @var{mode2} is the mode that the next block +requires @var{entity} to have. B1 does not have any mode requirements +of its own. + +The hook should return the mode that it prefers or requires @var{entity} +to have in B1, or the number of modes if there is no such requirement. +If the hook returns a required mode for more than one of B1's outgoing +edges, those modes are combined as for @code{TARGET_MODE_CONFLUENCE}. + +For example, suppose there is a ``one-shot'' entity that, +for a given execution of a function, either stays off or makes exactly +one transition from off to on. It is safe to make the transition at any +time, but it is better not to do so unnecessarily. This hook allows the +function to manage such an entity without having to track its state at +runtime. Specifically. the entity would have two modes, 0 for off and +1 for on, with 2 representing ``don't know''. The system is forbidden from +transitioning from 2 to 1, since 2 represents the possibility that the +entity is already on (and the aim is to avoid having to emit code to +check for that case). This hook would therefore return 1 when @var{mode1} +is 2 and @var{mode2} is 1, which would force the entity to be on in the +source block. Applying this inductively would remove all transitions +in which the previous state is unknown. +@end deftypefn + @deftypefn {Target Hook} int TARGET_MODE_ENTRY (int @var{entity}) If this hook is defined, it is evaluated for every @var{entity} that needs mode switching. It should return the mode that @var{entity} is diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index ae23241ea1c..3d3ae12cc2f 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -6977,6 +6977,8 @@ mode or ``no mode'', depending on context. @hook TARGET_MODE_CONFLUENCE +@hook TARGET_MODE_BACKPROP + @hook TARGET_MODE_ENTRY @hook TARGET_MODE_EXIT diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc index 87b23d2c050..720c30df72d 100644 --- a/gcc/mode-switching.cc +++ b/gcc/mode-switching.cc @@ -81,6 +81,7 @@ struct bb_info int computing; int mode_out; int mode_in; + int single_succ; }; /* Clear ode I from entity J in bitmap B. */ @@ -509,6 +510,9 @@ struct /* Information about each basic block, indexed by block id. */ struct bb_info *bb_info; + /* A bitmap of blocks for which the current entity is transparent. */ + sbitmap transp; + /* The entity that we're processing. */ int entity; @@ -580,6 +584,210 @@ forward_transfer (int bb_index) return true; } +/* A backwards confluence function. Update the the bb_info single_succ + field for E's source block, based on changes to E's destination block. + At the end of the dataflow problem, single_succ is the single mode + that all successors require (directly or indirectly), or no_mode + if there are conflicting requirements. + + Initially, a value of no_mode + 1 means "don't know". */ + +static bool +single_succ_confluence_n (edge e) +{ + /* The entry block has no associated mode information. */ + if (e->src->index == ENTRY_BLOCK) + return false; + + /* We don't control mode changes across abnormal edges. */ + if (e->flags & EDGE_ABNORMAL) + return false; + + /* Do nothing if we've already found a conflict. */ + struct bb_info *bb_info = confluence_info.bb_info; + int no_mode = confluence_info.no_mode; + int src_mode = bb_info[e->src->index].single_succ; + if (src_mode == no_mode) + return false; + + /* Work out what mode the destination block (or its successors) require. */ + int dest_mode; + if (e->dest->index == EXIT_BLOCK) + dest_mode = no_mode; + else if (bitmap_bit_p (confluence_info.transp, e->dest->index)) + dest_mode = bb_info[e->dest->index].single_succ; + else + dest_mode = bb_info[e->dest->index].seginfo->mode; + + /* Do nothing if the destination block has no new information. */ + if (dest_mode == no_mode + 1 || dest_mode == src_mode) + return false; + + /* Detect conflicting modes. */ + if (src_mode != no_mode + 1) + dest_mode = no_mode; + + bb_info[e->src->index].single_succ = dest_mode; + return true; +} + +/* A backward transfer function for computing the bb_info single_succ + fields, as described above single_succ_confluence. */ + +static bool +single_succ_transfer (int bb_index) +{ + /* We don't have any field to transfer to. Assume that, after the + first iteration, we are only called if single_succ has changed. + We should then process incoming edges if the entity is transparent. */ + return bitmap_bit_p (confluence_info.transp, bb_index); +} + +/* Check whether the target wants to back-propagate a mode change across + edge E, and update the source block's computed mode if so. Return true + if something changed. */ + +static bool +backprop_confluence_n (edge e) +{ + /* The entry and exit blocks have no useful mode information. */ + if (e->src->index == ENTRY_BLOCK || e->dest->index == EXIT_BLOCK) + return false; + + /* We don't control mode changes across abnormal edges. */ + if (e->flags & EDGE_ABNORMAL) + return false; + + /* We can only require a new mode in the source block if the entity + was originally transparent there. */ + if (!bitmap_bit_p (confluence_info.transp, e->src->index)) + return false; + + /* Exit now if there is no required mode, or if all paths into the + source block leave the entity in the required mode. */ + struct bb_info *bb_info = confluence_info.bb_info; + int no_mode = confluence_info.no_mode; + int src_mode = bb_info[e->src->index].mode_out; + int dest_mode = bb_info[e->dest->index].mode_in; + if (dest_mode == no_mode || src_mode == dest_mode) + return false; + + /* See what the target thinks about this transition. */ + int entity = confluence_info.entity; + int new_mode = targetm.mode_switching.backprop (entity, src_mode, + dest_mode); + if (new_mode == no_mode) + return false; + + /* The target doesn't like the current transition, but would be happy + with a transition from NEW_MODE. + + If we force the source block to use NEW_MODE, we might introduce a + double transition on at least one path through the function (one to + NEW_MODE and then one to DEST_MODE). Therefore, if all destination + blocks require the same mode, it is usually better to bring that + mode requirement forward. + + If that isn't possible, merge the preference for this edge with + the preferences for other edges. no_mode + 1 indicates that there + was no previous preference. */ + int old_mode = bb_info[e->src->index].computing; + if (bb_info[e->src->index].single_succ != no_mode) + new_mode = bb_info[e->src->index].single_succ; + else if (old_mode != no_mode + 1) + new_mode = mode_confluence (entity, old_mode, new_mode, no_mode); + + if (old_mode == new_mode) + return false; + + bb_info[e->src->index].computing = new_mode; + return true; +} + +/* If the current entity was originally transparent in block BB_INDEX, + update the incoming mode to match the outgoing mode. Register a mode + change if the entity is no longer transparent. + + Also, as an on-the-fly optimization, check whether the entity was + originally transparent in BB_INDEX and if all successor blocks require + the same mode. If so, anticipate the mode change in BB_INDEX if + doing it on the incoming edges would require no more mode changes than + doing it on the outgoing edges. The aim is to reduce the total number + of mode changes emitted for the function (and thus reduce code size and + cfg complexity) without increasing the number of mode changes on any + given path through the function. A typical case where it helps is: + + T + / \ + T M + \ / + M + + where the entity is transparent in the T blocks and is required to have + mode M in the M blocks. If there are no redundancies leading up to this, + there will be two mutually-exclusive changes to mode M, one on each of + the T->M edges. The optimization instead converts it to: + + T T M + / \ / \ / \ + T M -> M M -> M M + \ / \ / \ / + M M M + + which creates a single transition to M for both paths through the diamond. + + Return true if something changed. */ + +static bool +backprop_transfer (int bb_index) +{ + /* The entry and exit blocks have no useful mode information. */ + if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK) + return false; + + /* We can only require a new mode if the entity was previously + transparent. */ + if (!bitmap_bit_p (confluence_info.transp, bb_index)) + return false; + + struct bb_info *bb_info = confluence_info.bb_info; + basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index); + int no_mode = confluence_info.no_mode; + int mode_in = bb_info[bb_index].mode_in; + int mode_out = bb_info[bb_index].computing; + if (mode_out == no_mode + 1) + { + /* The entity is still transparent for this block. See whether + all successor blocks need the same mode, either directly or + indirectly. */ + mode_out = bb_info[bb_index].single_succ; + if (mode_out == no_mode) + return false; + + /* Get a minimum bound on the number of transitions that would be + removed if BB itself required MODE_OUT. */ + unsigned int moved = 0; + for (edge e : bb->succs) + if (e->dest->index != EXIT_BLOCK + && mode_out == bb_info[e->dest->index].seginfo->mode) + moved += 1; + + /* See whether making the mode change on all incoming edges would + be no worse than making it on MOVED outgoing edges. */ + if (moved < EDGE_COUNT (bb->preds)) + return false; + + bb_info[bb_index].mode_out = mode_out; + bb_info[bb_index].computing = mode_out; + } + else if (mode_out == mode_in) + return false; + + bb_info[bb_index].mode_in = mode_out; + bb_info[bb_index].seginfo->mode = mode_out; + return true; +} + /* Find all insns that need a particular mode setting, and insert the necessary mode switches. Return true if we did work. */ @@ -685,6 +893,7 @@ optimize_mode_switching (void) } confluence_info.bb_info = info; + confluence_info.transp = nullptr; confluence_info.entity = entity; confluence_info.no_mode = no_mode; @@ -818,6 +1027,53 @@ optimize_mode_switching (void) } } + /* If the target requests it, back-propagate selected mode requirements + through transparent blocks. */ + if (targetm.mode_switching.backprop) + { + /* First work out the mode on entry to and exit from each block. */ + forwprop_mode_info (info, e, no_mode); + + /* Compute the single_succ fields, as described above + single_succ_confluence. */ + FOR_EACH_BB_FN (bb, cfun) + info[bb->index].single_succ = no_mode + 1; + + confluence_info.transp = transp_all; + bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun)); + df_simple_dataflow (DF_BACKWARD, NULL, NULL, + single_succ_confluence_n, + single_succ_transfer, blocks, + df_get_postorder (DF_BACKWARD), + df_get_n_blocks (DF_BACKWARD)); + + FOR_EACH_BB_FN (bb, cfun) + { + /* Repurpose mode_in as the first mode required by the block, + or the output mode if none. */ + if (info[bb->index].seginfo->mode != no_mode) + info[bb->index].mode_in = info[bb->index].seginfo->mode; + + /* In transparent blocks, use computing == no_mode + 1 + to indicate that no propagation has taken place. */ + if (info[bb->index].computing == no_mode) + info[bb->index].computing = no_mode + 1; + } + + bitmap_set_range (blocks, 0, last_basic_block_for_fn (cfun)); + df_simple_dataflow (DF_BACKWARD, NULL, NULL, backprop_confluence_n, + backprop_transfer, blocks, + df_get_postorder (DF_BACKWARD), + df_get_n_blocks (DF_BACKWARD)); + + /* Any block that now computes a mode is no longer transparent. */ + FOR_EACH_BB_FN (bb, cfun) + if (info[bb->index].computing == no_mode + 1) + info[bb->index].computing = no_mode; + else if (info[bb->index].computing != no_mode) + bitmap_clear_bit (transp_all, bb->index); + } + /* Set the anticipatable and computing arrays. */ for (i = 0; i < no_mode; i++) { @@ -899,6 +1155,22 @@ optimize_mode_switching (void) for (i = 0; i < no_mode; i++) if (mode_bit_p (del[bb->index], j, i)) info[bb->index].seginfo->mode = no_mode; + + /* See whether the target can perform the first transition. + If not, push it onto the incoming edges. The earlier backprop + pass should ensure that the resulting transitions are valid. */ + if (targetm.mode_switching.backprop) + { + int from_mode = info[bb->index].mode_in; + int to_mode = info[bb->index].seginfo->mode; + if (targetm.mode_switching.backprop (entity_map[j], from_mode, + to_mode) != no_mode) + { + for (edge e : bb->preds) + e->aux = (void *) (intptr_t) (to_mode + 1); + info[bb->index].mode_in = to_mode; + } + } } /* Now output the remaining mode sets in all the segments. */ diff --git a/gcc/target.def b/gcc/target.def index b08ede692f1..0996da0f71a 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -7070,6 +7070,35 @@ The hook should return the number of modes if no suitable mode exists\n\ for the given arguments.", int, (int entity, int mode1, int mode2), NULL) +DEFHOOK +(backprop, + "If defined, the mode-switching pass uses this hook to back-propagate mode\n\ +requirements through blocks that have no mode requirements of their own.\n\ +Specifically, @var{mode1} is the mode that @var{entity} has on exit\n\ +from a block B1 (say) and @var{mode2} is the mode that the next block\n\ +requires @var{entity} to have. B1 does not have any mode requirements\n\ +of its own.\n\ +\n\ +The hook should return the mode that it prefers or requires @var{entity}\n\ +to have in B1, or the number of modes if there is no such requirement.\n\ +If the hook returns a required mode for more than one of B1's outgoing\n\ +edges, those modes are combined as for @code{TARGET_MODE_CONFLUENCE}.\n\ +\n\ +For example, suppose there is a ``one-shot'' entity that,\n\ +for a given execution of a function, either stays off or makes exactly\n\ +one transition from off to on. It is safe to make the transition at any\n\ +time, but it is better not to do so unnecessarily. This hook allows the\n\ +function to manage such an entity without having to track its state at\n\ +runtime. Specifically. the entity would have two modes, 0 for off and\n\ +1 for on, with 2 representing ``don't know''. The system is forbidden from\n\ +transitioning from 2 to 1, since 2 represents the possibility that the\n\ +entity is already on (and the aim is to avoid having to emit code to\n\ +check for that case). This hook would therefore return 1 when @var{mode1}\n\ +is 2 and @var{mode2} is 1, which would force the entity to be on in the\n\ +source block. Applying this inductively would remove all transitions\n\ +in which the previous state is unknown.", + int, (int entity, int mode1, int mode2), NULL) + DEFHOOK (entry, "If this hook is defined, it is evaluated for every @var{entity} that\n\