c++: improve TYPENAME_TYPE hashing [PR65328]
commit343d83c7a89d0c7a78139e685395228115a28f6e
authorPatrick Palka <ppalka@redhat.com>
Fri, 10 Jun 2022 20:10:02 +0000 (10 16:10 -0400)
committerPatrick Palka <ppalka@redhat.com>
Fri, 10 Jun 2022 20:10:02 +0000 (10 16:10 -0400)
tree02edb30bfdeb86b266f5d303c363282fa5b894ee
parentf9b5a8e58dfd0642bea932d449ad46da9e57396f
c++: improve TYPENAME_TYPE hashing [PR65328]

For the testcase in this PR, compilation takes very long ultimately due
to our poor hashing of TYPENAME_TYPE causing a huge number of collisions
in the spec_hasher and typename_hasher tables.

In spec_hasher, we don't hash the components of TYPENAME_TYPE, which
means most TYPENAME_TYPE arguments end up contributing the same hash.
This is the safe thing to do uniformly since structural_comptypes may
try resolving a TYPENAME_TYPE via the current instantiation.  But this
behavior of structural_comptypes is suppressed from spec_hasher::equal
via the comparing_specializations flag, which means spec_hasher::hash
can assume it's disabled too.  To that end, this patch makes
spec_hasher::hash set the flag, and teaches iterative_hash_template_arg
to hash the relevant components of TYPENAME_TYPE when the flag is set.

And in typename_hasher, the hash function considers TYPE_IDENTIFIER
instead of the more informative TYPENAME_TYPE_FULLNAME, which this patch
fixes accordingly.

After this patch, compile time for the testcase in the PR falls to
around 30 seconds on my machine (down from dozens of minutes).

PR c++/65328

gcc/cp/ChangeLog:

* decl.cc (typename_hasher::hash): Add extra overloads.
Use iterative_hash_object instead of htab_hash_pointer.
Hash TYPENAME_TYPE_FULLNAME instead of TYPE_IDENTIFIER.
(build_typename_type): Use typename_hasher::hash.
* pt.cc (spec_hasher::hash): Add two-parameter overload.
Set comparing_specializations around the call to
hash_tmpl_and_args.
(iterative_hash_template_arg) <case TYPENAME_TYPE>:
When comparing_specializations, hash the TYPE_CONTEXT
and TYPENAME_TYPE_FULLNAME.
(tsubst_function_decl): Use spec_hasher::hash instead of
hash_tmpl_and_args.
(tsubst_template_decl): Likewise.
(tsubst_decl): Likewise.
gcc/cp/decl.cc
gcc/cp/pt.cc