Hi! As the patch I've just posted is probably too dangerous for 7.1, here is a more localized version of the fix, which doesn't change reg_set_p/ modified_in_p/modified_between_p etc. behavior that is used in many spots, but just changes emit_swap_insn that has seen that problem (this code in emit_swap_insn is new in 7, so it is a P1 wrong-code regression).
What the patch does is instead of relying on modified_between_p to catch this it checks whether i1src is sp based and if it is, checks the insns while skipping over them whether they are push/pop (autoinc of sp) and if so, punts. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for 7.1? 2017-04-27 Jakub Jelinek <ja...@redhat.com> PR target/79430 * reg-stack.c (emit_swap_insn): If i1src mentions the stack pointer, punt if tmp contains autoinc of stack pointer. --- gcc/reg-stack.c.jj 2017-04-26 10:13:49.000000000 +0200 +++ gcc/reg-stack.c 2017-04-26 13:13:19.487471078 +0200 @@ -915,6 +915,7 @@ emit_swap_insn (rtx_insn *insn, stack_pt rtx i2set; rtx_insn *tmp = PREV_INSN (i1); rtx_insn *limit = PREV_INSN (BB_HEAD (current_block)); + bool sp_used = reg_overlap_mentioned_p (stack_pointer_rtx, i1src); /* Find the previous insn involving stack regs, but don't pass a block boundary. */ while (tmp != limit) @@ -928,6 +929,31 @@ emit_swap_insn (rtx_insn *insn, stack_pt i2 = tmp; break; } + /* FIXME: modified_between_p does not consider autoinc + modifications of stack pointer if i1src refers to + stack pointer, check it here manually. */ + if (sp_used && NONDEBUG_INSN_P (tmp)) + { + subrtx_var_iterator::array_type array; + FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (tmp), NONCONST) + { + rtx mem = *iter; + if (mem + && MEM_P (mem) + && (GET_RTX_CLASS (GET_CODE (XEXP (mem, 0))) + == RTX_AUTOINC)) + { + if (XEXP (XEXP (mem, 0), 0) == stack_pointer_rtx) + { + i2 = tmp; + break; + } + iter.skip_subrtxes (); + } + } + if (i2) + break; + } tmp = PREV_INSN (tmp); } if (i2 != NULL_RTX Jakub