On 5/26/2026 8:22 AM, Robin Dapp wrote:
> From: Robin Dapp <[email protected]>
>
> This patch adds foundational support for register filters that depend on
> or reference another operand. The patch borrows heavily from Richard's
> work on register filters.
>
> As opposed to register filters, dependent filters need a runtime
> evaluation function that dispatches to a target function (usually).
> Common code can then evaluate the filter via
> eval_dependent_filter (id, ...);
>
> gcc/ChangeLog:
>
> * doc/md.texi: Document dependent filters.
> * doc/tm.texi: Ditto.
> * doc/tm.texi.in: Ditto.
> * genconfig.cc (main): Add number of dependent filters.
> * genpreds.cc (add_constraint): Add dependent-filter reference
> operand.
> (process_define_register_constraint): Handle dependent filter.
> (write_get_register_filter): Ditto.
> (write_get_register_filter_id): Ditto.
> (write_dependent_filter_helpers_h): Ditto.
> (write_dependent_filter_functions_c): Ditto.
> (write_tm_preds_h): Ditto.
> (write_insn_preds_c): Ditto.
> (main): Ditto.
> * gensupport.cc (process_define_register_constraint): Ditto.
> * gensupport.h (get_register_filter_id): Declare.
> * rtl.def (DEFINE_REGISTER_CONSTRAINT): Adjust for dependent
> filter.
> ---
> gcc/doc/md.texi | 19 +++++-
> gcc/doc/tm.texi | 3 +
> gcc/doc/tm.texi.in | 3 +
> gcc/genconfig.cc | 1 +
> gcc/genpreds.cc | 165 +++++++++++++++++++++++++++++++++++++++++++--
> gcc/gensupport.cc | 37 ++++++----
> gcc/gensupport.h | 2 +
> gcc/rtl.def | 12 +++-
> 8 files changed, 222 insertions(+), 20 deletions(-)
>
> diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
> index 94d258c3c91..2e1a1ef19f0 100644
> --- a/gcc/doc/md.texi
> +++ b/gcc/doc/md.texi
> @@ -4376,7 +4376,7 @@ Register constraints correspond directly to register
> classes.
> @xref{Register Classes}. There is thus not much flexibility in their
> definitions.
>
> -@deffn {MD Expression} define_register_constraint name regclass docstring
> [filter]
> +@deffn {MD Expression} define_register_constraint name regclass docstring
> [filter] [opno]
> All arguments are string constants.
> @var{name} is the name of the constraint, as it will appear in
> @code{match_operand} expressions. If @var{name} is a multi-letter
> @@ -4426,6 +4426,23 @@ sometimes necessary for a register of class @var{c} to
> be aligned
> to @var{n}, the first register in @var{c} should itself by divisible
> by @var{n}.
>
> +If even more fine-grained control is needed, the optional @var{opno}
> +can be specified. It indicates that the constraint is dependent on
> +another operand indicated by @var{opno}. When it is specified, a
> +@var{filter} must be specified as well. The filter function will then
> +be called with the current regno and mode of the operand the constraint
> +refers to as well as ref_regno and ref_mode of the operand @var{opno}
> +the filter depends on additionally.
> +
> +As such dependent filters are dynamic and cannot be precomputed, it is
> +advisable to use them very sparingly. Register allocation is a very
> +compile-time sensitive part of GCC, and too many, or too complicated
> +dynamic filters may increase the compile time significantly.
> +
> +@smallexample
> +(define_register_constraint "Wtt" "V_REGS" "..." "riscv_widen_overlap_ok
> (regno, mode, ref_regno, ref_mode)" "0")
> +@end smallexample
You might consider describing how we (plan to) use these things on the
RISC-V port to deal with the overlap problem.
> @@ -779,7 +786,8 @@ static void
> add_constraint (const char *name, const char *regclass,
> rtx exp, bool is_memory, bool is_special_memory,
> bool is_relaxed_memory, bool is_address, file_location loc,
> - const char *filter = nullptr)
> + const char *filter = nullptr,
> + int ref_opno = -1)
There's only a couple callers, consider avoiding the defaulted argument
by fixing the callers.
> @@ -969,9 +980,37 @@ process_define_constraint (md_rtx_info *info)
> static void
> process_define_register_constraint (md_rtx_info *info)
> {
> + /* Get the optional reference operand number the filter is
> + dependent on. */
> + const char *ref_str = XSTR (info->def, 4);
> + int ref_opno = -1;
> +
> + if (ref_str && !XSTR (info->def, 3))
> + {
> + error_at (info->loc, "depends_on operand specified without"
> + " a filter expression");
> + return;
> + }
> +
> + /* Parse it. */
> + if (ref_str)
> + {
> + char *end;
> + long n = strtol (ref_str, &end, 10);
> + /* MAX_RECOG_OPERANDS = 30 is defined in insn-config.h
> + but is not available here. */
Presumably no sensible way to share this value. Seems like a pointer
from genconfig.cc back here is in order.
Seems pretty sensible overall to me.
So guessing you want to get the infrastructure in place, then ask Pan Li
to do the conversion?
Jeff