From a20fd5ac2eb9316dd87135ceb445702dc4d78aa2 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Sun, 28 Apr 2002 21:47:12 +0200
Subject: [PATCH] re PR rtl-optimization/6475 (zlib miscompilation with
 gcc-3.1)

	PR optimization/6475
	* reload1.c (alter_reg): Only call set_mem_expr if I is home pseudo
	register of REGNO_DECL (i).
	* Makefile.in (reload1.o): Add $(TREE_H).

	* gcc.dg/20020426-2.c: New test.

From-SVN: r52855
---
 gcc/ChangeLog                     |   7 ++
 gcc/Makefile.in                   |   2 +-
 gcc/reload1.c                     |  16 ++-
 gcc/testsuite/ChangeLog           |   4 +
 gcc/testsuite/gcc.dg/20020426-2.c | 173 ++++++++++++++++++++++++++++++
 5 files changed, 198 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/20020426-2.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 728e9ff7510a..a4ae41fc7e81 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2002-04-28  Jakub Jelinek  <jakub@redhat.com>
+
+	PR optimization/6475
+	* reload1.c (alter_reg): Only call set_mem_expr if I is home pseudo
+	register of REGNO_DECL (i).
+	* Makefile.in (reload1.o): Add $(TREE_H).
+
 2002-04-28  Neil Booth  <neil@daikokuya.demon.co.uk>
 
 	* cppexp.c (lex): Update to use state.skip_eval.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9d88ac674386..319e14fa1fba 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1537,7 +1537,7 @@ reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h output.h \
 reload1.o : reload1.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) real.h flags.h \
    $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) hard-reg-set.h insn-config.h \
    $(BASIC_BLOCK_H) $(RECOG_H) output.h function.h toplev.h cselib.h $(TM_P_H) \
-   except.h
+   except.h $(TREE_H)
 caller-save.o : caller-save.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h \
    $(REGS_H) hard-reg-set.h insn-config.h $(BASIC_BLOCK_H) function.h \
    $(RECOG_H) reload.h $(EXPR_H) toplev.h $(TM_P_H)
diff --git a/gcc/reload1.c b/gcc/reload1.c
index cf807af01e1b..840b1cbd4976 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "real.h"
 #include "toplev.h"
 #include "except.h"
+#include "tree.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -2067,10 +2068,19 @@ alter_reg (i, from_reg)
 	 memory.  If this is a shared MEM, make a copy.  */
       if (REGNO_DECL (i))
 	{
-	  if (from_reg != -1 && spill_stack_slot[from_reg] == x)
-	    x = copy_rtx (x);
+	  rtx decl = DECL_RTL_IF_SET (REGNO_DECL (i));
 
-	  set_mem_expr (x, REGNO_DECL (i));
+	  /* We can do this only for the DECLs home pseudo, not for
+	     any copies of it, since otherwise when the stack slot
+	     is reused, nonoverlapping_memrefs_p might think they
+	     cannot overlap.  */
+	  if (decl && GET_CODE (decl) == REG && REGNO (decl) == (unsigned) i)
+	    {
+	      if (from_reg != -1 && spill_stack_slot[from_reg] == x)
+		x = copy_rtx (x);
+
+	      set_mem_expr (x, REGNO_DECL (i));
+	    }
 	}
 
       /* Save the stack slot for later.  */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1ae710f08c3b..173ab5ce21bb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2002-04-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* gcc.dg/20020426-2.c: New test.
+
 2002-04-28  Neil Booth  <neil@daikokuya.demon.co.uk>
 
 	* gcc.dg/cpp/if-mop.c: Update.
