Dimitar Dimitrov <dimi...@dinux.eu> writes: > After r16-160-ge6f89d78c1a752, late_combine2 started transforming the > following RTL for pru-unknown-elf: > > (insn 3949 3948 3951 255 (set (reg:QI 56 r14.b0 [orig:1856 _619 ] [1856]) > (and:QI (reg:QI 1 r0.b1 [orig:1855 _201 ] [1855]) > (const_int 3 [0x3]))) > (nil)) > ... > (insn 3961 7067 3962 255 (set (reg:SI 56 r14.b0) > (zero_extend:SI (reg:QI 56 r14.b0 [orig:1856 _619 ] [1856]))) > (nil)) > > into: > > (insn 3961 7067 3962 255 (set (reg:SI 56 r14.b0) > (and:SI (subreg:SI (reg:QI 1 r0.b1 [orig:1855 _201 ] [1855]) 0) > (const_int 3 [0x3]))) > (nil)) > > That caused libbacktrace build to break for pru-unknown-elf. Register > r0.b1 (regno 1) is not valid for SImode, which validate_subreg failed to > reject. > > Fix by calling HARD_REGNO_MODE_OK to ensure that both inner and outer > modes are valid for the hardware subreg. > > This patch fixes the broken PRU toolchain build. It leaves only two > test case regressions for PRU, caused by rnreg pass renaming a valid > paradoxical subreg into an invalid one. > gcc.c-torture/execute/20040709-1.c > gcc.c-torture/execute/20040709-2.c > > PR target/119966 > > gcc/ChangeLog: > > * emit-rtl.cc (validate_subreg): Validate inner > and outer mode for paradoxical hardware subregs. > > Co-authored-by: Andrew Pinski <pins...@gmail.com> > Signed-off-by: Dimitar Dimitrov <dimi...@dinux.eu> > --- > gcc/emit-rtl.cc | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc > index e46b0f9eac4..6c5d9b55508 100644 > --- a/gcc/emit-rtl.cc > +++ b/gcc/emit-rtl.cc > @@ -983,6 +983,9 @@ validate_subreg (machine_mode omode, machine_mode imode, > if ((COMPLEX_MODE_P (imode) || VECTOR_MODE_P (imode)) > && GET_MODE_INNER (imode) == omode) > ; > + else if (!targetm.hard_regno_mode_ok (regno, imode) > + || !targetm.hard_regno_mode_ok (regno, omode)) > + return false;
It isn't meaningful to test regno against omode, since that isn't necessarily the register that would be produced by the subreg. ISTR that this is a sensitive part of the codebase. I think there are/were targets that create unfoldable subregs for argument passing and return. And I think e500 had unfoldable subregs of FP registers, although that port is gone now. So I suppose the question is: when given a hard register, should validate_subreg test whether the subreg can be folded to a hard register? Or is it more relaxed than that? Do we need different rules before LRA (which could fix up subregs through reloading) and after LRA (where unfoldable subregs stay unfoldable). If validate_subreg should test whether a subreg of a hard register can be folded to a hard register, the fix would be to use simplify_subreg_regno instead of the current tests. But it looks like that was deliberately not done. It might still be worth trying to use simplify_subreg_regno and seeing what breaks. Any fallaout would at least let us expand the comments to explain the constraints. Thanks, Richard