[C++ PATCH] Reduce accumulated garbage in constexpr evaluation.
Jason Merrill
jason@redhat.com
Tue Jun 4 14:46:00 GMT 2019
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.
Tested x86_64-pc-linux-gnu, applying to trunk.
* 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.
---
gcc/cp/constexpr.c | 25 +++++++++++++++++++++++++
gcc/cp/ChangeLog | 8 ++++++++
2 files changed, 33 insertions(+)
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<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)
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 <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_
base-commit: 384aea128aac71e96ac413298adb49d7bae71c7d
--
2.20.1
More information about the Gcc-patches
mailing list