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. */ @@ -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; -- 2.49.0