https://gcc.gnu.org/g:73f32a2cbd8c3b910443448f8ab4a2d79e3ff520

commit r17-2066-g73f32a2cbd8c3b910443448f8ab4a2d79e3ff520
Author: Robin Dapp <[email protected]>
Date:   Mon Jun 29 22:13:30 2026 +0200

    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:
---
 gcc/doc/md.texi        | 13 +++++++++----
 gcc/lra-constraints.cc | 10 +++++++++-
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 1ef748796f5d..5ad4a201273d 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 a5e67eaae215..aed3b77038d4 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;
     }

Reply via email to