htab_t gimple_canonical_types;
static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
htab_t type_hash_cache;
+static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
+ htab_t canonical_type_hash_cache;
/* Global type comparison cache. This is by TYPE_UID for space efficiency
and thus cannot use and does not need GC. */
}
-static hashval_t gimple_type_hash (const void *);
+static hashval_t gimple_type_hash_1 (const void *, enum gtc_mode);
/* Structure used to maintain a cache of some type pairs compared by
gimple_types_compatible_p when comparing aggregate types. There are
/* If the hash values of t1 and t2 are different the types can't
possibly be the same. This helps keeping the type-pair hashtable
small, only tracking comparisons for hash collisions. */
- if (gimple_type_hash (t1) != gimple_type_hash (t2))
+ if (gimple_type_hash_1 (t1, mode) != gimple_type_hash_1 (t2, mode))
return false;
/* Allocate a new cache entry for this comparison. */
tree f1, f2;
/* The struct tags shall compare equal. */
- if (!compare_type_names_p (TYPE_MAIN_VARIANT (t1),
- TYPE_MAIN_VARIANT (t2), false))
+ if (mode == GTC_MERGE
+ && !compare_type_names_p (TYPE_MAIN_VARIANT (t1),
+ TYPE_MAIN_VARIANT (t2), false))
goto different_types;
/* For aggregate types, all the fields must be the same. */
f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
{
/* The fields must have the same name, offset and type. */
- if (DECL_NAME (f1) != DECL_NAME (f2)
+ if ((mode == GTC_MERGE
+ && DECL_NAME (f1) != DECL_NAME (f2))
|| DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
|| !gimple_compare_field_offset (f1, f2)
|| !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2), mode,
/* If the hash values of t1 and t2 are different the types can't
possibly be the same. This helps keeping the type-pair hashtable
small, only tracking comparisons for hash collisions. */
- if (gimple_type_hash (t1) != gimple_type_hash (t2))
+ if (gimple_type_hash_1 (t1, mode) != gimple_type_hash_1 (t2, mode))
return false;
/* If we've visited this type pair before (in the case of aggregates
static hashval_t
iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **,
- struct pointer_map_t *, struct obstack *);
+ struct pointer_map_t *, struct obstack *,
+ enum gtc_mode);
/* DFS visit the edge from the callers type with state *STATE to T.
Update the callers type hash V with the hash for T if it is not part
visit (tree t, struct sccs *state, hashval_t v,
VEC (tree, heap) **sccstack,
struct pointer_map_t *sccstate,
- struct obstack *sccstate_obstack)
+ struct obstack *sccstate_obstack, enum gtc_mode mode)
{
struct sccs *cstate = NULL;
struct tree_int_map m;
/* If there is a hash value recorded for this type then it can't
possibly be part of our parent SCC. Simply mix in its hash. */
m.base.from = t;
- if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
+ if ((slot = htab_find_slot (mode == GTC_MERGE
+ ? type_hash_cache : canonical_type_hash_cache,
+ &m, NO_INSERT))
&& *slot)
return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, v);
hashval_t tem;
/* Not yet visited. DFS recurse. */
tem = iterative_hash_gimple_type (t, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack,
+ mode);
if (!cstate)
cstate = (struct sccs *)* pointer_map_contains (sccstate, t);
state->low = MIN (state->low, cstate->low);
iterative_hash_gimple_type (tree type, hashval_t val,
VEC(tree, heap) **sccstack,
struct pointer_map_t *sccstate,
- struct obstack *sccstate_obstack)
+ struct obstack *sccstate_obstack,
+ enum gtc_mode mode)
{
hashval_t v;
void **slot;
{
v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
v = iterative_hash_name
- (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
+ (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
}
else
v = visit (TREE_TYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack, mode);
}
/* For integer types hash the types min/max values and the string flag. */
{
v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
v = visit (TYPE_DOMAIN (type), state, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack, mode);
}
/* Recurse for aggregates with a single element type. */
|| TREE_CODE (type) == COMPLEX_TYPE
|| TREE_CODE (type) == VECTOR_TYPE)
v = visit (TREE_TYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack, mode);
/* Incorporate function return and argument types. */
if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
/* For method types also incorporate their parent class. */
if (TREE_CODE (type) == METHOD_TYPE)
v = visit (TYPE_METHOD_BASETYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack, mode);
/* For result types allow mismatch in completeness. */
if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
{
v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
v = iterative_hash_name
- (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
+ (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (type))), v);
}
else
v = visit (TREE_TYPE (type), state, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack, mode);
for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
{
{
v = iterative_hash_hashval_t (TREE_CODE (TREE_VALUE (p)), v);
v = iterative_hash_name
- (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_VALUE (p))), v);
+ (TYPE_NAME (TYPE_MAIN_VARIANT (TREE_VALUE (p))), v);
}
else
v = visit (TREE_VALUE (p), state, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack, mode);
na++;
}
unsigned nf;
tree f;
- v = iterative_hash_name (TYPE_NAME (TYPE_MAIN_VARIANT (type)), v);
+ if (mode == GTC_MERGE)
+ v = iterative_hash_name (TYPE_NAME (TYPE_MAIN_VARIANT (type)), v);
for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
{
- v = iterative_hash_name (DECL_NAME (f), v);
+ if (mode == GTC_MERGE)
+ v = iterative_hash_name (DECL_NAME (f), v);
v = visit (TREE_TYPE (f), state, v,
- sccstack, sccstate, sccstate_obstack);
+ sccstack, sccstate, sccstate_obstack, mode);
nf++;
}
cstate->on_sccstack = false;
m->base.from = x;
m->to = cstate->u.hash;
- slot = htab_find_slot (type_hash_cache, m, INSERT);
+ slot = htab_find_slot (mode == GTC_MERGE
+ ? type_hash_cache : canonical_type_hash_cache,
+ m, INSERT);
gcc_assert (!*slot);
*slot = (void *) m;
}
types according to gimple_types_compatible_p. */
static hashval_t
-gimple_type_hash (const void *p)
+gimple_type_hash_1 (const void *p, enum gtc_mode mode)
{
const_tree t = (const_tree) p;
VEC(tree, heap) *sccstack = NULL;
void **slot;
struct tree_int_map m;
- if (type_hash_cache == NULL)
+ if (mode == GTC_MERGE
+ && type_hash_cache == NULL)
type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
tree_int_map_eq, NULL);
+ else if (mode == GTC_DIAG
+ && canonical_type_hash_cache == NULL)
+ canonical_type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
+ tree_int_map_eq, NULL);
m.base.from = CONST_CAST_TREE (t);
- if ((slot = htab_find_slot (type_hash_cache, &m, NO_INSERT))
+ if ((slot = htab_find_slot (mode == GTC_MERGE
+ ? type_hash_cache : canonical_type_hash_cache,
+ &m, NO_INSERT))
&& *slot)
return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, 0);
sccstate = pointer_map_create ();
gcc_obstack_init (&sccstate_obstack);
val = iterative_hash_gimple_type (CONST_CAST_TREE (t), 0,
- &sccstack, sccstate, &sccstate_obstack);
+ &sccstack, sccstate, &sccstate_obstack,
+ mode);
VEC_free (tree, heap, sccstack);
pointer_map_destroy (sccstate);
obstack_free (&sccstate_obstack, NULL);
return val;
}
+static hashval_t
+gimple_type_hash (const void *p)
+{
+ return gimple_type_hash_1 (p, GTC_MERGE);
+}
+
+static hashval_t
+gimple_canonical_type_hash (const void *p)
+{
+ return gimple_type_hash_1 (p, GTC_DIAG);
+}
+
/* Returns nonzero if P1 and P2 are equal. */
gimple_register_canonical_type (TYPE_MAIN_VARIANT (t));
if (gimple_canonical_types == NULL)
- gimple_canonical_types = htab_create_ggc (16381, gimple_type_hash,
+ gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
gimple_canonical_type_eq, 0);
slot = htab_find_slot (gimple_canonical_types, t, INSERT);
htab_collisions (gimple_types));
else
fprintf (stderr, "GIMPLE type table is empty\n");
+ if (type_hash_cache)
+ fprintf (stderr, "GIMPLE type hash table: size %ld, %ld elements, "
+ "%ld searches, %ld collisions (ratio: %f)\n",
+ (long) htab_size (type_hash_cache),
+ (long) htab_elements (type_hash_cache),
+ (long) type_hash_cache->searches,
+ (long) type_hash_cache->collisions,
+ htab_collisions (type_hash_cache));
+ else
+ fprintf (stderr, "GIMPLE type hash table is empty\n");
if (gimple_canonical_types)
fprintf (stderr, "GIMPLE canonical type table: size %ld, %ld elements, "
"%ld searches, %ld collisions (ratio: %f)\n",
htab_collisions (gimple_canonical_types));
else
fprintf (stderr, "GIMPLE canonical type table is empty\n");
- if (type_hash_cache)
- fprintf (stderr, "GIMPLE type hash table: size %ld, %ld elements, "
+ if (canonical_type_hash_cache)
+ fprintf (stderr, "GIMPLE canonical type hash table: size %ld, %ld elements, "
"%ld searches, %ld collisions (ratio: %f)\n",
- (long) htab_size (type_hash_cache),
- (long) htab_elements (type_hash_cache),
- (long) type_hash_cache->searches,
- (long) type_hash_cache->collisions,
- htab_collisions (type_hash_cache));
+ (long) htab_size (canonical_type_hash_cache),
+ (long) htab_elements (canonical_type_hash_cache),
+ (long) canonical_type_hash_cache->searches,
+ (long) canonical_type_hash_cache->collisions,
+ htab_collisions (canonical_type_hash_cache));
else
- fprintf (stderr, "GIMPLE type hash table is empty\n");
+ fprintf (stderr, "GIMPLE canonical type hash table is empty\n");
if (gtc_visited)
fprintf (stderr, "GIMPLE type comparison table: size %ld, %ld "
"elements, %ld searches, %ld collisions (ratio: %f)\n",
htab_delete (type_hash_cache);
type_hash_cache = NULL;
}
+ if (canonical_type_hash_cache)
+ {
+ htab_delete (canonical_type_hash_cache);
+ canonical_type_hash_cache = NULL;
+ }
if (gtc_visited)
{
htab_delete (gtc_visited);