Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On 7/17/23 17:29, Patrick Palka wrote: On Fri, 14 Jul 2023, Jason Merrill wrote: On 7/14/23 14:07, Patrick Palka wrote: On Thu, 13 Jul 2023, Jason Merrill wrote: On 7/13/23 11:48, Patrick Palka wrote: On Wed, 28 Jun 2023, Patrick Palka wrote: On Wed, Jun 28, 2023 at 11:50 AM Jason Merrill wrote: On 6/23/23 12:23, Patrick Palka wrote: On Fri, 23 Jun 2023, Jason Merrill wrote: On 6/21/23 13:19, Patrick Palka wrote: When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It should suffice to perform coercion once. To that end patch elides this second coercion from tsubst_decl when possible. We can't get rid of it completely because we don't always specialize a variable template from finish_template_variable: we could also be doing so directly from instantiate_template during variable template partial specialization selection, in which case the coercion from tsubst_decl would be the first and only coercion. Perhaps we should be coercing in lookup_template_variable rather than finish_template_variable? Ah yes, there's a patch for that at https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) So after that patch, can we get rid of the second coercion completely? On second thought it should be possible to get rid of it, if we rearrange things to always pass the primary arguments to tsubst_decl, and perform partial specialization selection from there instead of instantiate_template. Let me try... Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. -- >8 -- When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It'd be good to avoid this redundant coercion. It turns out that this coercion could be safely elided whenever specializing a primary variable/alias template, because we can rely on lookup_template_variable and instantiate_alias_template to already have coerced the arguments. The other situation to consider is when fully specializing a partial variable template specialization (from instantiate_template), in which case the passed 'args' are the (already coerced) arguments relative to the partial template and 'argvec', the result of substitution into DECL_TI_ARGS, are the (uncoerced) arguments relative to the primary template, so coercion is still necessary. We can still avoid this coercion however if we always pass the primary variable template to tsubst_decl from instantiate_template, and instead perform partial specialization selection directly from tsubst_decl. This patch implements this approach. The relationship between instantiate_template and tsubst_decl is pretty tangled. We use the former to substitute (often deduced) template arguments into a template, and the latter to substitute template arguments into a use of a template...and also to implement the former. For substitution of uses of a template, we expect to need to coerce the arguments after substitution. But we avoid this issue for variable templates by keeping them as TEMPLATE_ID_EXPR until substitution time, so if we see a VAR_DECL in tsubst_decl it's either a non-template variable or under instantiate_template. FWIW it seems we could also be in tsubst_decl for a VAR_DECL if * we're partially instantiating a class-scope variable template during instantiation of the class Hmm, why don't partial instantiations stay as TEMPLATE_ID_EXPR? Whoops, I accidentally omitted a crucial word. The situation is when partially instantiating a class-scope variable template _declaration_, e.g. for template struct A { template static int v; }; template struct A; we call tsubst_decl from instantiate_class_template with T=int for the VAR_DECL for v. * we're substituting a use of an already non-dependent variable template specialization Sure. So it seems like the current coercion for variable templates is only needed in this case to support the redundant hash table lookup that we just did in instantiate_template. Perhaps instead of doing coercion here or moving the partial spec lookup, we could skip the hash table lookup for the case of a variable template? It seems we'd then also have to make instantiate_template responsible for registering the variable template specialization since tsubst_decl no longer necessarily has the arguments relative to the primary template ('args' could be relative to the partial template). Like so? The following makes us perform all the specialization table manipulation in instantiate_template instead of tsubst_decl for variable template specializations. Looks good. I wonder if we might want to do this for alias templa
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On Fri, 14 Jul 2023, Jason Merrill wrote: > On 7/14/23 14:07, Patrick Palka wrote: > > On Thu, 13 Jul 2023, Jason Merrill wrote: > > > > > On 7/13/23 11:48, Patrick Palka wrote: > > > > On Wed, 28 Jun 2023, Patrick Palka wrote: > > > > > > > > > On Wed, Jun 28, 2023 at 11:50 AM Jason Merrill > > > > > wrote: > > > > > > > > > > > > On 6/23/23 12:23, Patrick Palka wrote: > > > > > > > On Fri, 23 Jun 2023, Jason Merrill wrote: > > > > > > > > > > > > > > > On 6/21/23 13:19, Patrick Palka wrote: > > > > > > > > > When stepping through the variable/alias template > > > > > > > > > specialization > > > > > > > > > code > > > > > > > > > paths, I noticed we perform template argument coercion twice: > > > > > > > > > first from > > > > > > > > > instantiate_alias_template / finish_template_variable and > > > > > > > > > again > > > > > > > > > from > > > > > > > > > tsubst_decl (during instantiate_template). It should suffice > > > > > > > > > to > > > > > > > > > perform > > > > > > > > > coercion once. > > > > > > > > > > > > > > > > > > To that end patch elides this second coercion from tsubst_decl > > > > > > > > > when > > > > > > > > > possible. We can't get rid of it completely because we don't > > > > > > > > > always > > > > > > > > > specialize a variable template from finish_template_variable: > > > > > > > > > we > > > > > > > > > could > > > > > > > > > also be doing so directly from instantiate_template during > > > > > > > > > variable > > > > > > > > > template partial specialization selection, in which case the > > > > > > > > > coercion > > > > > > > > > from tsubst_decl would be the first and only coercion. > > > > > > > > > > > > > > > > Perhaps we should be coercing in lookup_template_variable rather > > > > > > > > than > > > > > > > > finish_template_variable? > > > > > > > > > > > > > > Ah yes, there's a patch for that at > > > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) > > > > > > > > > > > > So after that patch, can we get rid of the second coercion > > > > > > completely? > > > > > > > > > > On second thought it should be possible to get rid of it, if we > > > > > rearrange things to always pass the primary arguments to tsubst_decl, > > > > > and perform partial specialization selection from there instead of > > > > > instantiate_template. Let me try... > > > > > > > > Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. > > > > > > > > -- >8 -- > > > > > > > > When stepping through the variable/alias template specialization code > > > > paths, I noticed we perform template argument coercion twice: first from > > > > instantiate_alias_template / finish_template_variable and again from > > > > tsubst_decl (during instantiate_template). It'd be good to avoid this > > > > redundant coercion. > > > > > > > > It turns out that this coercion could be safely elided whenever > > > > specializing a primary variable/alias template, because we can rely on > > > > lookup_template_variable and instantiate_alias_template to already have > > > > coerced the arguments. > > > > > > > > The other situation to consider is when fully specializing a partial > > > > variable template specialization (from instantiate_template), in which > > > > case the passed 'args' are the (already coerced) arguments relative to > > > > the partial template and 'argvec', the result of substitution into > > > > DECL_TI_ARGS, are the (uncoerced) arguments relative to the primary > > > > template, so coercion is still necessary. We can still avoid this > > > > coercion however if we always pass the primary variable template to > > > > tsubst_decl from instantiate_template, and instead perform partial > > > > specialization selection directly from tsubst_decl. This patch > > > > implements this approach. > > > > > > The relationship between instantiate_template and tsubst_decl is pretty > > > tangled. We use the former to substitute (often deduced) template > > > arguments > > > into a template, and the latter to substitute template arguments into a > > > use of > > > a template...and also to implement the former. > > > > > > For substitution of uses of a template, we expect to need to coerce the > > > arguments after substitution. But we avoid this issue for variable > > > templates > > > by keeping them as TEMPLATE_ID_EXPR until substitution time, so if we see > > > a > > > VAR_DECL in tsubst_decl it's either a non-template variable or under > > > instantiate_template. > > > > FWIW it seems we could also be in tsubst_decl for a VAR_DECL if > > > >* we're partially instantiating a class-scope variable template > > during instantiation of the class > > Hmm, why don't partial instantiations stay as TEMPLATE_ID_EXPR? Whoops, I accidentally omitted a crucial word. The situation is when partially instantiating a class-scope variable template _declaration_, e.g. for template struct A { template static int v; }; template struct A; we call ts
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On 7/14/23 14:07, Patrick Palka wrote: On Thu, 13 Jul 2023, Jason Merrill wrote: On 7/13/23 11:48, Patrick Palka wrote: On Wed, 28 Jun 2023, Patrick Palka wrote: On Wed, Jun 28, 2023 at 11:50 AM Jason Merrill wrote: On 6/23/23 12:23, Patrick Palka wrote: On Fri, 23 Jun 2023, Jason Merrill wrote: On 6/21/23 13:19, Patrick Palka wrote: When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It should suffice to perform coercion once. To that end patch elides this second coercion from tsubst_decl when possible. We can't get rid of it completely because we don't always specialize a variable template from finish_template_variable: we could also be doing so directly from instantiate_template during variable template partial specialization selection, in which case the coercion from tsubst_decl would be the first and only coercion. Perhaps we should be coercing in lookup_template_variable rather than finish_template_variable? Ah yes, there's a patch for that at https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) So after that patch, can we get rid of the second coercion completely? On second thought it should be possible to get rid of it, if we rearrange things to always pass the primary arguments to tsubst_decl, and perform partial specialization selection from there instead of instantiate_template. Let me try... Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. -- >8 -- When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It'd be good to avoid this redundant coercion. It turns out that this coercion could be safely elided whenever specializing a primary variable/alias template, because we can rely on lookup_template_variable and instantiate_alias_template to already have coerced the arguments. The other situation to consider is when fully specializing a partial variable template specialization (from instantiate_template), in which case the passed 'args' are the (already coerced) arguments relative to the partial template and 'argvec', the result of substitution into DECL_TI_ARGS, are the (uncoerced) arguments relative to the primary template, so coercion is still necessary. We can still avoid this coercion however if we always pass the primary variable template to tsubst_decl from instantiate_template, and instead perform partial specialization selection directly from tsubst_decl. This patch implements this approach. The relationship between instantiate_template and tsubst_decl is pretty tangled. We use the former to substitute (often deduced) template arguments into a template, and the latter to substitute template arguments into a use of a template...and also to implement the former. For substitution of uses of a template, we expect to need to coerce the arguments after substitution. But we avoid this issue for variable templates by keeping them as TEMPLATE_ID_EXPR until substitution time, so if we see a VAR_DECL in tsubst_decl it's either a non-template variable or under instantiate_template. FWIW it seems we could also be in tsubst_decl for a VAR_DECL if * we're partially instantiating a class-scope variable template during instantiation of the class Hmm, why don't partial instantiations stay as TEMPLATE_ID_EXPR? * we're substituting a use of an already non-dependent variable template specialization Sure. So it seems like the current coercion for variable templates is only needed in this case to support the redundant hash table lookup that we just did in instantiate_template. Perhaps instead of doing coercion here or moving the partial spec lookup, we could skip the hash table lookup for the case of a variable template? It seems we'd then also have to make instantiate_template responsible for registering the variable template specialization since tsubst_decl no longer necessarily has the arguments relative to the primary template ('args' could be relative to the partial template). Like so? The following makes us perform all the specialization table manipulation in instantiate_template instead of tsubst_decl for variable template specializations. Looks good. I wonder if we might want to do this for alias template specializations too? That would make sense. @@ -15222,20 +15230,21 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) { tmpl = DECL_TI_TEMPLATE (t); gen_tmpl = most_general_template (tmpl); - argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl); - if (argvec != error_mark_node - && PRIMARY_TEMPLAT
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On Thu, 13 Jul 2023, Jason Merrill wrote: > On 7/13/23 11:48, Patrick Palka wrote: > > On Wed, 28 Jun 2023, Patrick Palka wrote: > > > > > On Wed, Jun 28, 2023 at 11:50 AM Jason Merrill wrote: > > > > > > > > On 6/23/23 12:23, Patrick Palka wrote: > > > > > On Fri, 23 Jun 2023, Jason Merrill wrote: > > > > > > > > > > > On 6/21/23 13:19, Patrick Palka wrote: > > > > > > > When stepping through the variable/alias template specialization > > > > > > > code > > > > > > > paths, I noticed we perform template argument coercion twice: > > > > > > > first from > > > > > > > instantiate_alias_template / finish_template_variable and again > > > > > > > from > > > > > > > tsubst_decl (during instantiate_template). It should suffice to > > > > > > > perform > > > > > > > coercion once. > > > > > > > > > > > > > > To that end patch elides this second coercion from tsubst_decl > > > > > > > when > > > > > > > possible. We can't get rid of it completely because we don't > > > > > > > always > > > > > > > specialize a variable template from finish_template_variable: we > > > > > > > could > > > > > > > also be doing so directly from instantiate_template during > > > > > > > variable > > > > > > > template partial specialization selection, in which case the > > > > > > > coercion > > > > > > > from tsubst_decl would be the first and only coercion. > > > > > > > > > > > > Perhaps we should be coercing in lookup_template_variable rather > > > > > > than > > > > > > finish_template_variable? > > > > > > > > > > Ah yes, there's a patch for that at > > > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) > > > > > > > > So after that patch, can we get rid of the second coercion completely? > > > > > > On second thought it should be possible to get rid of it, if we > > > rearrange things to always pass the primary arguments to tsubst_decl, > > > and perform partial specialization selection from there instead of > > > instantiate_template. Let me try... > > > > Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. > > > > -- >8 -- > > > > When stepping through the variable/alias template specialization code > > paths, I noticed we perform template argument coercion twice: first from > > instantiate_alias_template / finish_template_variable and again from > > tsubst_decl (during instantiate_template). It'd be good to avoid this > > redundant coercion. > > > > It turns out that this coercion could be safely elided whenever > > specializing a primary variable/alias template, because we can rely on > > lookup_template_variable and instantiate_alias_template to already have > > coerced the arguments. > > > > The other situation to consider is when fully specializing a partial > > variable template specialization (from instantiate_template), in which > > case the passed 'args' are the (already coerced) arguments relative to > > the partial template and 'argvec', the result of substitution into > > DECL_TI_ARGS, are the (uncoerced) arguments relative to the primary > > template, so coercion is still necessary. We can still avoid this > > coercion however if we always pass the primary variable template to > > tsubst_decl from instantiate_template, and instead perform partial > > specialization selection directly from tsubst_decl. This patch > > implements this approach. > > The relationship between instantiate_template and tsubst_decl is pretty > tangled. We use the former to substitute (often deduced) template arguments > into a template, and the latter to substitute template arguments into a use of > a template...and also to implement the former. > > For substitution of uses of a template, we expect to need to coerce the > arguments after substitution. But we avoid this issue for variable templates > by keeping them as TEMPLATE_ID_EXPR until substitution time, so if we see a > VAR_DECL in tsubst_decl it's either a non-template variable or under > instantiate_template. FWIW it seems we could also be in tsubst_decl for a VAR_DECL if * we're partially instantiating a class-scope variable template during instantiation of the class * we're substituting a use of an already non-dependent variable template specialization > > So it seems like the current coercion for variable templates is only needed in > this case to support the redundant hash table lookup that we just did in > instantiate_template. Perhaps instead of doing coercion here or moving the > partial spec lookup, we could skip the hash table lookup for the case of a > variable template? It seems we'd then also have to make instantiate_template responsible for registering the variable template specialization since tsubst_decl no longer necessarily has the arguments relative to the primary template ('args' could be relative to the partial template). Like so? The following makes us perform all the specialization table manipulation in instantiate_template instead of tsubst_decl for variable template specializations.
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On 7/13/23 11:48, Patrick Palka wrote: On Wed, 28 Jun 2023, Patrick Palka wrote: On Wed, Jun 28, 2023 at 11:50 AM Jason Merrill wrote: On 6/23/23 12:23, Patrick Palka wrote: On Fri, 23 Jun 2023, Jason Merrill wrote: On 6/21/23 13:19, Patrick Palka wrote: When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It should suffice to perform coercion once. To that end patch elides this second coercion from tsubst_decl when possible. We can't get rid of it completely because we don't always specialize a variable template from finish_template_variable: we could also be doing so directly from instantiate_template during variable template partial specialization selection, in which case the coercion from tsubst_decl would be the first and only coercion. Perhaps we should be coercing in lookup_template_variable rather than finish_template_variable? Ah yes, there's a patch for that at https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) So after that patch, can we get rid of the second coercion completely? On second thought it should be possible to get rid of it, if we rearrange things to always pass the primary arguments to tsubst_decl, and perform partial specialization selection from there instead of instantiate_template. Let me try... Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. -- >8 -- When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It'd be good to avoid this redundant coercion. It turns out that this coercion could be safely elided whenever specializing a primary variable/alias template, because we can rely on lookup_template_variable and instantiate_alias_template to already have coerced the arguments. The other situation to consider is when fully specializing a partial variable template specialization (from instantiate_template), in which case the passed 'args' are the (already coerced) arguments relative to the partial template and 'argvec', the result of substitution into DECL_TI_ARGS, are the (uncoerced) arguments relative to the primary template, so coercion is still necessary. We can still avoid this coercion however if we always pass the primary variable template to tsubst_decl from instantiate_template, and instead perform partial specialization selection directly from tsubst_decl. This patch implements this approach. The relationship between instantiate_template and tsubst_decl is pretty tangled. We use the former to substitute (often deduced) template arguments into a template, and the latter to substitute template arguments into a use of a template...and also to implement the former. For substitution of uses of a template, we expect to need to coerce the arguments after substitution. But we avoid this issue for variable templates by keeping them as TEMPLATE_ID_EXPR until substitution time, so if we see a VAR_DECL in tsubst_decl it's either a non-template variable or under instantiate_template. So it seems like the current coercion for variable templates is only needed in this case to support the redundant hash table lookup that we just did in instantiate_template. Perhaps instead of doing coercion here or moving the partial spec lookup, we could skip the hash table lookup for the case of a variable template? gcc/cp/ChangeLog: * pt.cc (tsubst_decl) : Don't call coerce_template_parms. Call most_specialized_partial_spec when fully specializing a variable template here ... (instantiate_template): ... instead of here. Always pass the primary variable template pattern to tsubst_decl. --- gcc/cp/pt.cc | 62 +++- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fa15b75b9c5..53968b823d5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -15194,6 +15194,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) /* Check to see if we already have the specialization we need. */ tree spec = NULL_TREE; + tree partial_ti = NULL_TREE; bool local_p = false; tree ctx = DECL_CONTEXT (t); if (!(VAR_P (t) && DECL_LOCAL_DECL_P (t)) @@ -15230,17 +15231,29 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) tmpl = DECL_TI_TEMPLATE (t); gen_tmpl = most_general_template (tmpl); argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl); - if (argvec != error_mark_node - && PRIMARY_TEMPLATE_P (gen_tmpl) - && TMPL_ARGS_DEPTH (args) >= TMPL_AR
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On Wed, 28 Jun 2023, Patrick Palka wrote: > On Wed, Jun 28, 2023 at 11:50 AM Jason Merrill wrote: > > > > On 6/23/23 12:23, Patrick Palka wrote: > > > On Fri, 23 Jun 2023, Jason Merrill wrote: > > > > > >> On 6/21/23 13:19, Patrick Palka wrote: > > >>> When stepping through the variable/alias template specialization code > > >>> paths, I noticed we perform template argument coercion twice: first from > > >>> instantiate_alias_template / finish_template_variable and again from > > >>> tsubst_decl (during instantiate_template). It should suffice to perform > > >>> coercion once. > > >>> > > >>> To that end patch elides this second coercion from tsubst_decl when > > >>> possible. We can't get rid of it completely because we don't always > > >>> specialize a variable template from finish_template_variable: we could > > >>> also be doing so directly from instantiate_template during variable > > >>> template partial specialization selection, in which case the coercion > > >>> from tsubst_decl would be the first and only coercion. > > >> > > >> Perhaps we should be coercing in lookup_template_variable rather than > > >> finish_template_variable? > > > > > > Ah yes, there's a patch for that at > > > https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) > > > > So after that patch, can we get rid of the second coercion completely? > > On second thought it should be possible to get rid of it, if we > rearrange things to always pass the primary arguments to tsubst_decl, > and perform partial specialization selection from there instead of > instantiate_template. Let me try... Like so? Bootstrapped and regtested on x86_64-pc-linux-gnu. -- >8 -- When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It'd be good to avoid this redundant coercion. It turns out that this coercion could be safely elided whenever specializing a primary variable/alias template, because we can rely on lookup_template_variable and instantiate_alias_template to already have coerced the arguments. The other situation to consider is when fully specializing a partial variable template specialization (from instantiate_template), in which case the passed 'args' are the (already coerced) arguments relative to the partial template and 'argvec', the result of substitution into DECL_TI_ARGS, are the (uncoerced) arguments relative to the primary template, so coercion is still necessary. We can still avoid this coercion however if we always pass the primary variable template to tsubst_decl from instantiate_template, and instead perform partial specialization selection directly from tsubst_decl. This patch implements this approach. gcc/cp/ChangeLog: * pt.cc (tsubst_decl) : Don't call coerce_template_parms. Call most_specialized_partial_spec when fully specializing a variable template here ... (instantiate_template): ... instead of here. Always pass the primary variable template pattern to tsubst_decl. --- gcc/cp/pt.cc | 62 +++- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index fa15b75b9c5..53968b823d5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -15194,6 +15194,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) /* Check to see if we already have the specialization we need. */ tree spec = NULL_TREE; + tree partial_ti = NULL_TREE; bool local_p = false; tree ctx = DECL_CONTEXT (t); if (!(VAR_P (t) && DECL_LOCAL_DECL_P (t)) @@ -15230,17 +15231,29 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) tmpl = DECL_TI_TEMPLATE (t); gen_tmpl = most_general_template (tmpl); argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl); - if (argvec != error_mark_node - && PRIMARY_TEMPLATE_P (gen_tmpl) - && TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (argvec)) - /* We're fully specializing a template declaration, so -we need to coerce the innermost arguments corresponding to -the template. */ - argvec = (coerce_template_parms - (DECL_TEMPLATE_PARMS (gen_tmpl), -argvec, tmpl, complain)); if (argvec == error_mark_node) RETURN (error_mark_node); + if (variable_template_p (gen_tmpl) + && TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (argvec)) + { + /* We need to determine if we're using a partial + specialization now, because the type of the + variable could be different. */ +
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On Wed, Jun 28, 2023 at 11:50 AM Jason Merrill wrote: > > On 6/23/23 12:23, Patrick Palka wrote: > > On Fri, 23 Jun 2023, Jason Merrill wrote: > > > >> On 6/21/23 13:19, Patrick Palka wrote: > >>> When stepping through the variable/alias template specialization code > >>> paths, I noticed we perform template argument coercion twice: first from > >>> instantiate_alias_template / finish_template_variable and again from > >>> tsubst_decl (during instantiate_template). It should suffice to perform > >>> coercion once. > >>> > >>> To that end patch elides this second coercion from tsubst_decl when > >>> possible. We can't get rid of it completely because we don't always > >>> specialize a variable template from finish_template_variable: we could > >>> also be doing so directly from instantiate_template during variable > >>> template partial specialization selection, in which case the coercion > >>> from tsubst_decl would be the first and only coercion. > >> > >> Perhaps we should be coercing in lookup_template_variable rather than > >> finish_template_variable? > > > > Ah yes, there's a patch for that at > > https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) > > So after that patch, can we get rid of the second coercion completely? On second thought it should be possible to get rid of it, if we rearrange things to always pass the primary arguments to tsubst_decl, and perform partial specialization selection from there instead of instantiate_template. Let me try... > > Jason >
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On 6/23/23 12:23, Patrick Palka wrote: On Fri, 23 Jun 2023, Jason Merrill wrote: On 6/21/23 13:19, Patrick Palka wrote: When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It should suffice to perform coercion once. To that end patch elides this second coercion from tsubst_decl when possible. We can't get rid of it completely because we don't always specialize a variable template from finish_template_variable: we could also be doing so directly from instantiate_template during variable template partial specialization selection, in which case the coercion from tsubst_decl would be the first and only coercion. Perhaps we should be coercing in lookup_template_variable rather than finish_template_variable? Ah yes, there's a patch for that at https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) So after that patch, can we get rid of the second coercion completely? Jason
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On Fri, 23 Jun 2023, Jason Merrill wrote: > On 6/21/23 13:19, Patrick Palka wrote: > > When stepping through the variable/alias template specialization code > > paths, I noticed we perform template argument coercion twice: first from > > instantiate_alias_template / finish_template_variable and again from > > tsubst_decl (during instantiate_template). It should suffice to perform > > coercion once. > > > > To that end patch elides this second coercion from tsubst_decl when > > possible. We can't get rid of it completely because we don't always > > specialize a variable template from finish_template_variable: we could > > also be doing so directly from instantiate_template during variable > > template partial specialization selection, in which case the coercion > > from tsubst_decl would be the first and only coercion. > > Perhaps we should be coercing in lookup_template_variable rather than > finish_template_variable? Ah yes, there's a patch for that at https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617377.html :) > It looks like we currently get to > most_specialized_partial_spec with args that haven't yet been coerced to match > the primary template. The call to most_specialized_partial_spec from instantiate_template? I believe the arguments should already have been coerced by the caller, which is presumably always finish_template_variable. So in that patch I also made instantiate_template use build2 (TEMPLATE_ID_EXPR, ...) directly instead of calling lookup_template_variable, to avoid an unnecessary double coercion. > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > trunk? This reduces memory usage of range-v3's zip.cpp by ~0.5%. > > > > gcc/cp/ChangeLog: > > > > * pt.cc (tsubst_decl) : Call > > coercion_template_parms only if DECL_TEMPLATE_SPECIALIZATION > > is set. > > --- > > gcc/cp/pt.cc | 15 +++ > > 1 file changed, 11 insertions(+), 4 deletions(-) > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index be86051abad..dd10409ce18 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -15232,10 +15232,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t > > complain) > > argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl); > > if (argvec != error_mark_node > > && PRIMARY_TEMPLATE_P (gen_tmpl) > > - && TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (argvec)) > > - /* We're fully specializing a template declaration, so > > -we need to coerce the innermost arguments corresponding > > to > > -the template. */ > > + && TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (argvec) > > + && DECL_TEMPLATE_SPECIALIZATION (t)) > > + /* We're fully specializing an alias or variable template, > > so > > +coerce the innermost arguments if necessary. We expect > > +instantiate_alias_template and finish_template_variable > > to > > +already have done this relative to the primary template, > > in > > +which case this coercion is unnecessary, but we can also > > +get here when substituting a partial variable template > > +specialization (directly from instantiate_template), in > > +which case DECL_TEMPLATE_SPECIALIZATION is set and > > coercion > > +is necessary. */ > > argvec = (coerce_template_parms > > (DECL_TEMPLATE_PARMS (gen_tmpl), > > argvec, tmpl, complain)); > >
Re: [PATCH] c++: redundant targ coercion for var/alias tmpls
On 6/21/23 13:19, Patrick Palka wrote: When stepping through the variable/alias template specialization code paths, I noticed we perform template argument coercion twice: first from instantiate_alias_template / finish_template_variable and again from tsubst_decl (during instantiate_template). It should suffice to perform coercion once. To that end patch elides this second coercion from tsubst_decl when possible. We can't get rid of it completely because we don't always specialize a variable template from finish_template_variable: we could also be doing so directly from instantiate_template during variable template partial specialization selection, in which case the coercion from tsubst_decl would be the first and only coercion. Perhaps we should be coercing in lookup_template_variable rather than finish_template_variable? It looks like we currently get to most_specialized_partial_spec with args that haven't yet been coerced to match the primary template. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? This reduces memory usage of range-v3's zip.cpp by ~0.5%. gcc/cp/ChangeLog: * pt.cc (tsubst_decl) : Call coercion_template_parms only if DECL_TEMPLATE_SPECIALIZATION is set. --- gcc/cp/pt.cc | 15 +++ 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index be86051abad..dd10409ce18 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -15232,10 +15232,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl); if (argvec != error_mark_node && PRIMARY_TEMPLATE_P (gen_tmpl) - && TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (argvec)) - /* We're fully specializing a template declaration, so -we need to coerce the innermost arguments corresponding to -the template. */ + && TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (argvec) + && DECL_TEMPLATE_SPECIALIZATION (t)) + /* We're fully specializing an alias or variable template, so +coerce the innermost arguments if necessary. We expect +instantiate_alias_template and finish_template_variable to +already have done this relative to the primary template, in +which case this coercion is unnecessary, but we can also +get here when substituting a partial variable template +specialization (directly from instantiate_template), in +which case DECL_TEMPLATE_SPECIALIZATION is set and coercion +is necessary. */ argvec = (coerce_template_parms (DECL_TEMPLATE_PARMS (gen_tmpl), argvec, tmpl, complain));