https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70001
--- Comment #7 from Jason Merrill <jason at gcc dot gnu.org> ---
(In reply to Patrick Palka from comment #6)
> struct X
> {
> int a;
>
> constexpr X () : a (0) { }
> };
>
> const int N = 1 << 19;
>
> struct A
> {
> X elems[N];
> } F;
>
>
> Just playing around, but naively sharing the constructor of each array
> element in the case of default- or value-initialization lowers compile time
> of the original test case down to a few seconds.
>
> diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> index d3b04b1..2ce44a5 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -2328,6 +2328,7 @@ 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
> @@ -2377,9 +2378,12 @@ 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. */
> - 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;
> }
> else
> {
That won't work in all cases (a constructor could depend on the value of
'this'), but perhaps we could use initializer_constant_valid_p to test for that
case and avoid re-using the initializer if it returns something other than
null_pointer_node.