diff mbox

More conservative reg-stack push/pop sp modification fix (PR target/79430)

Message ID 20170427073706.GX1809@tucnak
State New
Headers show

Commit Message

Jakub Jelinek April 27, 2017, 7:37 a.m. UTC
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  <jakub@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.


	Jakub

Comments

Richard Biener April 27, 2017, 9:12 a.m. UTC | #1
On Thu, 27 Apr 2017, Jakub Jelinek wrote:

> 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?

Looks good to me.

Thanks,
Richard.

> 2017-04-27  Jakub Jelinek  <jakub@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
>
diff mbox

Patch

--- 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