diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-07-30 22:21:41 -0400 |
---|---|---|
committer | Giuliano Belinassi <giuliano.belinassi@usp.br> | 2020-08-17 13:20:20 -0300 |
commit | efedf7a100a1c3670bc3c1f0880479fd676c5290 (patch) | |
tree | ed44b6ed76018786b7ee3d4f019b36bb7453d38c /gcc/cp/constexpr.c | |
parent | d79c51c66ab0e379dd65aefb3ef72bee27ba1e86 (diff) | |
download | gcc-efedf7a100a1c3670bc3c1f0880479fd676c5290.zip gcc-efedf7a100a1c3670bc3c1f0880479fd676c5290.tar.gz gcc-efedf7a100a1c3670bc3c1f0880479fd676c5290.tar.bz2 |
c++: decl_constant_value and unsharing [PR96197]
In the testcase from the PR we're seeing excessive memory use (> 5GB)
during constexpr evaluation, almost all of which is due to the call to
decl_constant_value in the VAR_DECL/CONST_DECL branch of
cxx_eval_constant_expression. We reach here every time we evaluate an
ARRAY_REF of a constexpr VAR_DECL, and from there decl_constant_value
makes an unshared copy of the VAR_DECL's initializer. But unsharing
here is unnecessary because callers of cxx_eval_constant_expression
already unshare its result when necessary.
To fix this excessive unsharing, this patch adds a new defaulted
parameter unshare_p to decl_really_constant_value and
decl_constant_value so that callers can control whether to unshare.
As a simplification, we can also move the call to unshare_expr in
constant_value_1 outside of the loop, since doing unshare_expr on a
DECL_P is a no-op.
Now that we no longer unshare the result of decl_constant_value and
decl_really_constant_value from cxx_eval_constant_expression, memory use
during constexpr evaluation for the testcase from the PR falls from ~5GB
to 15MB according to -ftime-report.
gcc/cp/ChangeLog:
PR c++/96197
* constexpr.c (cxx_eval_constant_expression) <case CONST_DECL>:
Pass false to decl_constant_value and decl_really_constant_value
so that they don't unshare their result.
* cp-tree.h (decl_constant_value): New declaration with an added
bool parameter.
(decl_really_constant_value): Add bool parameter defaulting to
true to existing declaration.
* init.c (constant_value_1): Add bool parameter which controls
whether to unshare the initializer before returning. Call
unshare_expr at most once.
(scalar_constant_value): Pass true to constant_value_1's new
bool parameter.
(decl_really_constant_value): Add bool parameter and forward it
to constant_value_1.
(decl_constant_value): Likewise, but instead define a new
overload with an added bool parameter.
gcc/testsuite/ChangeLog:
PR c++/96197
* g++.dg/cpp1y/constexpr-array8.C: New test.
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r-- | gcc/cp/constexpr.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 97dcc1b..b1c1d24 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5695,9 +5695,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, TREE_CONSTANT (r) = true; } else if (ctx->strict) - r = decl_really_constant_value (t); + r = decl_really_constant_value (t, /*unshare_p=*/false); else - r = decl_constant_value (t); + r = decl_constant_value (t, /*unshare_p=*/false); if (TREE_CODE (r) == TARGET_EXPR && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR) r = TARGET_EXPR_INITIAL (r); |