Message ID | 20230919150444.356437-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: further optimize tsubst_template_decl | expand |
On 9/19/23 11:04, Patrick Palka wrote: > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK > for trunk? > > -- >8 -- > > This patch makes tsubst_template_decl use use_spec_table=false also in > the non-class non-function template case, to avoid computing 'argvec' and > doing a hash table lookup from tsubst_decl (when partially instantiating > a member variable or alias template). > > This change reveals that for function templates, tsubst_template_decl > registers the partially instantiated TEMPLATE_DECL, whereas for other > non-class templates it registers the corresponding DECL_TEMPLATE_RESULT > which is an interesting inconsistency that I decided to preserve for now. Can you document that in a comment somewhere, maybe at the bottom of tsubst_template_decl where you're handling them differently? OK with that change. > Trying to consistently register the TEMPLATE_DECL (or FUNCTION_DECL) > causes modules crashes, but I haven't looked into why. > > In passing, I noticed in tsubst_function_decl that its 'argvec' goes > unused when 'lambda_fntype' is set (since lambdas aren't recorded in the > specializations table), so we can avoid computing it in that case. > > gcc/cp/ChangeLog: > > * pt.cc (tsubst_function_decl): Don't bother computing 'argvec' > when 'lambda_fntype' is set. > (tsubst_template_decl): Make sure we return a TEMPLATE_DECL > after specialization lookup. In the non-class non-function > template case, use tsubst_decl directly with use_spec_table=false, > update DECL_TI_ARGS and call register_specialization like > tsubst_decl would have done if use_spec_table=true. > --- > gcc/cp/pt.cc | 39 +++++++++++++++++++++------------------ > 1 file changed, 21 insertions(+), 18 deletions(-) > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index 777ff592789..cc8ba21d6fd 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -14370,7 +14370,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, > > /* Calculate the complete set of arguments used to > specialize R. */ > - if (use_spec_table) > + if (use_spec_table && !lambda_fntype) > { > argvec = tsubst_template_args (DECL_TI_ARGS > (DECL_TEMPLATE_RESULT > @@ -14380,14 +14380,11 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, > return error_mark_node; > > /* Check to see if we already have this specialization. */ > - if (!lambda_fntype) > - { > - hash = spec_hasher::hash (gen_tmpl, argvec); > - if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash)) > - /* The spec for these args might be a partial instantiation of the > - template, but here what we want is the FUNCTION_DECL. */ > - return STRIP_TEMPLATE (spec); > - } > + hash = spec_hasher::hash (gen_tmpl, argvec); > + if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash)) > + /* The spec for these args might be a partial instantiation of the > + template, but here what we want is the FUNCTION_DECL. */ > + return STRIP_TEMPLATE (spec); > } > else > argvec = args; > @@ -14704,6 +14701,8 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, > /* Type partial instantiations are stored as the type by > lookup_template_class_1, not here as the template. */ > spec = CLASSTYPE_TI_TEMPLATE (spec); > + else if (TREE_CODE (spec) != TEMPLATE_DECL) > + spec = DECL_TI_TEMPLATE (spec); > return spec; > } > } > @@ -14754,7 +14753,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, > inner = tsubst_aggr_type (inner, args, complain, > in_decl, /*entering*/1); > else > - inner = tsubst (inner, args, complain, in_decl); > + inner = tsubst_decl (inner, args, complain, /*use_spec_table=*/false); > } > --processing_template_decl; > if (inner == error_mark_node) > @@ -14780,12 +14779,11 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, > } > else > { > - if (TREE_CODE (inner) == FUNCTION_DECL) > - /* Set DECL_TI_ARGS to the full set of template arguments, which > - tsubst_function_decl didn't do due to use_spec_table=false. */ > - DECL_TI_ARGS (inner) = full_args; > - > DECL_TI_TEMPLATE (inner) = r; > + /* Set DECL_TI_ARGS to the full set of template arguments, > + which tsubst_function_decl / tsubst_decl didn't do due to > + use_spec_table=false. */ > + DECL_TI_ARGS (inner) = full_args; > DECL_TI_ARGS (r) = DECL_TI_ARGS (inner); > } > > @@ -14813,9 +14811,14 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, > if (PRIMARY_TEMPLATE_P (t)) > DECL_PRIMARY_TEMPLATE (r) = r; > > - if (TREE_CODE (decl) == FUNCTION_DECL && !lambda_fntype) > - /* Record this non-type partial instantiation. */ > - register_specialization (r, t, full_args, false, hash); > + if (!lambda_fntype && !class_p) > + { > + /* Record this non-type partial instantiation. */ > + if (TREE_CODE (inner) == FUNCTION_DECL) > + register_specialization (r, t, full_args, false, hash); > + else > + register_specialization (inner, t, full_args, false, hash); > + } > > return r; > }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 777ff592789..cc8ba21d6fd 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -14370,7 +14370,7 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, /* Calculate the complete set of arguments used to specialize R. */ - if (use_spec_table) + if (use_spec_table && !lambda_fntype) { argvec = tsubst_template_args (DECL_TI_ARGS (DECL_TEMPLATE_RESULT @@ -14380,14 +14380,11 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain, return error_mark_node; /* Check to see if we already have this specialization. */ - if (!lambda_fntype) - { - hash = spec_hasher::hash (gen_tmpl, argvec); - if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash)) - /* The spec for these args might be a partial instantiation of the - template, but here what we want is the FUNCTION_DECL. */ - return STRIP_TEMPLATE (spec); - } + hash = spec_hasher::hash (gen_tmpl, argvec); + if (tree spec = retrieve_specialization (gen_tmpl, argvec, hash)) + /* The spec for these args might be a partial instantiation of the + template, but here what we want is the FUNCTION_DECL. */ + return STRIP_TEMPLATE (spec); } else argvec = args; @@ -14704,6 +14701,8 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, /* Type partial instantiations are stored as the type by lookup_template_class_1, not here as the template. */ spec = CLASSTYPE_TI_TEMPLATE (spec); + else if (TREE_CODE (spec) != TEMPLATE_DECL) + spec = DECL_TI_TEMPLATE (spec); return spec; } } @@ -14754,7 +14753,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, inner = tsubst_aggr_type (inner, args, complain, in_decl, /*entering*/1); else - inner = tsubst (inner, args, complain, in_decl); + inner = tsubst_decl (inner, args, complain, /*use_spec_table=*/false); } --processing_template_decl; if (inner == error_mark_node) @@ -14780,12 +14779,11 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, } else { - if (TREE_CODE (inner) == FUNCTION_DECL) - /* Set DECL_TI_ARGS to the full set of template arguments, which - tsubst_function_decl didn't do due to use_spec_table=false. */ - DECL_TI_ARGS (inner) = full_args; - DECL_TI_TEMPLATE (inner) = r; + /* Set DECL_TI_ARGS to the full set of template arguments, + which tsubst_function_decl / tsubst_decl didn't do due to + use_spec_table=false. */ + DECL_TI_ARGS (inner) = full_args; DECL_TI_ARGS (r) = DECL_TI_ARGS (inner); } @@ -14813,9 +14811,14 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain, if (PRIMARY_TEMPLATE_P (t)) DECL_PRIMARY_TEMPLATE (r) = r; - if (TREE_CODE (decl) == FUNCTION_DECL && !lambda_fntype) - /* Record this non-type partial instantiation. */ - register_specialization (r, t, full_args, false, hash); + if (!lambda_fntype && !class_p) + { + /* Record this non-type partial instantiation. */ + if (TREE_CODE (inner) == FUNCTION_DECL) + register_specialization (r, t, full_args, false, hash); + else + register_specialization (inner, t, full_args, false, hash); + } return r; }