https://gcc.gnu.org/g:7fc6024998c37114556912c15d3eae024d310667

commit r16-4732-g7fc6024998c37114556912c15d3eae024d310667
Author: Stefan Schulze Frielinghaus <[email protected]>
Date:   Thu Oct 30 13:50:46 2025 +0100

    lra: Fix computing reg class for hard register constraints [PR121198]
    
    Currently the register class derived from a hard register constraint is
    solely determined from a single register.  This even works for register
    pairs if all the required registers are contained in this very register
    class and falls apart if not.  For example:
    
    long
    test (void)
    {
      long x;
      __asm__ ("..." : "={r22}" (x));
      return x;
    }
    
    For AVR -mmcu=atmega8, variable `x` requires a register quadruple and
    the minimal class for single register r22 is SIMPLE_LD_REGS which itself
    entails registers r16 up to r23.  However, variable `x` is bound to
    registers r22 up to r25.  Thus, the minimal class containing those is
    LD_REGS.  Therefore, compute the least upper bound of all register
    classes over all required registers.
    
            PR rtl-optimization/121198
    
    gcc/ChangeLog:
    
            * lra-constraints.cc (process_alt_operands): Compute least upper
            bound of all register classes over all required registers in
            order to determine register class for a hard register constraint.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/avr/pr121198.c: New test.

Diff:
---
 gcc/lra-constraints.cc                  |  5 ++++-
 gcc/testsuite/gcc.target/avr/pr121198.c | 10 ++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index b15299791745..48ce75781d4b 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -2552,7 +2552,10 @@ process_alt_operands (int only_alternative)
                    {
                      int regno = decode_hard_reg_constraint (p);
                      gcc_assert (regno >= 0);
-                     cl = REGNO_REG_CLASS (regno);
+                     cl = NO_REGS;
+                     int nregs = hard_regno_nregs (regno, mode);
+                     for (int i = 0; i < nregs; ++i)
+                       cl = reg_class_superunion[cl][REGNO_REG_CLASS (regno + 
i)];
                      CLEAR_HARD_REG_SET (hard_reg_constraint);
                      SET_HARD_REG_BIT (hard_reg_constraint, regno);
                      cl_filter = &hard_reg_constraint;
diff --git a/gcc/testsuite/gcc.target/avr/pr121198.c 
b/gcc/testsuite/gcc.target/avr/pr121198.c
new file mode 100644
index 000000000000..551247e1d34b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/pr121198.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mmcu=atmega8" } */
+
+long
+test (void)
+{
+  long x;
+  __asm__ ("" : "={r22}" (x));
+  return x;
+}

Reply via email to