aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-06-10 15:32:30 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-06-10 15:32:30 -0400
commit9b9eb42a4168c342e5cd71b13d21e63ba7e1b7ab (patch)
tree980566ca120b28a695e8c245a3a71a7d96303406
parent3c961dc7556fd00afac4a5275f1ea9444d43cd64 (diff)
downloadgcc-9b9eb42a4168c342e5cd71b13d21e63ba7e1b7ab.zip
gcc-9b9eb42a4168c342e5cd71b13d21e63ba7e1b7ab.tar.gz
gcc-9b9eb42a4168c342e5cd71b13d21e63ba7e1b7ab.tar.bz2
Reduce unsharing in constexpr call evaluation.
* constexpr.c (unshare_constructor): Only unshare if T is itself a CONSTRUCTOR. (cxx_eval_call_expression): Don't call it on the result here. From-SVN: r272126
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/constexpr.c39
2 files changed, 26 insertions, 17 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7a782dc..93d5f49 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2019-06-10 Jason Merrill <jason@redhat.com>
+ * constexpr.c (unshare_constructor): Only unshare if T is itself a
+ CONSTRUCTOR.
+ (cxx_eval_call_expression): Don't call it on the result here.
+
Reduce constexpr_call memory consumption.
* constexpr.c (cxx_bind_parameters_in_call): Use TREE_VEC rather
than TREE_LIST.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 74752bc..d7adb46 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1321,27 +1321,32 @@ adjust_temp_type (tree type, tree temp)
return cp_fold_convert (type, temp);
}
-/* Callback for walk_tree used by unshare_constructor. */
+/* If T is a CONSTRUCTOR, return an unshared copy of T and any
+ sub-CONSTRUCTORs. Otherwise return T.
-static tree
-find_constructor (tree *tp, int *walk_subtrees, void *)
-{
- if (TYPE_P (*tp))
- *walk_subtrees = 0;
- if (TREE_CODE (*tp) == CONSTRUCTOR)
- return *tp;
- return NULL_TREE;
-}
-
-/* If T is a CONSTRUCTOR or an expression that has a CONSTRUCTOR node as a
- subexpression, return an unshared copy of T. Otherwise return T. */
+ We use this whenever we initialize an object as a whole, whether it's a
+ parameter, a local variable, or a subobject, so that subsequent
+ modifications don't affect other places where it was used. */
tree
unshare_constructor (tree t)
{
- tree ctor = walk_tree (&t, find_constructor, NULL, NULL);
- if (ctor != NULL_TREE)
- return unshare_expr (t);
+ if (!t || TREE_CODE (t) != CONSTRUCTOR)
+ return t;
+ auto_vec <tree*, 4> ptrs;
+ ptrs.safe_push (&t);
+ while (!ptrs.is_empty ())
+ {
+ tree *p = ptrs.pop ();
+ tree n = copy_node (*p);
+ CONSTRUCTOR_ELTS (n) = vec_safe_copy (CONSTRUCTOR_ELTS (*p));
+ *p = n;
+ vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (n);
+ constructor_elt *ce;
+ for (HOST_WIDE_INT i = 0; vec_safe_iterate (v, i, &ce); ++i)
+ if (TREE_CODE (ce->value) == CONSTRUCTOR)
+ ptrs.safe_push (&ce->value);
+ }
return t;
}
@@ -1898,7 +1903,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
clear_no_implicit_zero (result);
pop_cx_call_context ();
- return unshare_constructor (result);
+ return result;
}
/* FIXME speed this up, it's taking 16% of compile time on sieve testcase. */