https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124643
--- Comment #7 from Richard Sandiford <rsandifo at gcc dot gnu.org> ---
It looks like the late-combine ICE might just exposing invalid RTL created by
an earlier pass, namely cse_local. cse_local propagates the T register from
insn 8 to insn 10 in:
(insn 8 7 10 2 (set (reg:SI 173)
(reg:SI 147 t)) "/tmp/pr.c":4:24 … {movt}
(expr_list:REG_DEAD (reg:SI 147 t)
(nil)))
(insn 10 8 12 2 (set (reg:SI 170 [ _16+-3 ])
(zero_extend:SI (subreg:QI (reg:SI 173) 3))) …
{*zero_extendqisi2_compact}
(nil))
giving:
(insn 10 7 12 2 (set (reg:SI 170 [ _16+-3 ])
(zero_extend:SI (subreg:QI (reg:SI 147 t) 3))) … {movt}
(expr_list:REG_DEAD (reg:SI 173)
(nil)))
even though this subreg is invalid according to validate_subreg.
Note how the insn is now "movt". And indeed, t_reg_operand has:
case ZERO_EXTEND:
case SIGN_EXTEND:
if (REG_P (XEXP (op, 0)) && REGNO (XEXP (op, 0)) == T_REG)
return true;
return GET_CODE (XEXP (op, 0)) == SUBREG
&& REG_P (SUBREG_REG (XEXP (op, 0)))
&& REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG;
I don't understand what the port is trying to do. Why is zero-extension
equivalent to a move? Why does sh_hard_regno_mode_ok specifically reject
anything other than SImode for the T register, then go to such lengths to allow
QImode references via extension? If the T register is just a single bit,
wouldn't QImode and HImode be valid too?
Rejecting QImode for the T register is what makes validate_subreg reject the
subreg.