]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
lra: Pass INVALID_REGNUM to dependent filter.
authorRobin Dapp <robin.dapp@oss.qualcomm.com>
Mon, 29 Jun 2026 20:13:30 +0000 (22:13 +0200)
committerRobin Dapp <robin.dapp@oss.qualcomm.com>
Wed, 1 Jul 2026 18:22:05 +0000 (20:22 +0200)
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.

gcc/doc/md.texi
gcc/lra-constraints.cc

index 1ef748796f5d0de63127b86c9903c9b12420bebf..5ad4a201273d52bd48aecf6780f901a20f5245bd 100644 (file)
@@ -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")
index a5e67eaae215d294578f72091fd624167b7db43b..aed3b77038d418d02e4598c8a64f47fdaa8745f3 100644 (file)
@@ -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;
     }