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...

> @@ -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.  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.

Thanks,
Richard

Reply via email to