re PR c++/70001 (Infinity compilation time)
authorJakub Jelinek <jakub@redhat.com>
Wed, 23 Mar 2016 18:55:38 +0000 (19:55 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 23 Mar 2016 18:55:38 +0000 (19:55 +0100)
PR c++/70001
* constexpr.c (cxx_eval_vec_init_1): Reuse CONSTRUCTOR initializers
for 1..max even for multi-dimensional arrays.  Call unshare_expr
on it.

* g++.dg/cpp0x/constexpr-70001-4.C: New test.
* g++.dg/cpp1y/pr70001.C: New test.

From-SVN: r234439

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-70001-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr70001.C [new file with mode: 0644]

index b7a1f3984b1f264c65799cdbf2a175fc8b36ef75..42c7054637838edeea144012e17c69302900ab6d 100644 (file)
@@ -1,5 +1,10 @@
 2016-03-23  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/70001
+       * constexpr.c (cxx_eval_vec_init_1): Reuse CONSTRUCTOR initializers
+       for 1..max even for multi-dimensional arrays.  Call unshare_expr
+       on it.
+
        PR c++/70323
        * constexpr.c (cxx_eval_constant_expression): Diagnose overflow
        on TREE_OVERFLOW constants.
index 4baf11445df67da23f64cdd486d89cd1d888ff94..8427513854d408451b1e959e3cf793f8da110a5a 100644 (file)
@@ -2362,7 +2362,6 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
   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
@@ -2392,6 +2391,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
     {
       tree idx = build_int_cst (size_type_node, i);
       tree eltinit;
+      bool reuse = false;
       constexpr_ctx new_ctx;
       init_subob_ctx (ctx, new_ctx, idx, pre_init ? init : elttype);
       if (new_ctx.ctor != ctx->ctor)
@@ -2400,7 +2400,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
        {
          /* A multidimensional array; recurse.  */
          if (value_init || init == NULL_TREE)
-           eltinit = NULL_TREE;
+           {
+             eltinit = NULL_TREE;
+             reuse = i == 0;
+           }
          else
            eltinit = cp_build_array_ref (input_location, init, idx,
                                          tf_warning_or_error);
@@ -2412,18 +2415,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
        {
          /* Initializing an element using value or default initialization
             we just pre-built above.  */
-         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;
+         eltinit = cxx_eval_constant_expression (&new_ctx, init, lval,
+                                                 non_constant_p, overflow_p);
+         reuse = i == 0;
        }
       else
        {
@@ -2449,6 +2443,23 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
        }
       else
        CONSTRUCTOR_APPEND_ELT (*p, idx, eltinit);
+      /* Reuse the result of cxx_eval_constant_expression call
+         from the first iteration to all others if it is a constant
+         initializer that doesn't require relocations.  */
+      if (reuse
+         && max > 1
+         && (initializer_constant_valid_p (eltinit, TREE_TYPE (eltinit))
+             == null_pointer_node))
+       {
+         if (new_ctx.ctor != ctx->ctor)
+           eltinit = new_ctx.ctor;
+         for (i = 1; i < max; ++i)
+           {
+             idx = build_int_cst (size_type_node, i);
+             CONSTRUCTOR_APPEND_ELT (*p, idx, unshare_expr (eltinit));
+           }
+         break;
+       }
     }
 
   if (!*non_constant_p)
index 8fbd1e865114771ae28d898dd2f1c3c79952bdc8..1b3283286c37627efcf922560c2cbf59fa93c443 100644 (file)
@@ -1,5 +1,9 @@
 2016-03-23  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/70001
+       * g++.dg/cpp0x/constexpr-70001-4.C: New test.
+       * g++.dg/cpp1y/pr70001.C: New test.
+
        PR c++/70323
        * g++.dg/cpp0x/constexpr-70323.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-70001-4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-70001-4.C
new file mode 100644 (file)
index 0000000..c1ab176
--- /dev/null
@@ -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][1][1][1];
+} c;
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr70001.C b/gcc/testsuite/g++.dg/cpp1y/pr70001.C
new file mode 100644 (file)
index 0000000..adbb132
--- /dev/null
@@ -0,0 +1,49 @@
+// PR c++/70001
+// { dg-do compile { target c++14 } }
+
+struct B
+{
+  int a;
+  constexpr B () : a (0) { }
+  constexpr B (int x) : a (x) { }
+};
+struct C
+{
+  B c;
+  constexpr C () : c (0) { }
+};
+struct A
+{
+  B b[1 << 4];
+};
+struct D
+{
+  C d[1 << 4];
+};
+
+constexpr int
+foo (int a, int b)
+{
+  A c;
+  c.b[a].a += b;
+  c.b[b].a += a;
+  return c.b[0].a + c.b[a].a + c.b[b].a;
+}
+
+constexpr int
+bar (int a, int b)
+{
+  D c;
+  c.d[a].c.a += b;
+  c.d[b].c.a += a;
+  return c.d[0].c.a + c.d[a].c.a + c.d[b].c.a;
+}
+
+constexpr int d = foo (1, 2);
+constexpr int e = foo (0, 3);
+constexpr int f = foo (2, 4);
+constexpr int g = bar (1, 2);
+constexpr int h = bar (0, 3);
+constexpr int i = bar (2, 4);
+static_assert (d == 3 && e == 6 && f == 6, "");
+static_assert (g == 3 && h == 6 && i == 6, "");