aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-03-23 19:55:38 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2016-03-23 19:55:38 +0100
commit928af3bfe2bd34a803c3a371436463fd46b31e5d (patch)
treeab45560fcaf026a391bb8e5afaa07f430e349432
parent61637db3f2f55a1b97e6f466be012a131bede75d (diff)
downloadgcc-928af3bfe2bd34a803c3a371436463fd46b31e5d.zip
gcc-928af3bfe2bd34a803c3a371436463fd46b31e5d.tar.gz
gcc-928af3bfe2bd34a803c3a371436463fd46b31e5d.tar.bz2
re PR c++/70001 (Infinity compilation time)
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
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/constexpr.c39
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-70001-4.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr70001.C49
5 files changed, 96 insertions, 14 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b7a1f39..42c7054 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 4baf114..8427513 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8fbd1e8..1b32832 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..c1ab176
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-70001-4.C
@@ -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
index 0000000..adbb132
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr70001.C
@@ -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, "");