aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-06-04 10:47:40 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-06-04 10:47:40 -0400
commitecdcd56094cadc7bd3c18a0edd19f00d670e0d9b (patch)
tree6c44b508c28bc1e7f1f7141324f204af83dcb7f2 /gcc
parentc790e3ece633d7e566f15b4df389ad8aefd9b78a (diff)
downloadgcc-ecdcd56094cadc7bd3c18a0edd19f00d670e0d9b.zip
gcc-ecdcd56094cadc7bd3c18a0edd19f00d670e0d9b.tar.gz
gcc-ecdcd56094cadc7bd3c18a0edd19f00d670e0d9b.tar.bz2
Reduce accumulated garbage in constexpr evaluation.
We want to evaluate the arguments to a call before looking into the cache so that we have constant values, but if we then find the call in the cache we end up with a TREE_LIST that we don't end up using; in highly recursive constexpr evaluation this ends up being a large proportion of the garbage generated. The cxx_eval_increment_expression hunk is less important, but it's an easy tweak; we only use the MODIFY_EXPR to evaluate it, so after that it's garbage. * constexpr.c (cxx_eval_call_expression): ggc_free any bindings we don't save. (cxx_eval_increment_expression): ggc_free the MODIFY_EXPR after evaluating it. From-SVN: r271909
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/constexpr.c25
2 files changed, 33 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a3b18c7..efa79f3 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2019-06-04 Jason Merrill <jason@redhat.com>
+
+ Reduce accumulated garbage in constexpr evaluation.
+ * constexpr.c (cxx_eval_call_expression): ggc_free any bindings we
+ don't save.
+ (cxx_eval_increment_expression): ggc_free the MODIFY_EXPR after
+ evaluating it.
+
2019-06-04 Jakub Jelinek <jakub@redhat.com>
* cp-tree.h (CP_OMP_CLAUSE_INFO): Allow for any clauses up to _condvar_
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 67a8f04..84c9834 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1733,6 +1733,29 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
bool non_constant_args = false;
cxx_bind_parameters_in_call (ctx, t, &new_call,
non_constant_p, overflow_p, &non_constant_args);
+
+ /* We build up the bindings list before we know whether we already have this
+ call cached. If we don't end up saving these bindings, ggc_free them when
+ this function exits. */
+ struct free_bindings
+ {
+ tree &bindings;
+ bool do_free;
+ free_bindings (tree &b): bindings (b), do_free(true) { }
+ void preserve () { do_free = false; }
+ ~free_bindings () {
+ if (do_free)
+ {
+ while (bindings)
+ {
+ tree b = bindings;
+ bindings = TREE_CHAIN (bindings);
+ ggc_free (b);
+ }
+ }
+ }
+ } fb (new_call.bindings);
+
if (*non_constant_p)
return t;
@@ -1760,6 +1783,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
slot can move in the call to cxx_eval_builtin_function_call. */
*slot = entry = ggc_alloc<constexpr_call> ();
*entry = new_call;
+ fb.preserve ();
}
/* Calls that are in progress have their result set to NULL,
so that we can detect circular dependencies. */
@@ -4002,6 +4026,7 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
tree store = build2 (MODIFY_EXPR, type, op, mod);
cxx_eval_constant_expression (ctx, store,
true, non_constant_p, overflow_p);
+ ggc_free (store);
/* And the value of the expression. */
if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)