Hi!

As mentioned in the PR, the compile time and compile memory are wasted
if a large array is is using value or default initialization, and
if the resulting initializer value is simple enough, we can just share
it by all the elements.

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

2016-03-10  Patrick Palka  <ppa...@gcc.gnu.org>
            Jakub Jelinek  <ja...@redhat.com>

        PR c++/70001
        * constexpr.c (cxx_eval_vec_init_1): For pre_init case, reuse
        return value from cxx_eval_constant_expression from earlier
        elements if it is valid constant initializer requiring no
        relocations.

        * g++.dg/cpp0x/constexpr-70001-1.C: New test.
        * g++.dg/cpp0x/constexpr-70001-2.C: New test.
        * g++.dg/cpp0x/constexpr-70001-3.C: New test.

--- gcc/cp/constexpr.c.jj       2016-03-08 21:04:43.050564671 +0100
+++ gcc/cp/constexpr.c  2016-03-10 12:52:04.016852313 +0100
@@ -2340,6 +2340,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx
   vec<constructor_elt, va_gc> **p = &CONSTRUCTOR_ELTS (ctx->ctor);
   vec_alloc (*p, max + 1);
   bool pre_init = false;
+  tree pre_init_elt = NULL_TREE;
   unsigned HOST_WIDE_INT i;
 
   /* For the default constructor, build up a call to the default
@@ -2389,9 +2390,18 @@ cxx_eval_vec_init_1 (const constexpr_ctx
        {
          /* Initializing an element using value or default initialization
             we just pre-built above.  */
-         eltinit = (cxx_eval_constant_expression
-                    (&new_ctx, init,
-                     lval, non_constant_p, overflow_p));
+         if (pre_init_elt == NULL_TREE)
+           pre_init_elt
+             = cxx_eval_constant_expression (&new_ctx, init, lval,
+                                             non_constant_p, overflow_p);
+         eltinit = pre_init_elt;
+         /* Don't reuse the result of cxx_eval_constant_expression
+            call if it isn't a constant initializer or if it requires
+            relocations.  */
+         if (initializer_constant_valid_p (pre_init_elt,
+                                           TREE_TYPE (pre_init_elt))
+             != null_pointer_node)
+           pre_init_elt = NULL_TREE;
        }
       else
        {
--- gcc/testsuite/g++.dg/cpp0x/constexpr-70001-1.C.jj   2016-03-10 
13:08:58.732932160 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-70001-1.C      2016-03-10 
13:05:53.000000000 +0100
@@ -0,0 +1,13 @@
+// PR c++/70001
+// { dg-do compile { target c++11 } }
+
+struct B
+{
+  int a;
+  constexpr B () : a (0) { }
+};
+
+struct A
+{
+  B b[1 << 19];
+} c;
--- gcc/testsuite/g++.dg/cpp0x/constexpr-70001-2.C.jj   2016-03-10 
13:09:01.866889167 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-70001-2.C      2016-03-10 
13:07:27.000000000 +0100
@@ -0,0 +1,19 @@
+// PR c++/70001
+// { dg-do run { target c++11 } }
+
+struct B
+{
+  struct B *a;
+  constexpr B () : a (this) { }
+};
+
+constexpr int N = 1 << 4;
+struct A { B c[N]; } d;
+
+int
+main ()
+{
+  for (int i = 0; i < N; ++i)
+    if (d.c[i].a != &d.c[i])
+      __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp0x/constexpr-70001-3.C.jj   2016-03-10 
13:09:04.700850290 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-70001-3.C      2016-03-10 
13:09:53.199184977 +0100
@@ -0,0 +1,26 @@
+// PR c++/70001
+// { dg-do compile { target c++11 } }
+
+#include <array>
+#include <complex>
+
+typedef std::complex<double> cd;
+
+const int LOG = 17;
+const int N = (1 << LOG);
+
+std::array<cd, N> a;
+std::array<cd, N> b;
+
+void
+foo (std::array<cd, N> &arr)
+{
+  std::array<std::array<cd, N>, LOG + 1> f;
+}
+
+int
+main ()
+{
+  foo (a);
+  foo (b);
+}

        Jakub

Reply via email to