https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64785
Oleg Endo <olegendo at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2015-01-27 CC| |kkojima at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #1 from Oleg Endo <olegendo at gcc dot gnu.org> --- It seems that hardregs in insn operands are kind of sticky. Combine propagates the function arg in r5 into the and insn and this doesn't get changed to r0. Disallowing combine to do that seems to fix the problem, although I haven't checked for any other side effects of that change. Probably some code will get worse for insns that really use hardregs (e.g. libfuncs). Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (revision 220144) +++ gcc/config/sh/sh.c (working copy) @@ -2066,6 +2066,26 @@ && MEM_P (XEXP (XEXP (p, 1), 0))) return false; + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (i, array, p, ALL) + { + if (*i == NULL) + continue; + int regno = -1; + for (const_rtx x = *i; regno == -1; ) + { + if (REG_P (x)) + regno = REGNO (x); + else if (SUBREG_P (x)) + x = SUBREG_REG (x); + else + break; + } + + if (regno != -1 && regno >= R0_REG && regno <= R0_REG + 15) + return false; + } + return true; } Another more radical approach could be to insert an RTL pass that pre-allocates the R0 reg for those insns that have "z" constraint alternatives, similar to what Kaz did with the mov.{b|w} patterns in prepare_move_operands for LRA.