aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2023-09-20 12:07:15 -0400
committerPatrick Palka <ppalka@redhat.com>2023-09-20 12:07:15 -0400
commit915574e538322aad5195bc3b6be2a4f85bbd2467 (patch)
tree23dff84f3051ac24ab4b3c1c5618895e6f74fe8d
parent1a554a2c9f33fdb3c170f1c37274037ece050114 (diff)
downloadgcc-915574e538322aad5195bc3b6be2a4f85bbd2467.zip
gcc-915574e538322aad5195bc3b6be2a4f85bbd2467.tar.gz
gcc-915574e538322aad5195bc3b6be2a4f85bbd2467.tar.bz2
c++: further optimize tsubst_template_decl
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/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. Trying to consistently register the TEMPLATE_DECL (or DECL_TEMPLATE_RESULT) causes modules ICEs which I didn't look into. In passing, in tsubst_function_decl I noticed 'argvec' is 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 during 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.
-rw-r--r--gcc/cp/pt.cc42
1 files changed, 24 insertions, 18 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 777ff59..8758e21 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,17 @@ 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. */
+ /* FIXME we'd like to always register the TEMPLATE_DECL, or always
+ the DECL_TEMPLATE_RESULT, but it seems the modules code relies
+ on this current behavior. */
+ 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;
}