diff --git a/gcc/testsuite/gcc.dg/20020426-2.c b/gcc/testsuite/gcc.dg/20020426-2.c
new file mode 100644
index 000000000000..8ac170986e11
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20020426-2.c
@@ -0,0 +1,173 @@
+/* PR optimization/6475
+   Distilled from zlib sources.  */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-options "-O2 -frename-registers -fomit-frame-pointer -fPIC -mcpu=i686" { target i?86-*-* } } */
+
+typedef struct
+{
+  union
+  {
+    struct
+    {
+      unsigned char a3;
+      unsigned char a4;
+    } a2;
+    unsigned int a5;
+  } a0;
+  unsigned int a1;
+} A;
+
+static int
+foo (unsigned int *b, unsigned int n, unsigned int s, const unsigned int *d,
+     const unsigned int *e, A **t, unsigned int *m, A *hp, unsigned int *hn,
+     unsigned int *v)
+{
+  unsigned int a, c[15 + 1], f;
+  int g, h;
+  unsigned int i, j, k;
+  int l;
+  unsigned int ee;
+  unsigned int *p;
+  A *q, r, *u[15];
+  int w;
+  unsigned int x[15 + 1], *xx;
+  int y;
+  unsigned int z;
+  p = c;
+  *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
+  *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
+  *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
+  *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;
+  p = b;
+  i = n;
+  do
+    c[*p++]++;
+  while (--i);
+  if (c[0] == n)
+    {
+      *t = (A *) 0;
+      *m = 0;
+      return 0;
+    }
+  l = *m;
+  for (j = 1; j <= 15; j++)
+    if (c[j])
+      break;
+  k = j;
+  if ((unsigned int) l < j)
+    l = j;
+  for (i = 15; i; i--)
+    if (c[i])
+      break;
+  g = i;
+  if ((unsigned int) l > i)
+    l = i;
+  *m = l;
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return -3;
+  if ((y -= c[i]) < 0)
+    return -3;
+  c[i] += y;
+  x[1] = j = 0;
+  p = c + 1;
+  xx = x + 2;
+  while (--i)
+    *xx++ = (j += *p++);
+  p = b;
+  i = 0;
+  do
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  while (++i < n);
+  n = x[g];
+  x[0] = i = 0;
+  p = v;
+  h = -1;
+  w = -l;
+  u[0] = (A *) 0;
+  q = (A *) 0;
+  z = 0;
+  for (; k <= g; k++)
+    {
+      a = c[k];
+      while (a--)
+	{
+	  while (k > w + l)
+	    {
+	      h++;
+	      w += l;
+	      z = g - w;
+	      z = z > (unsigned int) l ? l : z;
+	      if ((f = 1 << (j = k - w)) > a + 1)
+		{
+		  f -= a + 1;
+		  xx = c + k;
+		  if (j < z)
+		    while (++j < z)
+		      {
+			if ((f <<= 1) <= *++xx)
+			  break;
+			f -= *xx;
+		      }
+		}
+	      z = 1 << j;
+	      if (*hn + z > 1440)
+		return -3;
+	      u[h] = q = hp + *hn;
+	      *hn += z;
+	      if (h)
+		{
+		  x[h] = i;
+		  r.a0.a2.a4 = (unsigned char) l;
+		  r.a0.a2.a3 = (unsigned char) j;
+		  j = i >> (w - l);
+		  r.a1 = (unsigned int) (q - u[h - 1] - j);
+		  u[h - 1][j] = r;
+		}
+	      else
+		*t = q;
+	    }
+	  r.a0.a2.a4 = (unsigned char) (k - w);
+	  if (p >= v + n)
+	    r.a0.a2.a3 = 128 + 64;
+	  else if (*p < s)
+	    {
+	      r.a0.a2.a3 = (unsigned char) (*p < 256 ? 0 : 32 + 64);
+	      r.a1 = *p++;
+	    }
+	  else
+	    {
+	      r.a0.a2.a3 = (unsigned char) (e[*p - s] + 16 + 64);
+	      r.a1 = d[*p++ - s];
+	    }
+	  f = 1 << (k - w);
+	  for (j = i >> w; j < z; j += f)
+	    q[j] = r;
+	  for (j = 1 << (k - 1); i & j; j >>= 1)
+	    i ^= j;
+	  i ^= j;
+	  ee = (1 << w) - 1;
+	  while ((i & ee) != x[h])
+	    {
+	      h--;
+	      w -= l;
+	      ee = (1 << w) - 1;
+	    }
+	}
+    }
+  return y != 0 && g != 1 ? (-5) : 0;
+}
+
+int a[19] = { 3, 4, 0, 2, 2, [17] = 3, 3 };
+int d[19];
+A h[1440];
+
+int
+main (void)
+{
+  int b = 0, c = 0;
+  A *e = 0;
+  foo (a, 19, 19, 0, 0, &e, &b, h, &c, d);
+  exit (0);
-- 
GitLab