]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
middle-end: add target hook for isel
authorTamar Christina <tamar.christina@arm.com>
Thu, 20 Nov 2025 14:14:59 +0000 (14:14 +0000)
committerTamar Christina <tamar.christina@arm.com>
Thu, 20 Nov 2025 14:14:59 +0000 (14:14 +0000)
This adds a new target hook to gimple-sel to allow targets to
do target specific massaging of the gimple IL to prepare for
expand.

Tejas will be sending up part 2 of this soon to help convert
SVE packed boolean VEC_COND_EXPR into something that we can
handle more efficiently if expanded in a different order.

We also want to use this to e.g. for Adv. SIMD prefer avoiding
!= vector compare expressions because the ISA doesn't have
this instruction and so we expand to == + ~ but changing the
expression from a MIN to MAX only for VECTOR_BOOLEAN_TYPE_P
and flipping the operands we can expand more efficient.

These are the kind of things we want to use the hook for,
not generic changes that apply to all target.

gcc/ChangeLog:

* target.def (instruction_selection): New.
* doc/tm.texi.in: Document it.
* doc/tm.texi: Regenerate
* gimple-isel.cc (pass_gimple_isel::execute): Use it.
* targhooks.cc (default_instruction_selection): New.
* targhooks.h (default_instruction_selection): New.

gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/gimple-isel.cc
gcc/target.def
gcc/targhooks.cc
gcc/targhooks.h

index fd208f53844a157721dd8a0282f283da64cf5d93..25aad2eb74b6c3bedb5d527c6bfe216347d48a01 100644 (file)
@@ -6628,6 +6628,20 @@ like @code{cond_add@var{m}}.  The default implementation returns a zero
 constant of type @var{type}.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_INSTRUCTION_SELECTION (function *@var{fun}, gimple_stmt_iterator *@var{gsi})
+This hook allows a target to perform custom instruction selection for an
+instruction or sequence of instructions before expand to allow expansion to
+generate more efficient code.
+
+@var{fun} is the current function being considered and @var{gsi} is the
+iterator pointing to the current instruction being optimized.  The default
+implementation does not do any rewriting and returns false.  The result of
+the function should be whether any changes were made to the CFG or not.  If a
+change was made then the @var{gsi} should be left at the same position as at
+the function start.  The caller is allowed to change the CFG at any point
+before the current statement @var{gsi} is pointing to but not afterwards.
+@end deftypefn
+
 @deftypefn {Target Hook} tree TARGET_GOACC_ADJUST_PRIVATE_DECL (location_t @var{loc}, tree @var{var}, int @var{level})
 This hook, if defined, is used by accelerator target back-ends to adjust
 OpenACC variable declarations that should be made private to the given
index 14315dd508051037b7936c89638c05f07b6d3d6f..24d47b19e5f13e15f9d0b0e9c0b343825ce6e761 100644 (file)
@@ -4352,6 +4352,8 @@ address;  but often a machine-dependent strategy can generate better code.
 
 @hook TARGET_PREFERRED_ELSE_VALUE
 
+@hook TARGET_INSTRUCTION_SELECTION
+
 @hook TARGET_GOACC_ADJUST_PRIVATE_DECL
 
 @hook TARGET_GOACC_EXPAND_VAR_DECL
index e745608904e3db77a88d861bc6512afe67a82480..269151ac21dd05bfb0dc16529e54521d32703a9f 100644 (file)
@@ -1357,6 +1357,9 @@ pass_gimple_isel::execute (struct function *fun)
     {
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
+         /* Give the target first try at replacing the instruction.  */
+         cfg_changed |= targetm.instruction_selection (fun, &gsi);
+
          /* Pre-expand VEC_COND_EXPRs to .VCOND* internal function
             calls mapping to supported optabs.  */
          gimple *g = gimple_expand_vec_cond_expr (&gsi);
index f288329ffcab81e2773c2066e60a470611f29e23..61931278fd936eae8ae16aee772ace409144d22f 100644 (file)
@@ -2137,6 +2137,23 @@ constant of type @var{type}.",
  (unsigned ifn, tree type, unsigned nops, tree *ops),
  default_preferred_else_value)
 
+DEFHOOK
+(instruction_selection,
+ "This hook allows a target to perform custom instruction selection for an\n\
+instruction or sequence of instructions before expand to allow expansion to\n\
+generate more efficient code.\n\
+\n\
+@var{fun} is the current function being considered and @var{gsi} is the\n\
+iterator pointing to the current instruction being optimized.  The default\n\
+implementation does not do any rewriting and returns false.  The result of\n\
+the function should be whether any changes were made to the CFG or not.  If a\n\
+change was made then the @var{gsi} should be left at the same position as at\n\
+the function start.  The caller is allowed to change the CFG at any point\n\
+before the current statement @var{gsi} is pointing to but not afterwards.",
+ bool,
+ (function *fun, gimple_stmt_iterator *gsi),
+ default_instruction_selection)
+
 DEFHOOK
 (record_offload_symbol,
  "Used when offloaded functions are seen in the compilation unit and no named\n\
index 1873d572ba3fb59c4713e10b5c5b14afb029b953..ab398673b4763e9d062f565d73732f38e60619c0 100644 (file)
@@ -2764,6 +2764,14 @@ default_preferred_else_value (unsigned, tree type, unsigned, tree *)
   return build_zero_cst (type);
 }
 
+/* The default implementation of TARGET_INSTRUCTION_SELECTION.  */
+
+bool
+default_instruction_selection (function *, gimple_stmt_iterator *)
+{
+  return false;
+}
+
 /* Default implementation of TARGET_HAVE_SPECULATION_SAFE_VALUE.  */
 bool
 default_have_speculation_safe_value (bool active ATTRIBUTE_UNUSED)
index 92e7a4cb10f109978301d8c10f69b4c5a3952f56..01d4fc7a4508da2fa138bd135406656bd72ab2cf 100644 (file)
@@ -305,7 +305,7 @@ extern machine_mode default_mode_for_floating_type (enum tree_index);
 extern HOST_WIDE_INT default_stack_clash_protection_alloca_probe_range (void);
 extern void default_select_early_remat_modes (sbitmap);
 extern tree default_preferred_else_value (unsigned, tree, unsigned, tree *);
-
+extern bool default_instruction_selection (function *, gimple_stmt_iterator *);
 extern bool default_have_speculation_safe_value (bool);
 extern bool speculation_safe_value_not_needed (bool);
 extern rtx default_speculation_safe_value (machine_mode, rtx, rtx, rtx);