From: Jason Merrill Date: Tue, 4 Jun 2019 14:47:40 +0000 (-0400) Subject: Reduce accumulated garbage in constexpr evaluation. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ecdcd56094cadc7bd3c18a0edd19f00d670e0d9b;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a3b18c76f5e..efa79f3ad35 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-06-04 Jason Merrill + + 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 * 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 67a8f04310c..84c98342835 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 (); *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)