This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Don't set REG_ATTRS or REG_POINTER{,_ALIGN} from value for hard registers (PR target/36533)


Hi!

For hard registers we shouldn't set REG_ATTRS, REG_POINTER
or REG_POINTER_ALIGN from value, as hard registers are often used
for multiple purposes within the same function.  One of the
set_reg_attrs_from_value callers knows reg is never a hard registers,
but the other two don't, so IMHO it is better to check this in
set_reg_attrs_from_value than to check it in the two callers.

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

2008-06-23  Jakub Jelinek  <jakub@redhat.com>

	PR target/36533
	* emit-rtl.c (set_reg_attrs_from_value): Do nothing if
	REG is a hard register.

	* gcc.target/i386/pr36533.c: New test.

--- gcc/emit-rtl.c.jj	2008-06-19 12:22:29.000000000 +0200
+++ gcc/emit-rtl.c	2008-06-23 10:29:07.000000000 +0200
@@ -963,6 +963,12 @@ set_reg_attrs_from_value (rtx reg, rtx x
 {
   int offset;
 
+  /* Hard registers can be reused for multiple purposes within the same
+     function, so setting REG_ATTRS, REG_POINTER and REG_POINTER_ALIGN
+     on them is wrong.  */
+  if (HARD_REGISTER_P (reg))
+    return;
+
   offset = byte_lowpart_offset (GET_MODE (reg), GET_MODE (x));
   if (MEM_P (x))
     {
--- gcc/testsuite/gcc.target/i386/pr36533.c.jj	2008-06-23 10:10:51.000000000 +0200
+++ gcc/testsuite/gcc.target/i386/pr36533.c	2008-06-23 10:09:48.000000000 +0200
@@ -0,0 +1,174 @@
+/* PR target/36533 */
+/* { dg-do run { target { { i?86-*-linux* x86_64-*-linux* } && ilp32 } } } */
+/* { dg-options "-Os" } */
+#include <string.h>
+#include <sys/mman.h>
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+typedef struct S1
+{
+  unsigned long s1;
+  struct S1 *s2;
+  char *s3;
+} S1;
+
+typedef struct
+{
+  unsigned int s4;
+  unsigned int s5;
+  int s6;
+  unsigned int *s7;
+} S2;
+
+typedef struct
+{
+  unsigned int s8;
+  unsigned short s9;
+  unsigned char s10;
+  unsigned char s11;
+  char s12[255];
+} S3;
+
+typedef struct
+{
+  unsigned int s4;
+  unsigned short s13;
+  unsigned short s14;
+} S4;
+
+typedef struct
+{
+  char s15[16];
+  unsigned long s16;
+} S5;
+
+typedef struct
+{
+  char s15[48];
+  S5 *s17;
+} S6;
+
+typedef struct
+{
+  S1 *s18;
+} S7;
+
+__attribute__((regparm (3), noinline)) int
+fn1 (const char *x, void *y, S1 *z)
+{
+  asm volatile ("" : : : "memory");
+  return *x + (y != 0);
+}
+
+__attribute__((regparm (3), noinline)) int
+fn2 (const char *x, int y, S2 *z)
+{
+  asm volatile ("" : : : "memory");
+  return 0;
+}
+
+static inline __attribute__ ((always_inline)) unsigned int
+fn4 (unsigned short x)
+{
+  unsigned len = x;
+  if (len == ((1 << 16) - 1))
+    return 1 << 16;
+  return len;
+}
+
+static inline __attribute__ ((always_inline)) S3 *
+fn3 (S3 *p)
+{
+  return (S3 *) ((char *) p + fn4 (p->s9));
+}
+
+__attribute__((regparm (3), noinline)) int
+fn5 (void)
+{
+  asm volatile ("" : : : "memory");
+  return 0;
+}
+
+static inline __attribute__ ((always_inline)) int
+fn6 (S3 *w, int x, S2 *y, S4 *z)
+{
+  int a = 2;
+  char *b = (char *) w;
+  S2 c = *y;
+
+  while ((char *) w < b + x - 2 * sizeof (S4))
+    {
+      if (w->s10 && w->s8)
+	{
+	  fn2 (w->s12, w->s10, &c);
+	  z--;
+	  z->s4 = c.s4;
+	  z->s13 = (unsigned short) ((char *) w - b);
+	  z->s14 = w->s9;
+	  a++;
+	  fn5 ();
+	}
+
+      w = fn3 (w);
+    }
+  return a;
+}
+
+__attribute__((regparm (3), noinline)) unsigned int
+test (void *u, S6 *v, S1 **w, S7 *x, S2 *y, S1 *z)
+{
+  unsigned b = v->s17->s16;
+  unsigned a;
+  S4 *c;
+  unsigned d, e, f, i;
+
+  fn1 (__func__, u, x->s18);
+  c = (S4 *) (z->s3 + b);
+  a = fn6 ((S3 *) (*w)->s3, b, y, c);
+  c -= a;
+  f = 0;
+  e = 2;
+  for (i = a - 1; ; i--)
+    {
+      if (f + (unsigned short) (c[i].s14 / 2) > b / 2)
+	break;
+      f += c[i].s14;
+      e++;
+    }
+  d = a - e;
+  return c[d].s4;
+}
+
+int main (void)
+{
+  char *p = mmap (NULL, 131072, PROT_READ | PROT_WRITE,
+		  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  S1 wb, z, *w;
+  S6 v;
+  S7 x;
+  S2 y;
+  S5 vb;
+  S4 s4;
+  if (p == MAP_FAILED)
+    return 0;
+  if (munmap (p + 65536, 65536) < 0)
+    return 0;
+  memset (&wb, 0, sizeof (wb));
+  memset (&z, 0, sizeof (z));
+  memset (&v, 0, sizeof (v));
+  memset (&x, 0, sizeof (x));
+  memset (&y, 0, sizeof (y));
+  memset (&vb, 0, sizeof (vb));
+  memset (&s4, 0, sizeof (s4));
+  s4.s14 = 254;
+  z.s3 = p + 65536 - 2 * sizeof (S4);
+  w = &wb;
+  v.s17 = &vb;
+  vb.s16 = 2 * sizeof (S4);
+  memcpy (z.s3, &s4, sizeof (s4));
+  memcpy (z.s3 + sizeof (s4), &s4, sizeof (s4));
+  test ((void *) 0, &v, &w, &x, &y, &z);
+  return 0;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]