After gcc commit c416c52bcdb120db5e8c53a51bd78c4360daf79b Author: Nathan Sidwell nathan@acm.org
c++ ICE with nested requirement as default tpl parm[PR94827]
the following benchmarks slowed down by more than 2%: - 456.hmmer slowed down by 4%
Benchmark: Toolchain: GCC + Glibc + GNU Linker Version: all components were built from their latest release branch Target: aarch64-linux-gnu Compiler flags: -O3 -flto Hardware: NVidia TX1 4x Cortex-A57
This commit has regressed these CI configurations: - tcwg_bmk_gnu_tx1/gnu-release-aarch64-spec2k6-O3_LTO
First_bad build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-aa... Last_good build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-aa... Baseline build: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-aa... Even more details: https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-aa...
Reproduce builds: <cut> mkdir investigate-gcc-c416c52bcdb120db5e8c53a51bd78c4360daf79b cd investigate-gcc-c416c52bcdb120db5e8c53a51bd78c4360daf79b
# Fetch scripts git clone https://git.linaro.org/toolchain/jenkins-scripts
# Fetch manifests and test.sh script mkdir -p artifacts/manifests curl -o artifacts/manifests/build-baseline.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-aa... --fail curl -o artifacts/manifests/build-parameters.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-aa... --fail curl -o artifacts/test.sh https://ci.linaro.org/job/tcwg_bmk_ci_gnu-bisect-tcwg_bmk_tx1-gnu-release-aa... --fail chmod +x artifacts/test.sh
# Reproduce the baseline build (build all pre-requisites) ./jenkins-scripts/tcwg_bmk-build.sh @@ artifacts/manifests/build-baseline.sh
# Save baseline build state (which is then restored in artifacts/test.sh) mkdir -p ./bisect rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ --exclude /gcc/ ./ ./bisect/baseline/
cd gcc
# Reproduce first_bad build git checkout --detach c416c52bcdb120db5e8c53a51bd78c4360daf79b ../artifacts/test.sh
# Reproduce last_good build git checkout --detach b1983f4582bbe060b7da83578acb9ed653681fc8 ../artifacts/test.sh
cd .. </cut>
Full commit (up to 1000 lines): <cut> commit c416c52bcdb120db5e8c53a51bd78c4360daf79b Author: Nathan Sidwell nathan@acm.org Date: Thu Apr 30 08:23:16 2020 -0700
c++ ICE with nested requirement as default tpl parm[PR94827]
Template headers are not incrementally updated as we parse its parameters. We maintain a dummy level until the closing > when we replace the dummy with a real parameter set. requires processing was expecting a properly populated arg_vec in current_template_parms, and then creates a self-mapping of parameters from that. But we don't need to do that, just teach map_arguments to look at TREE_VALUE when args is NULL.
* constraint.cc (map_arguments): If ARGS is null, it's a self-mapping of parms. (finish_nested_requirement): Do not pass argified current_template_parms to normalization. (tsubst_nested_requirement): Don't assert no template parms. --- gcc/cp/ChangeLog | 10 ++++++++++ gcc/cp/constraint.cc | 27 ++++++++++++++++----------- gcc/testsuite/g++.dg/concepts/pr94827.C | 15 +++++++++++++++ 3 files changed, 41 insertions(+), 11 deletions(-)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1fa0e123cb1..3c57945cecf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2020-04-30 Jason Merrill jason@redhat.com + Nathan Sidwell nathan@acm.org + + PR c++/94827 + * constraint.cc (map_arguments): If ARGS is null, it's a + self-mapping of parms. + (finish_nested_requirement): Do not pass argified + current_template_parms to normalization. + (tsubst_nested_requirement): Don't assert no template parms. + 2020-04-30 Iain Sandoe iain@sandoe.co.uk
PR c++/94886 diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 866b0f51b05..85513fecf43 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -546,12 +546,16 @@ static tree map_arguments (tree parms, tree args) { for (tree p = parms; p; p = TREE_CHAIN (p)) - { - int level; - int index; - template_parm_level_and_index (TREE_VALUE (p), &level, &index); - TREE_PURPOSE (p) = TMPL_ARG (args, level, index); - } + if (args) + { + int level; + int index; + template_parm_level_and_index (TREE_VALUE (p), &level, &index); + TREE_PURPOSE (p) = TMPL_ARG (args, level, index); + } + else + TREE_PURPOSE (p) = TREE_VALUE (p); + return parms; }
@@ -2005,8 +2009,6 @@ tsubst_compound_requirement (tree t, tree args, subst_info info) static tree tsubst_nested_requirement (tree t, tree args, subst_info info) { - gcc_assert (!uses_template_parms (args)); - /* Ensure that we're in an evaluation context prior to satisfaction. */ tree norm = TREE_VALUE (TREE_TYPE (t)); tree result = satisfy_constraint (norm, args, info); @@ -2953,12 +2955,15 @@ finish_compound_requirement (location_t loc, tree expr, tree type, bool noexcept tree finish_nested_requirement (location_t loc, tree expr) { + /* Currently open template headers have dummy arg vectors, so don't + pass into normalization. */ + tree norm = normalize_constraint_expression (expr, NULL_TREE, false); + tree args = current_template_parms + ? template_parms_to_args (current_template_parms) : NULL_TREE; + /* Save the normalized constraint and complete set of normalization arguments with the requirement. We keep the complete set of arguments around for re-normalization during diagnostics. */ - tree args = current_template_parms - ? template_parms_to_args (current_template_parms) : NULL_TREE; - tree norm = normalize_constraint_expression (expr, args, false); tree info = build_tree_list (args, norm);
/* Build the constraint, saving its normalization as its type. */ diff --git a/gcc/testsuite/g++.dg/concepts/pr94827.C b/gcc/testsuite/g++.dg/concepts/pr94827.C new file mode 100644 index 00000000000..f14ec2551a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr94827.C @@ -0,0 +1,15 @@ +// PR 94287 ICE looking inside open template-parm level +// { dg-do run { target c++17 } } +// { dg-options -fconcepts } + +template <typename T, + bool X = requires { requires (sizeof(T)==1); } > + int foo(T) { return X; } + +int main() { + if (!foo('4')) + return 1; + if (foo (4)) + return 2; + return 0; +} </cut>