From: Stefan Schulze Frielinghaus <[email protected]>
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 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.
---
Bootstrapped and regtested on s390 and x86_64. Verified via a cross
compiler testsuite/gcc.target/avr/pr121198.c. Ok for mainline?
gcc/lra-constraints.cc | 5 ++++-
gcc/testsuite/gcc.target/avr/pr121198.c | 10 ++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/avr/pr121198.c
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index b1529979174..48ce75781d4 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 00000000000..551247e1d34
--- /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;
+}
--
2.49.0