Hi, This fixes PR 67657 on trunk. It seems that something after the peephole2 pass is not happy to see things like: mov.l @r2+,r2
which some of the SH peephole2 patterns create out of e.g. mov.l @r2+,r0 mov r0,r2 The post-inc is a bit pointless, so this patch catches such cases and replaces the address in the mem with a non-post-inc address. Tested on sh-elf with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}" Committed as r227969. A backport to GCC 5 will follow. Cheers, Oleg gcc/ChangeLog: PR target/67657 * config/sh/sh.c (sh_remove_overlapping_post_inc, sh_peephole_emit_move_insn): Add new functions. * config/sh/sh-protos.h (sh_remove_overlapping_post_inc, sh_peephole_emit_move_insn): Declere them. * config/sh/sh.md: Use them in various peephole2 patterns.
Index: gcc/config/sh/sh-protos.h =================================================================== --- gcc/config/sh/sh-protos.h (revision 227958) +++ gcc/config/sh/sh-protos.h (working copy) @@ -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); Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (revision 227958) +++ gcc/config/sh/sh.c (working copy) @@ -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 Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 227958) +++ gcc/config/sh/sh.md (working copy) @@ -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);