Re: [PATCH] c++: Micro-optimize most_specialized_partial_spec

2023-04-26 Thread Patrick Palka via Gcc-patches
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

2022-09-01 Thread Jason Merrill via Gcc-patches

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

2022-08-31 Thread Patrick Palka via Gcc-patches
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));