On Tue, May 06, 2025 at 01:17:40PM +0100, Richard Sandiford wrote:
> Dimitar Dimitrov <[email protected]> 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. Remove the premature "success"
> > return for paradoxical subregs, in order to allow subsequent validity
> > checks to be executed.
> >
> > 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
> > I consider these two a separate issue.
> >
> > I ensured that test results with and without this patch for
> > x86_64-pc-linux-gnu are the same for C and C++.
> >
> > Ok for trunk?
> >
> > PR target/119966
> >
> > gcc/ChangeLog:
> >
> > * emit-rtl.cc (validate_subreg): Do not exit immediately for
> > paradoxical subregs. Add mode checks for validity of
> > hardware subregs.
> >
> > Signed-off-by: Dimitar Dimitrov <[email protected]>
> > ---
> > gcc/emit-rtl.cc | 9 ++++++---
> > 1 file changed, 6 insertions(+), 3 deletions(-)
> >
> > diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
> > index 3e2c4309dee..d63543038bb 100644
> > --- a/gcc/emit-rtl.cc
> > +++ b/gcc/emit-rtl.cc
> > @@ -969,10 +969,10 @@ validate_subreg (machine_mode omode, machine_mode
> > imode,
> > }
> >
> > /* Paradoxical subregs must have offset zero. */
> > - if (maybe_gt (osize, isize))
> > - return known_eq (offset, 0U);
> > + if (maybe_gt (osize, isize) && !known_eq (offset, 0U))
> > + return false;
> >
> > - /* This is a normal subreg. Verify that the offset is representable. */
> > + /* Verify that the offset is representable. */
> >
> > /* For hard registers, we already have most of these rules collected in
> > subreg_offset_representable_p. */
>
> This part seems fine, but...
Linaro CI bot notified me that this chunk caused ICE regression for
armv8l-unknown-linux-gnueabihf. Combine creates paradoxical MEM
subregs, which fail the validate_subreg check a few lines below:
/* Do not allow SUBREG with stricter alignment than the inner MEM. */
else if (reg && MEM_P (reg) && STRICT_ALIGNMENT
&& MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (omode))
return false;
And then the following assert is triggered:
rtx
gen_rtx_SUBREG (machine_mode mode, rtx reg, poly_uint64 offset)
{
gcc_assert (validate_subreg (mode, GET_MODE (reg), reg, offset));
If I understand the documentation correctly, this is an issue with
combine. A subreg of mem should have never been created for aarch64
since it defines INSN_SCHEDULING.
>
> > @@ -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;
> > else if (!REG_CAN_CHANGE_MODE_P (regno, imode, omode))
> > return false;
>
> ...this is IMO a logically separate change...
I'll send this chunk as a separate patch since it is required to
fix the regression for pru-unknown-elf.
> ...Instead, I think we want
> to add known_le (osize, isize) to:
>
> if (maybe_lt (osize, regsize)
> && ! (lra_in_progress && (FLOAT_MODE_P (imode) || FLOAT_MODE_P
> (omode))))
>
> since the test is not correct for big-endian paradoxical subregs,
> and is redundant for little-endian paradoxical subregs.
>
That change indeed fixes libgcc build for powerpc64-unknown-linux-gnu.
I'll add it in the next patch revision.
Regards,
Dimitar
> Thanks,
> Richard