[v2] Mode-Switching: Add optional EMIT_AFTER hook

Message ID 20230826133634.610777-1-pan2.li@intel.com
State Accepted
Headers
Series [v2] Mode-Switching: Add optional EMIT_AFTER hook |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Li, Pan2 via Gcc-patches Aug. 26, 2023, 1:36 p.m. UTC
  From: Pan Li <pan2.li@intel.com>

Update in v2:

* Remove control flow check in BB_END.
* Passed x86 bootstrap and regression test.

Original log:

We have EMIT hook in mode switching already, which will insert the
insn before in most cases. However, in some arch like RISC-V, it
requires the additional insn to be inserted after when meet a call.

       |
       | <- EMIT HOOK, insert the insn before.
 +-----------+
 | ptr->insn |
 +-----------+
       | <- EMIT_AFTER HOOK, insert the insn after.
       |

Thus, this patch would like to add one optional EMIT_AFTER hook, which
will try to insert the emitted insn after. The end-user can either
implement this HOOK or leave it NULL as is.

If the backend ignore this optinal hook, there is no impact to the
original mode switching stuff. If the backend implement this optional
hook, the mode switching will try to insert the insn after. Please note
the EMIT_AFTER doen't have any impact to EMIT hook.

Signed-off-by: Pan Li <pan2.li@intel.com>

gcc/ChangeLog:

	* doc/tm.texi: Add hook def and update the description.
	* doc/tm.texi.in: Ditto.
	* mode-switching.cc (optimize_mode_switching): Insert the
	emitted insn after ptr->insn.
	* target.def (insn): Define emit_after hook.
---
 gcc/doc/tm.texi       | 12 ++++++++++--
 gcc/doc/tm.texi.in    |  6 ++++--
 gcc/mode-switching.cc | 43 +++++++++++++++++++++++++++++++++++++++++++
 gcc/target.def        |  9 +++++++++
 4 files changed, 66 insertions(+), 4 deletions(-)
  

Patch

diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index d0d47b0d471..9b93a85f634 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10334,8 +10334,8 @@  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.
+@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, @code{TARGET_MODE_EMIT_AFTER},
+and @code{TARGET_MODE_EXIT} are optional.
 @end defmac
 
 @defmac NUM_MODES_FOR_MODE_SWITCHING
@@ -10359,6 +10359,14 @@  to switch from. 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} void TARGET_MODE_EMIT_AFTER (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 after. @var{prev_moxde} indicates the mode
+to switch from. 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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 4ac96dc357d..2942ce0be3b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -6911,8 +6911,8 @@  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.
+@code{TARGET_MODE_AFTER}, @code{TARGET_MODE_ENTRY}, @code{TARGET_MODE_EMIT_AFTER},
+and @code{TARGET_MODE_EXIT} are optional.
 @end defmac
 
 @defmac NUM_MODES_FOR_MODE_SWITCHING
@@ -6930,6 +6930,8 @@  switch is needed / supplied.
 
 @hook TARGET_MODE_EMIT
 
+@hook TARGET_MODE_EMIT_AFTER
+
 @hook TARGET_MODE_NEEDED
 
 @hook TARGET_MODE_AFTER
diff --git a/gcc/mode-switching.cc b/gcc/mode-switching.cc
index f483c831c35..0127fb42330 100644
--- a/gcc/mode-switching.cc
+++ b/gcc/mode-switching.cc
@@ -34,6 +34,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "lcm.h"
 #include "cfgcleanup.h"
 #include "tree-pass.h"
+#include "gcse.h"
 
 /* We want target macros for the mode switching code to be able to refer
    to instruction attribute values.  */
@@ -831,6 +832,48 @@  optimize_mode_switching (void)
 			emit_insn_before (mode_set, ptr->insn_ptr);
 		    }
 
+		  if (targetm.mode_switching.emit_after)
+		    {
+		      if (ptr->insn_ptr != BB_END (bb))
+			{
+			  start_sequence ();
+			  targetm.mode_switching.emit_after (entity_map[j],
+			    ptr->mode, cur_mode, ptr->regs_live);
+			  mode_set = get_insns ();
+			  end_sequence ();
+
+			  if (mode_set != NULL_RTX)
+			    {
+			      emit_insn_after (mode_set, ptr->insn_ptr);
+			      emitted = true;
+			    }
+			}
+		      else
+			{
+			  edge eg;
+			  edge_iterator eg_iterator;
+
+			  FOR_EACH_EDGE (eg, eg_iterator, bb->succs)
+			    {
+			      start_sequence ();
+			      targetm.mode_switching.emit_after (entity_map[j],
+				ptr->mode, cur_mode, ptr->regs_live);
+			      mode_set = get_insns ();
+			      end_sequence ();
+
+			      if (mode_set != NULL_RTX)
+				{
+				  if (eg->flags & EDGE_ABNORMAL)
+				    insert_insn_end_basic_block (mode_set, bb);
+				  else
+				    insert_insn_on_edge (mode_set, eg);
+
+				  emitted = true;
+				  need_commit = true;
+				}
+			    }
+			}
+		    }
 		  default_rtl_profile ();
 		}
 
diff --git a/gcc/target.def b/gcc/target.def
index 05f267183a3..8a5426cf9ad 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -7005,6 +7005,15 @@  to switch from. 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
+(emit_after,
+ "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 after. @var{prev_moxde} indicates the mode\n\
+to switch from. 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\