diff mbox

Fix ICE due to invalid CONST_INT in DEBUG_INSN (PR target/69071)

Message ID 20160108201317.GE18720@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Jan. 8, 2016, 8:13 p.m. UTC
Hi!

The following testcase ICEs, because move_plus_up attempts to
optimize (subreg:HI (plus:SI (...) (const_int 0xff78)) 0)
into (plus:HI (subreg:HI (...) 0) (const_int 0xff78)) which is
incorrect, HImode CONST_INT with MSB set should be (const_int -136)
instead.  The patch also punts if the second operand of PLUS is
some CONSTANT_P that can't be simplified into a CONSTANT_P in the
narrower mode.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-01-08  Jakub Jelinek  <jakub@redhat.com>

	PR target/69071
	* lra-eliminations.c (move_plus_up): Only move plus up
	if subreg of the constant can be simplified into constant
	and use the simplified subreg of the constant instead of
	the original constant.

	* gcc.dg/pr69071.c: New test.


	Jakub

Comments

Vladimir Makarov Jan. 11, 2016, 6:58 p.m. UTC | #1
On 01/08/2016 03:13 PM, Jakub Jelinek wrote:
> Hi!
>
> The following testcase ICEs, because move_plus_up attempts to
> optimize (subreg:HI (plus:SI (...) (const_int 0xff78)) 0)
> into (plus:HI (subreg:HI (...) 0) (const_int 0xff78)) which is
> incorrect, HImode CONST_INT with MSB set should be (const_int -136)
> instead.  The patch also punts if the second operand of PLUS is
> some CONSTANT_P that can't be simplified into a CONSTANT_P in the
> narrower mode.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Sure.  Thanks, Jakub.

> 2016-01-08  Jakub Jelinek  <jakub@redhat.com>
>
> 	PR target/69071
> 	* lra-eliminations.c (move_plus_up): Only move plus up
> 	if subreg of the constant can be simplified into constant
> 	and use the simplified subreg of the constant instead of
> 	the original constant.
>
> 	* gcc.dg/pr69071.c: New test.
>
> --- gcc/lra-eliminations.c.jj	2016-01-04 14:55:50.000000000 +0100
> +++ gcc/lra-eliminations.c	2016-01-08 10:28:39.954706210 +0100
> @@ -296,9 +296,14 @@ move_plus_up (rtx x)
>     if (GET_CODE (x) == SUBREG && GET_CODE (subreg_reg) == PLUS
>         && GET_MODE_SIZE (x_mode) <= GET_MODE_SIZE (subreg_reg_mode)
>         && CONSTANT_P (XEXP (subreg_reg, 1)))
> -    return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode, subreg_reg,
> -						 subreg_reg_mode),
> -			 XEXP (subreg_reg, 1));
> +    {
> +      rtx cst = simplify_subreg (x_mode, XEXP (subreg_reg, 1), subreg_reg_mode,
> +				 subreg_lowpart_offset (x_mode,
> +							subreg_reg_mode));
> +      if (cst && CONSTANT_P (cst))
> +	return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode, subreg_reg,
> +						     subreg_reg_mode), cst);
> +    }
>     return x;
>   }
>   
> --- gcc/testsuite/gcc.dg/pr69071.c.jj	2016-01-08 10:24:50.029922989 +0100
> +++ gcc/testsuite/gcc.dg/pr69071.c	2016-01-08 10:24:34.000000000 +0100
> @@ -0,0 +1,22 @@
> +/* PR target/69071 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -g" } */
> +
> +void *bar (void *);
> +
> +void
> +foo (int c)
> +{
> +  unsigned char bf[65400];
> +  unsigned char *p2 = bar (bf);
> +  unsigned char *p3 = bar (bf);
> +  for (; *p2; p2++, c++)
> +    {
> +      if (c)
> +	{
> +	  short of = p2 - bf - 6;
> +	  unsigned ofu = of;
> +	  __builtin_memcpy (p3, &ofu, sizeof (ofu));
> +	}
> +    }
> +}
>
> 	Jakub
diff mbox

Patch

--- gcc/lra-eliminations.c.jj	2016-01-04 14:55:50.000000000 +0100
+++ gcc/lra-eliminations.c	2016-01-08 10:28:39.954706210 +0100
@@ -296,9 +296,14 @@  move_plus_up (rtx x)
   if (GET_CODE (x) == SUBREG && GET_CODE (subreg_reg) == PLUS
       && GET_MODE_SIZE (x_mode) <= GET_MODE_SIZE (subreg_reg_mode)
       && CONSTANT_P (XEXP (subreg_reg, 1)))
-    return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode, subreg_reg,
-						 subreg_reg_mode),
-			 XEXP (subreg_reg, 1));
+    {
+      rtx cst = simplify_subreg (x_mode, XEXP (subreg_reg, 1), subreg_reg_mode,
+				 subreg_lowpart_offset (x_mode,
+							subreg_reg_mode));
+      if (cst && CONSTANT_P (cst))
+	return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode, subreg_reg,
+						     subreg_reg_mode), cst);
+    }
   return x;
 }
 
--- gcc/testsuite/gcc.dg/pr69071.c.jj	2016-01-08 10:24:50.029922989 +0100
+++ gcc/testsuite/gcc.dg/pr69071.c	2016-01-08 10:24:34.000000000 +0100
@@ -0,0 +1,22 @@ 
+/* PR target/69071 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+
+void *bar (void *);
+
+void
+foo (int c)
+{
+  unsigned char bf[65400];
+  unsigned char *p2 = bar (bf);
+  unsigned char *p3 = bar (bf);
+  for (; *p2; p2++, c++)
+    {
+      if (c)
+	{
+	  short of = p2 - bf - 6;
+	  unsigned ofu = of;
+	  __builtin_memcpy (p3, &ofu, sizeof (ofu));
+	}
+    }
+}