https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65979
--- Comment #15 from Oleg Endo <olegendo at gcc dot gnu.org> --- (In reply to Oleg Endo from comment #14) > > I think the check operands[1] / operands[2] check should go into the > preparation statement. operands[0] is dying after this peephole, so I guess > this should work: > I have confirmed that the following fixes the test case in attachment 35572: Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 223416) +++ gcc/config/sh/sh.md (working copy) @@ -14721,6 +14721,9 @@ || REGNO (operands[2]) == REGNO (operands[5]))" [(const_int 0)] { + if (reg_overlap_mentioned_p (operands[1], operands[2])) + std::swap (operands[0], operands[2]); + sh_check_add_incdec_notes (emit_move_insn (operands[2], operands[3])); emit_insn (gen_tstsi_t (operands[2], gen_rtx_REG (SImode, (REGNO (operands[1]))))); However, I think that the emit_move_insn could also be a source of hidden problems. For instance, if the captured insn (set (match_operand:SI 2 "arith_reg_dest") (match_operand:SI 3)) is not a move insn, but some computation like (set (reg) (plus:SI ... )). I'm not sure what emit_move_insn is going to do in this case. Maybe a better way would be to copy/re-emit the captured original insn in a different way.