c++: set TYPE_CANONICAL for more template types
authorPatrick Palka <ppalka@redhat.com>
Tue, 24 May 2022 13:27:39 +0000 (09:27 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 24 May 2022 13:27:39 +0000 (09:27 -0400)
commitd0ef9e06197d14d7ba60404e37bd27c21791ba3d
tree6fb336ae02fc1c1ac897dea02c55f1a7e8332343
parent442cf0977a2993940a81aac08134fcdde4fb3035
c++: set TYPE_CANONICAL for more template types

When forming a class template specialization, lookup_template_class
uses structural equality for the specialized type whenever one of its
template arguments uses structural equality.  This is the sensible thing
to do in a vacuum, but given that we already effectively deduplicate class
specializations via the type_specializations table, we ought to be able
to safely assume that each class specialization is unique and therefore
canonical, regardless of the canonicity of the template arguments.

To that end this patch makes us use the canonical type machinery for all
type specializations, except for the case where a PARM_DECL appears in
the template arguments (this special case was recently added by
r12-3766-g72394d38d929c7).

Additionally, this patch makes us use the canonical type machinery for
TEMPLATE_TEMPLATE_PARMs and BOUND_TEMPLATE_TEMPLATE_PARMs, by extending
canonical_type_parameter appropriately.  A comment in tsubst says it's
unsafe to set TYPE_CANONICAL for a lowered TEMPLATE_TEMPLATE_PARM, but
I'm not sure this is true anymore.  According to Jason, this comment
(from r120341) became obsolete when later that year r129844 started to
substitute the template parms of ttps.  Note that r10-7817-ga6f400239d792d
recently changed process_template_parm to clear TYPE_CANONICAL for
TEMPLATE_TEMPLATE_PARM consistent with the tsubst comment; this patch
changes both functions to set instead of clear TYPE_CANONICAL for ttps.

These changes improve compile time of template-heavy code by around 10%
for me (with a release compiler).  For instance, compile time for the
libstdc++ test std/ranges/adaptors/all.cc drops from 1.45s to 1.25s, and
for the range-v3 test test/view/zip.cpp from 5.38s to 4.88s.  The total
number of calls to structural_comptypes for the latter test drops from
10.5M to 1.8M.  Memory use is unaffected (as expected).

The new testcase verifies we check the r12-3766 PARM_DECL special case
in bind_template_template_parm too.

gcc/cp/ChangeLog:

* cp-tree.h (any_template_arguments_need_structural_equality_p):
Declare.
* pt.cc (struct ctp_hasher): Define.
(ctp_table): Define.
(canonical_type_parameter): Use it.
(process_template_parm): Set TYPE_CANONICAL for
TEMPLATE_TEMPLATE_PARM too.
(lookup_template_class_1): Remove now outdated comment for the
any_template_arguments_need_structural_equality_p test.
(tsubst) <case TEMPLATE_TEMPLATE_PARM, etc>: Don't specifically
clear TYPE_CANONICAL for ttps.  Set TYPE_CANONICAL on the
substituted type later.
(any_template_arguments_need_structural_equality_p): Return
true for any_targ_node.  Don't return true just because a
template argument uses structural equality.  Add comment for
the PARM_DECL special case.
(rewrite_template_parm): Set TYPE_CANONICAL on the rewritten
parm's type later.
* tree.cc (bind_template_template_parm): Set TYPE_CANONICAL
when safe to do so.
* typeck.cc (structural_comptypes) [check_alias]: Increment
processing_template_decl before checking
dependent_alias_template_spec_p.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-52830a.C: New test.
gcc/cp/cp-tree.h
gcc/cp/pt.cc
gcc/cp/tree.cc
gcc/cp/typeck.cc
gcc/testsuite/g++.dg/cpp0x/constexpr-52830a.C [new file with mode: 0644]