c++: Micro-optimize most_specialized_partial_spec

Message ID 20220831211521.401160-1-ppalka@redhat.com
State New, archived
Headers
Series c++: Micro-optimize most_specialized_partial_spec |

Commit Message

Patrick Palka Aug. 31, 2022, 9:15 p.m. UTC
  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

Jason Merrill Sept. 1, 2022, 6:40 p.m. UTC | #1
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)),
  
Patrick Palka April 26, 2023, 7:45 p.m. UTC | #2
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)),
>
  

Patch

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)),