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; +}
