c++: Reuse identical ATOMIC_CONSTRs during normalization
Profiling revealed that sat_hasher::equal accounts for nearly 40% of compile time in some cmcstl2 tests. This patch eliminates this bottleneck by caching the ATOMIC_CONSTRs returned by normalize_atom. This in turn allows us to replace the expensive atomic_constraints_identical_p check in sat_hasher::equal with cheap pointer equality, with no loss in cache hit rate. With this patch, compile time for the cmcstl2 test test/algorithm/set_symmetric_difference4.cpp drops from 19s to 11s with an --enable-checking=release compiler. gcc/cp/ChangeLog: * constraint.cc (atom_cache): Define this deletable hash_table. (normalize_atom): Use it to cache ATOMIC_CONSTRs when not generating diagnostics. (sat_hasher::hash): Use htab_hash_pointer instead of hash_atomic_constraint. (sat_hasher::equal): Test for pointer equality instead of atomic_constraints_identical_p. * cp-tree.h (struct atom_hasher): Moved and renamed from ... * logic.cc (struct constraint_hash): ... here. (clause::m_set): Adjust accordingly.
This commit is contained in:
parent
71a8040716
commit
2096ebd393
3 changed files with 40 additions and 19 deletions
|
@ -710,6 +710,10 @@ normalize_concept_check (tree check, tree args, norm_info info)
|
|||
return normalize_expression (def, subst, info);
|
||||
}
|
||||
|
||||
/* Used by normalize_atom to cache ATOMIC_CONSTRs. */
|
||||
|
||||
static GTY((deletable)) hash_table<atom_hasher> *atom_cache;
|
||||
|
||||
/* The normal form of an atom depends on the expression. The normal
|
||||
form of a function call to a function concept is a check constraint
|
||||
for that concept. The normal form of a reference to a variable
|
||||
|
@ -729,7 +733,19 @@ normalize_atom (tree t, tree args, norm_info info)
|
|||
/* Build a new info object for the atom. */
|
||||
tree ci = build_tree_list (t, info.context);
|
||||
|
||||
return build1 (ATOMIC_CONSTR, ci, map);
|
||||
tree atom = build1 (ATOMIC_CONSTR, ci, map);
|
||||
if (!info.generate_diagnostics ())
|
||||
{
|
||||
/* Cache the ATOMIC_CONSTRs that we return, so that sat_hasher::equal
|
||||
later can cheaply compare two atoms using just pointer equality. */
|
||||
if (!atom_cache)
|
||||
atom_cache = hash_table<atom_hasher>::create_ggc (31);
|
||||
tree *slot = atom_cache->find_slot (atom, INSERT);
|
||||
if (*slot)
|
||||
return *slot;
|
||||
*slot = atom;
|
||||
}
|
||||
return atom;
|
||||
}
|
||||
|
||||
/* Returns the normal form of an expression. */
|
||||
|
@ -2294,13 +2310,18 @@ struct sat_hasher : ggc_ptr_hash<sat_entry>
|
|||
{
|
||||
static hashval_t hash (sat_entry *e)
|
||||
{
|
||||
hashval_t value = hash_atomic_constraint (e->constr);
|
||||
/* Since normalize_atom caches the ATOMIC_CONSTRs it returns,
|
||||
we can assume pointer-based identity for fast hashing and
|
||||
comparison. Even if this assumption is violated, that's
|
||||
okay, we'll just get a cache miss. */
|
||||
hashval_t value = htab_hash_pointer (e->constr);
|
||||
return iterative_hash_template_arg (e->args, value);
|
||||
}
|
||||
|
||||
static bool equal (sat_entry *e1, sat_entry *e2)
|
||||
{
|
||||
if (!atomic_constraints_identical_p (e1->constr, e2->constr))
|
||||
/* As in sat_hasher::hash. */
|
||||
if (e1->constr != e2->constr)
|
||||
return false;
|
||||
return template_args_equal (e1->args, e2->args);
|
||||
}
|
||||
|
|
|
@ -7839,6 +7839,21 @@ extern hashval_t iterative_hash_constraint (tree, hashval_t);
|
|||
extern hashval_t hash_atomic_constraint (tree);
|
||||
extern void diagnose_constraints (location_t, tree, tree);
|
||||
|
||||
/* A structural hasher for ATOMIC_CONSTRs. */
|
||||
|
||||
struct atom_hasher : default_hash_traits<tree>
|
||||
{
|
||||
static hashval_t hash (tree t)
|
||||
{
|
||||
return hash_atomic_constraint (t);
|
||||
}
|
||||
|
||||
static bool equal (tree t1, tree t2)
|
||||
{
|
||||
return atomic_constraints_identical_p (t1, t2);
|
||||
}
|
||||
};
|
||||
|
||||
/* in logic.cc */
|
||||
extern bool subsumes (tree, tree);
|
||||
|
||||
|
|
|
@ -47,21 +47,6 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "toplev.h"
|
||||
#include "type-utils.h"
|
||||
|
||||
/* Hash functions for atomic constrains. */
|
||||
|
||||
struct constraint_hash : default_hash_traits<tree>
|
||||
{
|
||||
static hashval_t hash (tree t)
|
||||
{
|
||||
return hash_atomic_constraint (t);
|
||||
}
|
||||
|
||||
static bool equal (tree t1, tree t2)
|
||||
{
|
||||
return atomic_constraints_identical_p (t1, t2);
|
||||
}
|
||||
};
|
||||
|
||||
/* A conjunctive or disjunctive clause.
|
||||
|
||||
Each clause maintains an iterator that refers to the current
|
||||
|
@ -219,7 +204,7 @@ struct clause
|
|||
}
|
||||
|
||||
std::list<tree> m_terms; /* The list of terms. */
|
||||
hash_set<tree, false, constraint_hash> m_set; /* The set of atomic constraints. */
|
||||
hash_set<tree, false, atom_hasher> m_set; /* The set of atomic constraints. */
|
||||
iterator m_current; /* The current term. */
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue