https://gcc.gnu.org/g:0fa5a39cc51e37f5002a5c279053a793867dd8aa
commit r16-5454-g0fa5a39cc51e37f5002a5c279053a793867dd8aa Author: Tamar Christina <[email protected]> Date: Thu Nov 20 14:14:59 2025 +0000 middle-end: add target hook for isel 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. Diff: --- gcc/doc/tm.texi | 14 ++++++++++++++ gcc/doc/tm.texi.in | 2 ++ gcc/gimple-isel.cc | 3 +++ gcc/target.def | 17 +++++++++++++++++ gcc/targhooks.cc | 8 ++++++++ gcc/targhooks.h | 2 +- 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index fd208f53844a..25aad2eb74b6 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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 diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 14315dd50805..24d47b19e5f1 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -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 diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc index e745608904e3..269151ac21dd 100644 --- a/gcc/gimple-isel.cc +++ b/gcc/gimple-isel.cc @@ -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); diff --git a/gcc/target.def b/gcc/target.def index f288329ffcab..61931278fd93 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -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\ diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index 1873d572ba3f..ab398673b476 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -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) diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 92e7a4cb10f1..01d4fc7a4508 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -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);
