https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65249
--- Comment #5 from Oleg Endo <olegendo at gcc dot gnu.org> --- On trunk, I've tried adding this: (define_split [(set (match_operand:SI 0 "arith_reg_dest") (mem:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") (match_operand:SI 2 "arith_reg_operand"))))] "TARGET_SH1 && can_create_pseudo_p ()" [(const_int 0)] { rtx tmp = gen_reg_rtx (SImode); rtx r0 = gen_rtx_REG (SImode, R0_REG); emit_move_insn (tmp, r0); emit_move_insn (r0, operands[1]); rtx mem = replace_equiv_address (XEXP (PATTERN (curr_insn), 1), gen_rtx_PLUS (SImode, r0, operands[2]), false); emit_move_insn (operands[0], mem); emit_move_insn (r0, tmp); }) to workaround the r0 spill failure for the (r0+rm) mem load. Then another spill failure with the 'cmp/eq #imm,r0' insn popped up. So I've added this: (define_split [(set (reg:SI T_REG) (eq:SI (match_operand:SI 1 "arith_reg_operand") (match_operand:SI 2 "const_int_operand")))] "TARGET_SH1 && can_create_pseudo_p () && satisfies_constraint_I08 (operands[2])" [(const_int 0)] { rtx tmp = gen_reg_rtx (SImode); rtx r0 = gen_rtx_REG (SImode, R0_REG); emit_move_insn (tmp, r0); emit_move_insn (r0, operands[1]); emit_insn (gen_cmpeqsi_t (r0, operands[2])); emit_move_insn (r0, tmp); }) With those two split patterns added attachment 34901 compiles. This is basically the same trick as done in prepare_move_operands for QIHImode loads with displacement. Effectively it pre-allocates the r0 uses and shortens the r0 live ranges. When compiling with LRA the resulting code seems a bit better (comment #4), too. I haven't checked the impact on average code (CSiBE) though. While we probably could add those two patterns as a quick fix, I don't think it's a great solution, because we'd actually need to add such patterns for *all* insns that have the 'z'/r0 constraint. In this case it might be better to add an SH specific RTL pass before IRA which can do such kind of RA preparations to improve the RA result/process.