For a specific testcase a lot of compile-time is spent in re-hashing hashtable elements upon expansion. The following records the hash in the hash element. This speeds up compilation by 20%.
There's probably module-related uses that need to be adjusted. Bootstrap failed (guess I was expecting this), but still I think this is a good idea - maybe somebody can pick it up. Possibly instead of having a single global hash table having one per ID would be better. The hashtable also keeps things GC-live ('args' for example). gcc/cp/ * cp-tree.h (spec_entry::hash): New member. * pt.cc (spec_hasher::hash): Return the elements recorded hash. (lookup_template_class): Record the hash in the element. --- gcc/cp/cp-tree.h | 1 + gcc/cp/pt.cc | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c5d02567cb4..56345214d8f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5843,6 +5843,7 @@ struct GTY((for_user)) spec_entry tree tmpl; /* The general template this is a specialization of. */ tree args; /* The args for this (maybe-partial) specialization. */ tree spec; /* The specialization itself. */ + hashval_t hash; }; /* in class.cc */ diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 2c8b0d8609d..11f84133fa7 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -1739,7 +1739,7 @@ spec_hasher::hash (tree tmpl, tree args) hashval_t spec_hasher::hash (spec_entry *e) { - return spec_hasher::hash (e->tmpl, e->args); + return e->hash; } /* Recursively calculate a hash value for a template argument ARG, for use @@ -10234,7 +10234,7 @@ lookup_template_class (tree d1, tree arglist, tree in_decl, tree context, elt.tmpl = gen_tmpl; elt.args = arglist; elt.spec = NULL_TREE; - hash = spec_hasher::hash (&elt); + hash = elt.hash = spec_hasher::hash (gen_tmpl, arglist); entry = type_specializations->find_with_hash (&elt, hash); if (entry) @@ -10519,7 +10519,7 @@ lookup_template_class (tree d1, tree arglist, tree in_decl, tree context, use it for hash table lookup. */ elt.tmpl = found; elt.args = arglist = INNERMOST_TEMPLATE_ARGS (arglist); - hash = spec_hasher::hash (&elt); + hash = elt.hash = spec_hasher::hash (found, arglist); } } -- 2.43.0