diff options
author | Jason Merrill <jason@redhat.com> | 2019-06-04 10:47:40 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-06-04 10:47:40 -0400 |
commit | ecdcd56094cadc7bd3c18a0edd19f00d670e0d9b (patch) | |
tree | 6c44b508c28bc1e7f1f7141324f204af83dcb7f2 /gcc | |
parent | c790e3ece633d7e566f15b4df389ad8aefd9b78a (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 25 |
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) |