c++: Reduce memory consumption for arrays of non-aggregate type.
authorJason Merrill <jason@redhat.com>
Fri, 31 Jan 2020 05:21:44 +0000 (00:21 -0500)
committerJason Merrill <jason@redhat.com>
Fri, 31 Jan 2020 23:19:31 +0000 (18:19 -0500)
The remaining low-hanging fruit for improvement on memory consumption in the
14179 testcase was the duplication of the CONSTRUCTOR for the array by
reshape_init.  This patch changes reshape_init to reuse a single constructor
for an array of non-aggregate type such as the one in the testcase.

PR c++/14179
* decl.c (reshape_init_array_1): Reuse a single CONSTRUCTOR with
non-aggregate elements.
(reshape_init_array): Add first_initializer_p parm.
(reshape_init_r): Change first_initializer_p from bool to tree.
(reshape_init): Pass init to it.

gcc/cp/ChangeLog
gcc/cp/decl.c

index f8140885dab408e680d8802cdddfc3fe84711aa0..cae1c918d304f4a9e34b32680df7b8641fc5ba4a 100644 (file)
@@ -1,5 +1,12 @@
 2020-01-31  Jason Merrill  <jason@redhat.com>
 
+       PR c++/14179
+       * decl.c (reshape_init_array_1): Reuse a single CONSTRUCTOR with
+       non-aggregate elements.
+       (reshape_init_array): Add first_initializer_p parm.
+       (reshape_init_r): Change first_initializer_p from bool to tree.
+       (reshape_init): Pass init to it.
+
        PR c++/14179
        * parser.c (cp_parser_initializer_list): Suppress location wrappers
        after 256 elements.
index 6ad558eef9e48a58910551cfa88d2ecfd538fc77..ef34f436fdff65bf1337714307677cc05fcd8c95 100644 (file)
@@ -5931,7 +5931,7 @@ struct reshape_iter
   constructor_elt *end;
 };
 
-static tree reshape_init_r (tree, reshape_iter *, bool, tsubst_flags_t);
+static tree reshape_init_r (tree, reshape_iter *, tree, tsubst_flags_t);
 
 /* FIELD is a FIELD_DECL or NULL.  In the former case, the value
    returned is the next FIELD_DECL (possibly FIELD itself) that can be
@@ -5979,15 +5979,21 @@ is_direct_enum_init (tree type, tree init)
 
 static tree
 reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
-                     tsubst_flags_t complain)
+                     tree first_initializer_p, tsubst_flags_t complain)
 {
   tree new_init;
   bool sized_array_p = (max_index && TREE_CONSTANT (max_index));
   unsigned HOST_WIDE_INT max_index_cst = 0;
   unsigned HOST_WIDE_INT index;
 
-  /* The initializer for an array is always a CONSTRUCTOR.  */
-  new_init = build_constructor (init_list_type_node, NULL);
+  /* The initializer for an array is always a CONSTRUCTOR.  If this is the
+     outermost CONSTRUCTOR and the element type is non-aggregate, we don't need
+     to build a new one.  */
+  bool reuse = first_initializer_p && !CP_AGGREGATE_TYPE_P (elt_type);
+  if (reuse)
+    new_init = first_initializer_p;
+  else
+    new_init = build_constructor (init_list_type_node, NULL);
 
   if (sized_array_p)
     {
@@ -6014,12 +6020,20 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
       constructor_elt *old_cur = d->cur;
 
       check_array_designated_initializer (d->cur, index);
-      elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false,
+      elt_init = reshape_init_r (elt_type, d,
+                                /*first_initializer_p=*/NULL_TREE,
                                 complain);
       if (elt_init == error_mark_node)
        return error_mark_node;
-      CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init),
-                             size_int (index), elt_init);
+      tree idx = size_int (index);
+      if (reuse)
+       {
+         old_cur->index = idx;
+         old_cur->value = elt_init;
+       }
+      else
+       CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init),
+                               idx, elt_init);
       if (!TREE_CONSTANT (elt_init))
        TREE_CONSTANT (new_init) = false;
 
@@ -6056,7 +6070,8 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
    Parameters are the same of reshape_init_r.  */
 
 static tree
-reshape_init_array (tree type, reshape_iter *d, tsubst_flags_t complain)
+reshape_init_array (tree type, reshape_iter *d, tree first_initializer_p,
+                   tsubst_flags_t complain)
 {
   tree max_index = NULL_TREE;
 
@@ -6065,7 +6080,8 @@ reshape_init_array (tree type, reshape_iter *d, tsubst_flags_t complain)
   if (TYPE_DOMAIN (type))
     max_index = array_type_nelts (type);
 
-  return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
+  return reshape_init_array_1 (TREE_TYPE (type), max_index, d,
+                              first_initializer_p, complain);
 }
 
 /* Subroutine of reshape_init_r, processes the initializers for vectors.
@@ -6096,7 +6112,8 @@ reshape_init_vector (tree type, reshape_iter *d, tsubst_flags_t complain)
   if (VECTOR_TYPE_P (type))
     max_index = size_int (TYPE_VECTOR_SUBPARTS (type) - 1);
 
-  return reshape_init_array_1 (TREE_TYPE (type), max_index, d, complain);
+  return reshape_init_array_1 (TREE_TYPE (type), max_index, d,
+                              NULL_TREE, complain);
 }
 
 /* Subroutine of reshape_init_r, processes the initializers for classes
@@ -6179,7 +6196,8 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
        break;
 
       field_init = reshape_init_r (TREE_TYPE (field), d,
-                                  /*first_initializer_p=*/false, complain);
+                                  /*first_initializer_p=*/NULL_TREE,
+                                  complain);
       if (field_init == error_mark_node)
        return error_mark_node;
 
@@ -6230,11 +6248,11 @@ has_designator_problem (reshape_iter *d, tsubst_flags_t complain)
 /* Subroutine of reshape_init, which processes a single initializer (part of
    a CONSTRUCTOR). TYPE is the type of the variable being initialized, D is the
    iterator within the CONSTRUCTOR which points to the initializer to process.
-   FIRST_INITIALIZER_P is true if this is the first initializer of the
-   outermost CONSTRUCTOR node.  */
+   If this is the first initializer of the outermost CONSTRUCTOR node,
+   FIRST_INITIALIZER_P is that CONSTRUCTOR; otherwise, it is NULL_TREE.  */
 
 static tree
-reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
+reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
                tsubst_flags_t complain)
 {
   tree init = d->cur->value;
@@ -6431,7 +6449,7 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
   if (CLASS_TYPE_P (type))
     return reshape_init_class (type, d, first_initializer_p, complain);
   else if (TREE_CODE (type) == ARRAY_TYPE)
-    return reshape_init_array (type, d, complain);
+    return reshape_init_array (type, d, first_initializer_p, complain);
   else if (VECTOR_TYPE_P (type))
     return reshape_init_vector (type, d, complain);
   else
@@ -6495,7 +6513,7 @@ reshape_init (tree type, tree init, tsubst_flags_t complain)
   d.cur = &(*v)[0];
   d.end = d.cur + v->length ();
 
-  new_init = reshape_init_r (type, &d, true, complain);
+  new_init = reshape_init_r (type, &d, init, complain);
   if (new_init == error_mark_node)
     return error_mark_node;