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]

Fix for PR27620


This fixes PR27620, a code generation regression: all of a sudden we were generating a 4MB temporary on the stack, rather than doing a memset directly on an object.

The problem was introduced in revision 102182, when the internal representation of CONSTRUCTOR tree nodes was changed and they became tcc_exceptional rather than tcc_expression. With that, safe_from_p no longer knows how to handle them and always returns 0, which in turn means the caller in expand_expr_real thinks it must make a temporary on the stack.

Bootstrapped and regression tested on i686-linux. I've also checked in a variant of the testcase to verify that we do not generate calls to memcpy.

Mark, ok for 4.1?


Bernd
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 113849)
+++ ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2005-05-17  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+	PR middle-end/27620
+	* expr.c (safe_from_p): Handle CONSTRUCTOR again.
+
 2006-05-17  Jakub Jelinek  <jakub@redhat.com>
 
 	PR middle-end/27415
Index: expr.c
===================================================================
--- expr.c	(revision 113849)
+++ expr.c	(working copy)
@@ -6075,6 +6075,19 @@ safe_from_p (rtx x, tree exp, int top_p)
 		return safe_from_p (x, exp, 0);
 	    }
 	}
+      else if (TREE_CODE (exp) == CONSTRUCTOR)
+	{
+	  constructor_elt *ce;
+	  unsigned HOST_WIDE_INT idx;
+
+	  for (idx = 0;
+	       VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), idx, ce);
+	       idx++)
+	    if ((ce->index != NULL_TREE && !safe_from_p (x, ce->index, 0))
+		|| !safe_from_p (x, ce->value, 0))
+	      return 0;
+	  return 1;
+	}
       else if (TREE_CODE (exp) == ERROR_MARK)
 	return 1;	/* An already-visited SAVE_EXPR? */
       else
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 113849)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,7 @@
+2005-05-17  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+	* g++.dg/opt/temp2.C: New test.
+
 2006-05-17  Jakub Jelinek  <jakub@redhat.com>
 
 	PR c++/27491
Index: testsuite/g++.dg/opt/temp2.C
===================================================================
--- testsuite/g++.dg/opt/temp2.C	(revision 0)
+++ testsuite/g++.dg/opt/temp2.C	(revision 0)
@@ -0,0 +1,62 @@
+// { dg-do run }
+
+// Copyright (C) 2006 Free Software Foundation, Inc.
+
+// Originally from PR 16681, found also in init/array15.C
+// This variant of the testcase verifies that we do not create
+// a temporary on the stack, which is PR 27620.
+
+int i;
+
+extern "C"
+void *memcpy (void *dest, const void *src, __SIZE_TYPE__ n)
+{
+  char *d = (char *) dest;
+  const char *s = (const char *) src;
+  while (n--)
+    d[n] = s[n];
+  ++i;
+  return dest;
+}
+
+struct foo {
+  unsigned char buffer[41112];
+  foo() ;
+  bool check () const;
+};
+
+foo::foo ()
+  : buffer()
+{}
+
+bool foo::check () const
+{
+  for (unsigned ix = sizeof (buffer); ix--;)
+    if (buffer[ix])
+      return false;
+  return true;
+}
+
+void *operator new (__SIZE_TYPE__ size, void *p)
+{
+  return p;
+}
+
+char heap[50000];
+
+int main ()
+{
+  for (unsigned ix = sizeof (heap); ix--;)
+    heap[ix] = ix;
+
+  i = 0;
+  foo *f = new (heap) foo ();
+
+  if (i != 0)
+    return 1;
+  if (!f->check ())
+    return 1;
+  return 0;
+}
+
+  

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