===================================================================
@@ -306,6 +306,8 @@
extern bool sh_reg_dead_or_unused_after_insn (const rtx_insn* i, int regno);
extern void sh_remove_reg_dead_or_unused_notes (rtx_insn* i, int regno);
extern rtx_insn* sh_check_add_incdec_notes (rtx_insn* i);
+extern rtx sh_remove_overlapping_post_inc (rtx dst, rtx src);
+extern rtx_insn* sh_peephole_emit_move_insn (rtx dst, rtx src);
extern bool sh_in_recog_treg_set_expr (void);
extern bool sh_recog_treg_set_expr (rtx op, machine_mode mode);
===================================================================
@@ -13810,6 +13810,34 @@
return i;
}
+/* Given a move insn destiation and a source, make sure that the move source
+ operand is not a post-inc mem load with the same address reg as the
+ destination. Returns the modified source operand with the post-inc removed
+ if necessary. */
+rtx
+sh_remove_overlapping_post_inc (rtx dst, rtx src)
+{
+ if (!MEM_P (src))
+ return src;
+
+ rtx addr = XEXP (src, 0);
+
+ if (GET_CODE (addr) == POST_INC
+ && reg_overlap_mentioned_p (XEXP (addr, 0), dst))
+ return replace_equiv_address (src, XEXP (addr, 0));
+
+ gcc_assert (GET_CODE (addr) != POST_MODIFY);
+ return src;
+}
+
+/* Emit a move insn that is safe to be used in peephole patterns. */
+rtx_insn*
+sh_peephole_emit_move_insn (rtx dst, rtx src)
+{
+ return sh_check_add_incdec_notes (
+ emit_move_insn (dst, sh_remove_overlapping_post_inc (dst, src)));
+}
+
/* Given an op rtx and an insn, try to find out whether the result of the
specified op consists only of logical operations on T bit stores. */
bool
===================================================================
@@ -14681,7 +14681,7 @@
[(const_int 0)]
{
emit_insn (gen_addsi3 (operands[1], operands[1], operands[2]));
- sh_check_add_incdec_notes (emit_move_insn (operands[3], operands[1]));
+ sh_peephole_emit_move_insn (operands[3], operands[1]);
})
;; mov.l @(r0,r9),r1
@@ -14694,7 +14694,7 @@
"TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
[(const_int 0)]
{
- sh_check_add_incdec_notes (emit_move_insn (operands[2], operands[1]));
+ sh_peephole_emit_move_insn (operands[2], operands[1]);
})
(define_peephole2
@@ -14705,7 +14705,7 @@
"TARGET_SH1 && peep2_reg_dead_p (2, operands[0])"
[(const_int 0)]
{
- sh_check_add_incdec_notes (emit_move_insn (operands[2], operands[1]));
+ sh_peephole_emit_move_insn (operands[2], operands[1]);
})
(define_peephole2
@@ -14717,7 +14717,7 @@
[(const_int 0)]
{
sh_check_add_incdec_notes (emit_insn (gen_extend<mode>si2 (operands[2],
- operands[1])));
+ sh_remove_overlapping_post_inc (operands[2], operands[1]))));
})
;; mov.w @(18,r1),r0 (r0 = HImode)
@@ -14747,8 +14747,9 @@
// We don't know what the new set insn will be in detail. Just make sure
// that it still can be recognized and the constraints are satisfied.
- rtx_insn* i = emit_insn (gen_rtx_SET (operands[2], operands[3]));
-
+ rtx_insn* i = emit_insn (gen_rtx_SET (operands[2],
+ sh_remove_overlapping_post_inc (operands[2], operands[3])));
+
recog_data_d prev_recog_data = recog_data;
bool i_invalid = insn_invalid_p (i, false);
recog_data = prev_recog_data;
@@ -14786,7 +14787,8 @@
{
// We don't know what the new set insn will be in detail. Just make sure
// that it still can be recognized and the constraints are satisfied.
- rtx_insn* i = emit_insn (gen_rtx_SET (operands[2], operands[3]));
+ rtx_insn* i = emit_insn (gen_rtx_SET (operands[2],
+ sh_remove_overlapping_post_inc (operands[2], operands[3])));
recog_data_d prev_recog_data = recog_data;
bool i_invalid = insn_invalid_p (i, false);