diff mbox

Fix up move_plus_up (PR rtl-optimization/69691)

Message ID 20160205181700.GZ3017@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 5, 2016, 6:17 p.m. UTC
Hi!

As mentioned in the PR, move_plus_up on
(subreg:SI (plus:DI (reg/f:DI 20 frame)
        (const_int 16 [0x10])) 0)
returns
(plus:SI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0)
        (const_int 16 [0x10]))
    (const_int 16 [0x10]))
which is wrong, the original added just 16, but the returned
rtx adds double that.
The problem is that subreg_reg is (verified in the conditions)
a PLUS, and we want to sum up the lowpart of the PLUS first operand
with CST, which is the lowpart of the second PLUS operand,
but we were actually returning lowpart of the whole PLUS plus
the lowpart of the PLUS second operand.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
ok for trunk?

2016-02-05  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/69691
	* lra-eliminations.c (move_plus_up): Don't add the addend twice.

	* gcc.c-torture/execute/pr69691.c: New test.


	Jakub

Comments

Jeff Law Feb. 5, 2016, 8:34 p.m. UTC | #1
On 02/05/2016 11:17 AM, Jakub Jelinek wrote:
> Hi!
>
> As mentioned in the PR, move_plus_up on
> (subreg:SI (plus:DI (reg/f:DI 20 frame)
>          (const_int 16 [0x10])) 0)
> returns
> (plus:SI (plus:SI (subreg:SI (reg/f:DI 20 frame) 0)
>          (const_int 16 [0x10]))
>      (const_int 16 [0x10]))
> which is wrong, the original added just 16, but the returned
> rtx adds double that.
> The problem is that subreg_reg is (verified in the conditions)
> a PLUS, and we want to sum up the lowpart of the PLUS first operand
> with CST, which is the lowpart of the second PLUS operand,
> but we were actually returning lowpart of the whole PLUS plus
> the lowpart of the PLUS second operand.
>
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
> ok for trunk?
>
> 2016-02-05  Jakub Jelinek  <jakub@redhat.com>
>
> 	PR rtl-optimization/69691
> 	* lra-eliminations.c (move_plus_up): Don't add the addend twice.
>
> 	* gcc.c-torture/execute/pr69691.c: New test.
OK.
jeff
diff mbox

Patch

--- gcc/lra-eliminations.c.jj	2016-01-14 20:57:03.000000000 +0100
+++ gcc/lra-eliminations.c	2016-02-05 16:54:42.142004224 +0100
@@ -303,7 +303,8 @@  move_plus_up (rtx x)
 				 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,
+	return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode,
+						     XEXP (subreg_reg, 0),
 						     subreg_reg_mode), cst);
     }
   return x;
--- gcc/testsuite/gcc.c-torture/execute/pr69691.c.jj	2016-02-05 17:08:31.582557031 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr69691.c	2016-02-05 17:08:24.000000000 +0100
@@ -0,0 +1,127 @@ 
+/* PR rtl-optimization/69691 */
+
+char u[] = { 46, 97, 99, 104, 52, 0 };
+char *v[] = { u, 0 };
+struct S { char a[10]; struct S *b[31]; };
+struct S r[7], *r2 = r;
+static struct S *w = 0;
+
+__attribute__((noinline, noclone)) int
+fn (int x)
+{
+  if (__builtin_strchr (u, x) || x == 96)
+    return x;
+  __builtin_abort ();
+}
+
+__attribute__((noinline, noclone)) int
+foo (char x)
+{
+  if (x == 0)
+    __builtin_abort ();
+  if (fn (x) >= 96 && fn (x) <= 122)
+    return (fn (x) - 96);
+  else if (x == 46)
+    return 0;
+  else
+    {
+      __builtin_printf ("foo %d\n", x);
+      return -1;
+    }
+}
+
+__attribute__((noinline, noclone)) void
+bar (char **x)
+{
+  char **b, c, *d, e[500], *f, g[10];
+  int z, l, h, i;
+  struct S *s;
+
+  w = r2++;
+  for (b = x; *b; b++)
+    {
+      __builtin_strcpy (e, *b);
+      f = e;
+      do
+	{
+	  d = __builtin_strchr (f, 32);
+	  if (d)
+	    *d = 0;
+	  l = __builtin_strlen (f);
+	  h = 0;
+	  s = w;
+	  __builtin_memset (g, 0, sizeof (g));
+	  for (z = 0; z < l; z++)
+	    {
+	      c = f[z];
+	      if (c >= 48 && c <= 57)
+		g[h] = c - 48;
+	      else
+		{
+		  i = foo (c);
+		  if (!s->b[i])
+		    {
+		      s->b[i] = r2++;
+		      if (r2 == &r[7])
+			__builtin_abort ();
+		    }
+		  s = s->b[i];
+		  h++;
+		}
+	    }
+	  __builtin_memcpy (s->a, g, 10);
+	  if (d)
+	    f = d + 1;
+	}
+      while (d);
+    }
+}
+
+__attribute__((noinline, noclone)) void
+baz (char *x)
+{
+  char a[300], b[300];
+  int z, y, t, l;
+  struct S *s;
+
+  l = __builtin_strlen (x);
+  *a = 96;
+  for (z = 0; z < l; z++)
+    {
+      a[z + 1] = fn ((unsigned int) x[z]);
+      if (foo (a[z + 1]) <= 0)
+	return;
+    }
+  a[l + 1] = 96;
+  l += 2;
+  __builtin_memset (b, 0, l + 2);
+
+  if (!w)
+    return;
+
+  for (z = 0; z < l; z++)
+    {
+      s = w;
+      for (y = z; y < l; y++)
+	{
+	  s = s->b[foo (a[y])];
+	  if (!s)
+	    break;
+	  for (t = 0; t <= y - z + 2; t++)
+	    if (s->a[t] > b[z + t])
+	      b[z + t] = s->a[t];
+	}
+    }
+  for (z = 3; z < l - 2; z++)
+    if ((b[z] & 1) == 1)
+     asm ("");
+}
+
+int
+main ()
+{
+  bar (v);
+  char c[] = { 97, 97, 97, 97, 97, 0 };
+  baz (c);
+  return 0;
+}