aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/constexpr.c
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-07-30 22:21:41 -0400
committerPatrick Palka <ppalka@redhat.com>2020-07-30 22:21:41 -0400
commit8c00059ce058ea2aec2933319e270f5443b8b909 (patch)
tree827a56233a6a312802401b1147f254516ea35b47 /gcc/cp/constexpr.c
parentd48cca8f21c64bba215f163314562a81e97074e2 (diff)
downloadgcc-8c00059ce058ea2aec2933319e270f5443b8b909.zip
gcc-8c00059ce058ea2aec2933319e270f5443b8b909.tar.gz
gcc-8c00059ce058ea2aec2933319e270f5443b8b909.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.c4
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);