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.

Reply via email to