On Mon, 2015-09-21 at 22:04 +0900, Oleg Endo wrote: > 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.
This is the patch for GCC 5. Basically same, just a small difference in the gen_rtx_SET invocation. Committed as r227970. Cheers, Oleg
Index: gcc/config/sh/sh-protos.h =================================================================== --- gcc/config/sh/sh-protos.h (revision 227969) +++ gcc/config/sh/sh-protos.h (working copy) @@ -305,6 +305,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 227969) +++ gcc/config/sh/sh.c (working copy) @@ -13787,6 +13787,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 227969) +++ gcc/config/sh/sh.md (working copy) @@ -14644,7 +14644,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 @@ -14657,7 +14657,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 @@ -14668,7 +14668,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 @@ -14680,7 +14680,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) @@ -14710,8 +14710,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 (VOIDmode, operands[2], operands[3])); - + rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, 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; @@ -14749,7 +14750,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 (VOIDmode, operands[2], operands[3])); + rtx_insn* i = emit_insn (gen_rtx_SET (VOIDmode, 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);