[PATCH] Fix up move_plus_up (PR rtl-optimization/69691)

Jakub Jelinek jakub@redhat.com
Fri Feb 5 18:17:00 GMT 2016


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.

--- 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;
+}

	Jakub



More information about the Gcc-patches mailing list