On Tue, May 06, 2025 at 01:17:40PM +0100, Richard Sandiford wrote:
> 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.  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 <dimi...@dinux.eu>
> > ---
> >  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

Reply via email to