From: Robin Dapp Date: Mon, 29 Jun 2026 20:13:30 +0000 (+0200) Subject: lra: Pass INVALID_REGNUM to dependent filter. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=73f32a2cbd8c3b910443448f8ab4a2d79e3ff520;p=thirdparty%2Fgcc.git lra: Pass INVALID_REGNUM to dependent filter. When the reference operand for a dependent filters is not yet chosen, we currently just allow everything. This can lead to situations where we fix a hard reg early, only for it to be rejected later. That's unreasonable and cannot be salvaged by lra. This patch gives the filter a chance to reject early in this situation and documents that IVNALID_REGNUM can be passed to dependent filters. It also adds Stefan's suggestion to look through subregs before filtering. gcc/ChangeLog: * doc/md.texi: Document new behavior. * lra-constraints.cc (get_dependent_filter): Call filter with INVALID_REGNUM ref op instead of allowing everything. --- diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 1ef748796f5..5ad4a201273 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -4442,15 +4442,20 @@ 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. +Note that either of the regnos can be INVALID_REGNUM to indicate that the +register allocator hasn't yet allocated a hard reg. For certain kinds +of filters it is still possible to reject regnos, even if the ref_regno is +unknown. + 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. -As an example, the riscv port must ensure that for widening vector -instructions, the destination register group either does not overlap -or only overlaps specific parts of the source. A dynamic register -constraint would then be: +An example for dependent filter usage is the riscv port. It must ensure +that for widening vector instructions, the destination register group either +does not overlap the source or only overlaps specific parts it. A dynamic +register constraint would then be: @smallexample (define_register_constraint "Wtt" "V_REGS" "..." "riscv_widen_overlap_ok (regno, mode, ref_regno, ref_mode)" "0") diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index a5e67eaae21..aed3b77038d 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -2359,14 +2359,22 @@ get_dependent_filter (constraint_num cn, machine_mode mode) gcc_assert (ref_opno >= 0 && ref_opno < curr_static_id->n_operands); rtx ref_op = *curr_id->operand_loc[ref_opno]; + if (SUBREG_P (ref_op)) + ref_op = SUBREG_REG (ref_op); if (!REG_P (ref_op)) return nullptr; unsigned int ref_regno = REGNO (ref_op); if (ref_regno >= FIRST_PSEUDO_REGISTER) { int ref_hard_regno = reg_renumber[ref_regno]; + /* Even with a pseudo reference op, the filter can still reject + based on the partner. We call it with INVALID_REGNUM + to give it a chance to do so. Otherwise we'd introduce + an "all choices legal" filter that might later + "change its mind" once there is a fixed reference. */ if (ref_hard_regno < 0) - return nullptr; + return lra_get_dependent_filter (id, mode, INVALID_REGNUM, + GET_MODE (ref_op), false); ref_regno = (unsigned int) ref_hard_regno; }