Re: [PATCH] c++: Micro-optimize most_specialized_partial_spec
On Thu, Sep 1, 2022 at 2:40 PM Jason Merrill wrote: > > On 8/31/22 17:15, Patrick Palka wrote: > > This introduces an early exit test to most_specialized_partial_spec for > > the common case where we have no partial specializations, which allows > > us to avoid some unnecessary work. In passing, clean the function up a > > bit. > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > trunk? > > OK. Thanks. This patch fell through the cracks for GCC 13, but I pushed it to trunk just now. > > > gcc/cp/ChangeLog: > > > > * pt.cc (most_specialized_partial_spec): Exit early when > > DECL_TEMPLATE_SPECIALIZATIONS is empty. Move local variable > > declarations closer to their first use. Remove redundant > > flag_concepts test. Remove redundant forward declaration. > > --- > > gcc/cp/pt.cc | 45 +++-- > > 1 file changed, 19 insertions(+), 26 deletions(-) > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index fe7e809fc2d..497a18ef728 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -187,7 +187,6 @@ static int unify_pack_expansion (tree, tree, tree, > > static tree copy_template_args (tree); > > static tree tsubst_template_parms (tree, tree, tsubst_flags_t); > > static void tsubst_each_template_parm_constraints (tree, tree, > > tsubst_flags_t); > > -tree most_specialized_partial_spec (tree, tsubst_flags_t); > > static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); > > static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree); > > static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); > > @@ -25756,15 +25755,7 @@ most_general_template (tree decl) > > tree > > most_specialized_partial_spec (tree target, tsubst_flags_t complain) > > { > > - tree list = NULL_TREE; > > - tree t; > > - tree champ; > > - int fate; > > - bool ambiguous_p; > > - tree outer_args = NULL_TREE; > > - tree tmpl, args; > > - > > - tree decl; > > + tree tmpl, args, decl; > > if (TYPE_P (target)) > > { > > tree tinfo = CLASSTYPE_TEMPLATE_INFO (target); > > @@ -25788,13 +25779,18 @@ most_specialized_partial_spec (tree target, > > tsubst_flags_t complain) > > else > > gcc_unreachable (); > > > > + tree main_tmpl = most_general_template (tmpl); > > + tree specs = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); > > + if (!specs) > > +/* There are no partial specializations of this template. */ > > +return NULL_TREE; > > + > > push_access_scope_guard pas (decl); > > deferring_access_check_sentinel acs (dk_no_deferred); > > > > - tree main_tmpl = most_general_template (tmpl); > > - > > /* For determining which partial specialization to use, only the > >innermost args are interesting. */ > > + tree outer_args = NULL_TREE; > > if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) > > { > > outer_args = strip_innermost_template_args (args, 1); > > @@ -25806,7 +25802,8 @@ most_specialized_partial_spec (tree target, > > tsubst_flags_t complain) > >fully resolve everything. */ > > processing_template_decl_sentinel ptds; > > > > - for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN > > (t)) > > + tree list = NULL_TREE; > > + for (tree t = specs; t; t = TREE_CHAIN (t)) > > { > > const tree ospec_tmpl = TREE_VALUE (t); > > > > @@ -25829,10 +25826,8 @@ most_specialized_partial_spec (tree target, > > tsubst_flags_t complain) > > if (outer_args) > > spec_args = add_to_template_args (outer_args, spec_args); > > > > - /* Keep the candidate only if the constraints are satisfied, > > - or if we're not compiling with concepts. */ > > - if (!flag_concepts > > - || constraints_satisfied_p (ospec_tmpl, spec_args)) > > + /* Keep the candidate only if the constraints are satisfied. */ > > + if (constraints_satisfied_p (ospec_tmpl, spec_args)) > > { > > list = tree_cons (spec_args, ospec_tmpl, list); > > TREE_TYPE (list) = TREE_TYPE (t); > > @@ -25843,13 +25838,11 @@ most_specialized_partial_spec (tree target, > > tsubst_flags_t complain) > > if (! list) > > return NULL_TREE; > > > > - ambiguous_p = false; > > - t = list; > > - champ = t; > > - t = TREE_CHAIN (t); > > - for (; t; t = TREE_CHAIN (t)) > > + tree champ = list; > > + bool ambiguous_p = false; > > + for (tree t = TREE_CHAIN (list); t; t = TREE_CHAIN (t)) > > { > > - fate = more_specialized_partial_spec (tmpl, champ, t); > > + int fate = more_specialized_partial_spec (tmpl, champ, t); > > if (fate == 1) > > ; > > else > > @@ -25868,9 +25861,9 @@ most_specialized_partial_spec (tree target, > > tsubst_flags_t complain) > > } > > > > if (!ambiguous_p) > > -for (t = list; t && t != champ; t = TREE_CHAIN (t)) > > +for (tree t = list; t
Re: [PATCH] c++: Micro-optimize most_specialized_partial_spec
On 8/31/22 17:15, Patrick Palka wrote: This introduces an early exit test to most_specialized_partial_spec for the common case where we have no partial specializations, which allows us to avoid some unnecessary work. In passing, clean the function up a bit. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? OK. gcc/cp/ChangeLog: * pt.cc (most_specialized_partial_spec): Exit early when DECL_TEMPLATE_SPECIALIZATIONS is empty. Move local variable declarations closer to their first use. Remove redundant flag_concepts test. Remove redundant forward declaration. --- gcc/cp/pt.cc | 45 +++-- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fe7e809fc2d..497a18ef728 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -187,7 +187,6 @@ static int unify_pack_expansion (tree, tree, tree, static tree copy_template_args (tree); static tree tsubst_template_parms (tree, tree, tsubst_flags_t); static void tsubst_each_template_parm_constraints (tree, tree, tsubst_flags_t); -tree most_specialized_partial_spec (tree, tsubst_flags_t); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); @@ -25756,15 +25755,7 @@ most_general_template (tree decl) tree most_specialized_partial_spec (tree target, tsubst_flags_t complain) { - tree list = NULL_TREE; - tree t; - tree champ; - int fate; - bool ambiguous_p; - tree outer_args = NULL_TREE; - tree tmpl, args; - - tree decl; + tree tmpl, args, decl; if (TYPE_P (target)) { tree tinfo = CLASSTYPE_TEMPLATE_INFO (target); @@ -25788,13 +25779,18 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) else gcc_unreachable (); + tree main_tmpl = most_general_template (tmpl); + tree specs = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); + if (!specs) +/* There are no partial specializations of this template. */ +return NULL_TREE; + push_access_scope_guard pas (decl); deferring_access_check_sentinel acs (dk_no_deferred); - tree main_tmpl = most_general_template (tmpl); - /* For determining which partial specialization to use, only the innermost args are interesting. */ + tree outer_args = NULL_TREE; if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) { outer_args = strip_innermost_template_args (args, 1); @@ -25806,7 +25802,8 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) fully resolve everything. */ processing_template_decl_sentinel ptds; - for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t)) + tree list = NULL_TREE; + for (tree t = specs; t; t = TREE_CHAIN (t)) { const tree ospec_tmpl = TREE_VALUE (t); @@ -25829,10 +25826,8 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) if (outer_args) spec_args = add_to_template_args (outer_args, spec_args); - /* Keep the candidate only if the constraints are satisfied, - or if we're not compiling with concepts. */ - if (!flag_concepts - || constraints_satisfied_p (ospec_tmpl, spec_args)) + /* Keep the candidate only if the constraints are satisfied. */ + if (constraints_satisfied_p (ospec_tmpl, spec_args)) { list = tree_cons (spec_args, ospec_tmpl, list); TREE_TYPE (list) = TREE_TYPE (t); @@ -25843,13 +25838,11 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) if (! list) return NULL_TREE; - ambiguous_p = false; - t = list; - champ = t; - t = TREE_CHAIN (t); - for (; t; t = TREE_CHAIN (t)) + tree champ = list; + bool ambiguous_p = false; + for (tree t = TREE_CHAIN (list); t; t = TREE_CHAIN (t)) { - fate = more_specialized_partial_spec (tmpl, champ, t); + int fate = more_specialized_partial_spec (tmpl, champ, t); if (fate == 1) ; else @@ -25868,9 +25861,9 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) } if (!ambiguous_p) -for (t = list; t && t != champ; t = TREE_CHAIN (t)) +for (tree t = list; t && t != champ; t = TREE_CHAIN (t)) { - fate = more_specialized_partial_spec (tmpl, champ, t); + int fate = more_specialized_partial_spec (tmpl, champ, t); if (fate != 1) { ambiguous_p = true; @@ -25889,7 +25882,7 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) else error ("ambiguous template instantiation for %q#D", target); str = ngettext ("candidate is:", "candidates are:", list_length (list)); - for (t = list; t; t = TREE_CHAIN (t)) + for (tree t = list; t; t =
[PATCH] c++: Micro-optimize most_specialized_partial_spec
This introduces an early exit test to most_specialized_partial_spec for the common case where we have no partial specializations, which allows us to avoid some unnecessary work. In passing, clean the function up a bit. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? gcc/cp/ChangeLog: * pt.cc (most_specialized_partial_spec): Exit early when DECL_TEMPLATE_SPECIALIZATIONS is empty. Move local variable declarations closer to their first use. Remove redundant flag_concepts test. Remove redundant forward declaration. --- gcc/cp/pt.cc | 45 +++-- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fe7e809fc2d..497a18ef728 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -187,7 +187,6 @@ static int unify_pack_expansion (tree, tree, tree, static tree copy_template_args (tree); static tree tsubst_template_parms (tree, tree, tsubst_flags_t); static void tsubst_each_template_parm_constraints (tree, tree, tsubst_flags_t); -tree most_specialized_partial_spec (tree, tsubst_flags_t); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); @@ -25756,15 +25755,7 @@ most_general_template (tree decl) tree most_specialized_partial_spec (tree target, tsubst_flags_t complain) { - tree list = NULL_TREE; - tree t; - tree champ; - int fate; - bool ambiguous_p; - tree outer_args = NULL_TREE; - tree tmpl, args; - - tree decl; + tree tmpl, args, decl; if (TYPE_P (target)) { tree tinfo = CLASSTYPE_TEMPLATE_INFO (target); @@ -25788,13 +25779,18 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) else gcc_unreachable (); + tree main_tmpl = most_general_template (tmpl); + tree specs = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); + if (!specs) +/* There are no partial specializations of this template. */ +return NULL_TREE; + push_access_scope_guard pas (decl); deferring_access_check_sentinel acs (dk_no_deferred); - tree main_tmpl = most_general_template (tmpl); - /* For determining which partial specialization to use, only the innermost args are interesting. */ + tree outer_args = NULL_TREE; if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) { outer_args = strip_innermost_template_args (args, 1); @@ -25806,7 +25802,8 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) fully resolve everything. */ processing_template_decl_sentinel ptds; - for (t = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl); t; t = TREE_CHAIN (t)) + tree list = NULL_TREE; + for (tree t = specs; t; t = TREE_CHAIN (t)) { const tree ospec_tmpl = TREE_VALUE (t); @@ -25829,10 +25826,8 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) if (outer_args) spec_args = add_to_template_args (outer_args, spec_args); - /* Keep the candidate only if the constraints are satisfied, - or if we're not compiling with concepts. */ - if (!flag_concepts - || constraints_satisfied_p (ospec_tmpl, spec_args)) + /* Keep the candidate only if the constraints are satisfied. */ + if (constraints_satisfied_p (ospec_tmpl, spec_args)) { list = tree_cons (spec_args, ospec_tmpl, list); TREE_TYPE (list) = TREE_TYPE (t); @@ -25843,13 +25838,11 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) if (! list) return NULL_TREE; - ambiguous_p = false; - t = list; - champ = t; - t = TREE_CHAIN (t); - for (; t; t = TREE_CHAIN (t)) + tree champ = list; + bool ambiguous_p = false; + for (tree t = TREE_CHAIN (list); t; t = TREE_CHAIN (t)) { - fate = more_specialized_partial_spec (tmpl, champ, t); + int fate = more_specialized_partial_spec (tmpl, champ, t); if (fate == 1) ; else @@ -25868,9 +25861,9 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) } if (!ambiguous_p) -for (t = list; t && t != champ; t = TREE_CHAIN (t)) +for (tree t = list; t && t != champ; t = TREE_CHAIN (t)) { - fate = more_specialized_partial_spec (tmpl, champ, t); + int fate = more_specialized_partial_spec (tmpl, champ, t); if (fate != 1) { ambiguous_p = true; @@ -25889,7 +25882,7 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain) else error ("ambiguous template instantiation for %q#D", target); str = ngettext ("candidate is:", "candidates are:", list_length (list)); - for (t = list; t; t = TREE_CHAIN (t)) + for (tree t = list; t; t = TREE_CHAIN (t)) { tree subst = build_tree_list (TREE_VALUE (t), TREE_PURPOSE (t));