c++: Micro-optimize most_specialized_partial_spec
Commit Message
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(-)
Comments
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 = TREE_CHAIN (t))
> {
> tree subst = build_tree_list (TREE_VALUE (t), TREE_PURPOSE (t));
> inform (DECL_SOURCE_LOCATION (TREE_VALUE (t)),
On Thu, Sep 1, 2022 at 2:40 PM Jason Merrill <jason@redhat.com> 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 && 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));
> > inform (DECL_SOURCE_LOCATION (TREE_VALUE (t)),
>
@@ -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));
inform (DECL_SOURCE_LOCATION (TREE_VALUE (t)),