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