diff options
author | Richard Guenther <rguenther@suse.de> | 2012-09-11 11:39:27 +0000 |
---|---|---|
committer | Richard Guenther <rguenther@suse.de> | 2012-09-11 11:39:27 +0000 |
commit | 1feb112c661cd2c84c6ce8b3c1019e1c5f13b3c8 (patch) | |
tree | 60891e0f2664c6adf4a5260fbe20326ef39ef539 /gcc/gimple.c | |
parent | 7e529ce907bc96188492eb271d31a24b258228c4 (diff) |
2012-09-11 Richard Guenther <rguenther@suse.de>
* gimple.h (gimple_register_type): Remove.
(print_gimple_types_stats): Adjust prototype.
* lto-streamer.h (print_lto_report): Likewise.
* lto-streamer.c (print_lto_report): Adjust.
* gimple.c (gimple_types, type_hash_cache, enum gtc_mode,
struct type_pair_d, lookup_type_pair, struct sccs,
next_dfs_num, gtc_next_dfs_num, struct gimple_type_leader_entry_s,
gimple_type_leader, gimple_lookup_type_leader, compare_type_names_p,
gtc_visit, gimple_types_compatible_p_1, gimple_types_compatible_p,
visit, iterative_hash_name, struct type_hash_pair,
type_hash_pair_compare, iterative_hash_gimple_type, gimple_type_hash,
gimple_type_eq, gimple_register_type_1, gimple_register_type):
Move to lto/lto.c.
(print_gimple_types_stats): Adjust.
(free_gimple_type_tables): Likewise.
lto/
* lto.c (gimple_types, type_hash_cache, enum gtc_mode,
struct type_pair_d, lookup_type_pair, struct sccs,
next_dfs_num, gtc_next_dfs_num, struct gimple_type_leader_entry_s,
gimple_type_leader, gimple_lookup_type_leader, compare_type_names_p,
gtc_visit, gimple_types_compatible_p_1, gimple_types_compatible_p,
visit, iterative_hash_name, struct type_hash_pair,
type_hash_pair_compare, iterative_hash_gimple_type, gimple_type_hash,
gimple_type_eq, gimple_register_type_1, gimple_register_type):
Move here from gimple.c
(read_cgraph_and_symbols): Free hash tables here.
(print_lto_report_1): New function wrapping print_lto_report.
(do_whole_program_analysis): Call it.
(lto_main): Likewise.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@191177 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r-- | gcc/gimple.c | 1181 |
1 files changed, 9 insertions, 1172 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index f639869e726..7c702cad71a 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -37,17 +37,10 @@ along with GCC; see the file COPYING3. If not see #include "demangle.h" #include "langhooks.h" -/* Global type table. FIXME lto, it should be possible to re-use some - of the type hashing routines in tree.c (type_hash_canon, type_hash_lookup, - etc), but those assume that types were built with the various - build_*_type routines which is not the case with the streamer. */ -static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node))) - htab_t gimple_types; +/* Global canonical type table. */ static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node))) 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; /* All the tuples have their operand vector (if present) at the very bottom @@ -3014,159 +3007,6 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip) } -enum gtc_mode { GTC_MERGE = 0, GTC_DIAG = 1 }; - -static hashval_t gimple_type_hash (const void *); - -/* Structure used to maintain a cache of some type pairs compared by - gimple_types_compatible_p when comparing aggregate types. There are - three possible values for SAME_P: - - -2: The pair (T1, T2) has just been inserted in the table. - 0: T1 and T2 are different types. - 1: T1 and T2 are the same type. - - The two elements in the SAME_P array are indexed by the comparison - mode gtc_mode. */ - -struct type_pair_d -{ - unsigned int uid1; - unsigned int uid2; - signed char same_p[2]; -}; -typedef struct type_pair_d *type_pair_t; -DEF_VEC_P(type_pair_t); -DEF_VEC_ALLOC_P(type_pair_t,heap); - -#define GIMPLE_TYPE_PAIR_SIZE 16381 -struct type_pair_d *type_pair_cache; - - -/* Lookup the pair of types T1 and T2 in *VISITED_P. Insert a new - entry if none existed. */ - -static inline type_pair_t -lookup_type_pair (tree t1, tree t2) -{ - unsigned int index; - unsigned int uid1, uid2; - - if (type_pair_cache == NULL) - type_pair_cache = XCNEWVEC (struct type_pair_d, GIMPLE_TYPE_PAIR_SIZE); - - if (TYPE_UID (t1) < TYPE_UID (t2)) - { - uid1 = TYPE_UID (t1); - uid2 = TYPE_UID (t2); - } - else - { - uid1 = TYPE_UID (t2); - uid2 = TYPE_UID (t1); - } - gcc_checking_assert (uid1 != uid2); - - /* iterative_hash_hashval_t imply an function calls. - We know that UIDS are in limited range. */ - index = ((((unsigned HOST_WIDE_INT)uid1 << HOST_BITS_PER_WIDE_INT / 2) + uid2) - % GIMPLE_TYPE_PAIR_SIZE); - if (type_pair_cache [index].uid1 == uid1 - && type_pair_cache [index].uid2 == uid2) - return &type_pair_cache[index]; - - type_pair_cache [index].uid1 = uid1; - type_pair_cache [index].uid2 = uid2; - type_pair_cache [index].same_p[0] = -2; - type_pair_cache [index].same_p[1] = -2; - - return &type_pair_cache[index]; -} - -/* Per pointer state for the SCC finding. The on_sccstack flag - is not strictly required, it is true when there is no hash value - recorded for the type and false otherwise. But querying that - is slower. */ - -struct sccs -{ - unsigned int dfsnum; - unsigned int low; - bool on_sccstack; - union { - hashval_t hash; - signed char same_p; - } u; -}; - -static unsigned int next_dfs_num; -static unsigned int gtc_next_dfs_num; - - -/* GIMPLE type merging cache. A direct-mapped cache based on TYPE_UID. */ - -typedef struct GTY(()) gimple_type_leader_entry_s { - tree type; - tree leader; -} gimple_type_leader_entry; - -#define GIMPLE_TYPE_LEADER_SIZE 16381 -static GTY((deletable, length("GIMPLE_TYPE_LEADER_SIZE"))) - gimple_type_leader_entry *gimple_type_leader; - -/* Lookup an existing leader for T and return it or NULL_TREE, if - there is none in the cache. */ - -static inline tree -gimple_lookup_type_leader (tree t) -{ - gimple_type_leader_entry *leader; - - if (!gimple_type_leader) - return NULL_TREE; - - leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE]; - if (leader->type != t) - return NULL_TREE; - - return leader->leader; -} - -/* Return true if T1 and T2 have the same name. If FOR_COMPLETION_P is - true then if any type has no name return false, otherwise return - true if both types have no names. */ - -static bool -compare_type_names_p (tree t1, tree t2) -{ - tree name1 = TYPE_NAME (t1); - tree name2 = TYPE_NAME (t2); - - if ((name1 != NULL_TREE) != (name2 != NULL_TREE)) - return false; - - if (name1 == NULL_TREE) - return true; - - /* Either both should be a TYPE_DECL or both an IDENTIFIER_NODE. */ - if (TREE_CODE (name1) != TREE_CODE (name2)) - return false; - - if (TREE_CODE (name1) == TYPE_DECL) - name1 = DECL_NAME (name1); - gcc_checking_assert (!name1 || TREE_CODE (name1) == IDENTIFIER_NODE); - - if (TREE_CODE (name2) == TYPE_DECL) - name2 = DECL_NAME (name2); - gcc_checking_assert (!name2 || TREE_CODE (name2) == IDENTIFIER_NODE); - - /* Identifiers can be compared with pointer equality rather - than a string comparison. */ - if (name1 == name2) - return true; - - return false; -} /* Return true if the field decls F1 and F2 are at the same offset. @@ -3219,892 +3059,6 @@ gimple_compare_field_offset (tree f1, tree f2) return false; } -static bool -gimple_types_compatible_p_1 (tree, tree, type_pair_t, - VEC(type_pair_t, heap) **, - struct pointer_map_t *, struct obstack *); - -/* DFS visit the edge from the callers type pair with state *STATE to - the pair T1, T2 while operating in FOR_MERGING_P mode. - Update the merging status if it is not part of the SCC containing the - callers pair and return it. - SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */ - -static bool -gtc_visit (tree t1, tree t2, - struct sccs *state, - VEC(type_pair_t, heap) **sccstack, - struct pointer_map_t *sccstate, - struct obstack *sccstate_obstack) -{ - struct sccs *cstate = NULL; - type_pair_t p; - void **slot; - tree leader1, leader2; - - /* Check first for the obvious case of pointer identity. */ - if (t1 == t2) - return true; - - /* Check that we have two types to compare. */ - if (t1 == NULL_TREE || t2 == NULL_TREE) - return false; - - /* Can't be the same type if the types don't have the same code. */ - if (TREE_CODE (t1) != TREE_CODE (t2)) - return false; - - /* Can't be the same type if they have different CV qualifiers. */ - if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) - return false; - - if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)) - return false; - - /* Void types and nullptr types are always the same. */ - if (TREE_CODE (t1) == VOID_TYPE - || TREE_CODE (t1) == NULLPTR_TYPE) - return true; - - /* Can't be the same type if they have different alignment or mode. */ - if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2) - || TYPE_MODE (t1) != TYPE_MODE (t2)) - return false; - - /* Do some simple checks before doing three hashtable queries. */ - if (INTEGRAL_TYPE_P (t1) - || SCALAR_FLOAT_TYPE_P (t1) - || FIXED_POINT_TYPE_P (t1) - || TREE_CODE (t1) == VECTOR_TYPE - || TREE_CODE (t1) == COMPLEX_TYPE - || TREE_CODE (t1) == OFFSET_TYPE - || POINTER_TYPE_P (t1)) - { - /* Can't be the same type if they have different sign or precision. */ - if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2) - || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) - return false; - - if (TREE_CODE (t1) == INTEGER_TYPE - && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) - return false; - - /* That's all we need to check for float and fixed-point types. */ - if (SCALAR_FLOAT_TYPE_P (t1) - || FIXED_POINT_TYPE_P (t1)) - return true; - - /* For other types fall through to more complex checks. */ - } - - /* If the types have been previously registered and found equal - they still are. */ - leader1 = gimple_lookup_type_leader (t1); - leader2 = gimple_lookup_type_leader (t2); - if (leader1 == t2 - || t1 == leader2 - || (leader1 && leader1 == leader2)) - return true; - - /* 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)) - return false; - - /* Allocate a new cache entry for this comparison. */ - p = lookup_type_pair (t1, t2); - if (p->same_p[GTC_MERGE] == 0 || p->same_p[GTC_MERGE] == 1) - { - /* We have already decided whether T1 and T2 are the - same, return the cached result. */ - return p->same_p[GTC_MERGE] == 1; - } - - if ((slot = pointer_map_contains (sccstate, p)) != NULL) - cstate = (struct sccs *)*slot; - /* Not yet visited. DFS recurse. */ - if (!cstate) - { - gimple_types_compatible_p_1 (t1, t2, p, - sccstack, sccstate, sccstate_obstack); - cstate = (struct sccs *)* pointer_map_contains (sccstate, p); - state->low = MIN (state->low, cstate->low); - } - /* If the type is still on the SCC stack adjust the parents low. */ - if (cstate->dfsnum < state->dfsnum - && cstate->on_sccstack) - state->low = MIN (cstate->dfsnum, state->low); - - /* Return the current lattice value. We start with an equality - assumption so types part of a SCC will be optimistically - treated equal unless proven otherwise. */ - return cstate->u.same_p; -} - -/* Worker for gimple_types_compatible. - SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */ - -static bool -gimple_types_compatible_p_1 (tree t1, tree t2, type_pair_t p, - VEC(type_pair_t, heap) **sccstack, - struct pointer_map_t *sccstate, - struct obstack *sccstate_obstack) -{ - struct sccs *state; - - gcc_assert (p->same_p[GTC_MERGE] == -2); - - state = XOBNEW (sccstate_obstack, struct sccs); - *pointer_map_insert (sccstate, p) = state; - - VEC_safe_push (type_pair_t, heap, *sccstack, p); - state->dfsnum = gtc_next_dfs_num++; - state->low = state->dfsnum; - state->on_sccstack = true; - /* Start with an equality assumption. As we DFS recurse into child - SCCs this assumption may get revisited. */ - state->u.same_p = 1; - - /* The struct tags shall compare equal. */ - if (!compare_type_names_p (t1, t2)) - goto different_types; - - /* We may not merge typedef types to the same type in different - contexts. */ - if (TYPE_NAME (t1) - && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL - && DECL_CONTEXT (TYPE_NAME (t1)) - && TYPE_P (DECL_CONTEXT (TYPE_NAME (t1)))) - { - if (!gtc_visit (DECL_CONTEXT (TYPE_NAME (t1)), - DECL_CONTEXT (TYPE_NAME (t2)), - state, sccstack, sccstate, sccstate_obstack)) - goto different_types; - } - - /* If their attributes are not the same they can't be the same type. */ - if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2))) - goto different_types; - - /* Do type-specific comparisons. */ - switch (TREE_CODE (t1)) - { - case VECTOR_TYPE: - case COMPLEX_TYPE: - if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), - state, sccstack, sccstate, sccstate_obstack)) - goto different_types; - goto same_types; - - case ARRAY_TYPE: - /* Array types are the same if the element types are the same and - the number of elements are the same. */ - if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), - state, sccstack, sccstate, sccstate_obstack) - || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2) - || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2)) - goto different_types; - else - { - tree i1 = TYPE_DOMAIN (t1); - tree i2 = TYPE_DOMAIN (t2); - - /* For an incomplete external array, the type domain can be - NULL_TREE. Check this condition also. */ - if (i1 == NULL_TREE && i2 == NULL_TREE) - goto same_types; - else if (i1 == NULL_TREE || i2 == NULL_TREE) - goto different_types; - else - { - tree min1 = TYPE_MIN_VALUE (i1); - tree min2 = TYPE_MIN_VALUE (i2); - tree max1 = TYPE_MAX_VALUE (i1); - tree max2 = TYPE_MAX_VALUE (i2); - - /* The minimum/maximum values have to be the same. */ - if ((min1 == min2 - || (min1 && min2 - && ((TREE_CODE (min1) == PLACEHOLDER_EXPR - && TREE_CODE (min2) == PLACEHOLDER_EXPR) - || operand_equal_p (min1, min2, 0)))) - && (max1 == max2 - || (max1 && max2 - && ((TREE_CODE (max1) == PLACEHOLDER_EXPR - && TREE_CODE (max2) == PLACEHOLDER_EXPR) - || operand_equal_p (max1, max2, 0))))) - goto same_types; - else - goto different_types; - } - } - - case METHOD_TYPE: - /* Method types should belong to the same class. */ - if (!gtc_visit (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2), - state, sccstack, sccstate, sccstate_obstack)) - goto different_types; - - /* Fallthru */ - - case FUNCTION_TYPE: - /* Function types are the same if the return type and arguments types - are the same. */ - if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), - state, sccstack, sccstate, sccstate_obstack)) - goto different_types; - - if (!comp_type_attributes (t1, t2)) - goto different_types; - - if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)) - goto same_types; - else - { - tree parms1, parms2; - - for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2); - parms1 && parms2; - parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2)) - { - if (!gtc_visit (TREE_VALUE (parms1), TREE_VALUE (parms2), - state, sccstack, sccstate, sccstate_obstack)) - goto different_types; - } - - if (parms1 || parms2) - goto different_types; - - goto same_types; - } - - case OFFSET_TYPE: - { - if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), - state, sccstack, sccstate, sccstate_obstack) - || !gtc_visit (TYPE_OFFSET_BASETYPE (t1), - TYPE_OFFSET_BASETYPE (t2), - state, sccstack, sccstate, sccstate_obstack)) - goto different_types; - - goto same_types; - } - - case POINTER_TYPE: - case REFERENCE_TYPE: - { - /* If the two pointers have different ref-all attributes, - they can't be the same type. */ - if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) - goto different_types; - - /* Otherwise, pointer and reference types are the same if the - pointed-to types are the same. */ - if (gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), - state, sccstack, sccstate, sccstate_obstack)) - goto same_types; - - goto different_types; - } - - case INTEGER_TYPE: - case BOOLEAN_TYPE: - { - tree min1 = TYPE_MIN_VALUE (t1); - tree max1 = TYPE_MAX_VALUE (t1); - tree min2 = TYPE_MIN_VALUE (t2); - tree max2 = TYPE_MAX_VALUE (t2); - bool min_equal_p = false; - bool max_equal_p = false; - - /* If either type has a minimum value, the other type must - have the same. */ - if (min1 == NULL_TREE && min2 == NULL_TREE) - min_equal_p = true; - else if (min1 && min2 && operand_equal_p (min1, min2, 0)) - min_equal_p = true; - - /* Likewise, if either type has a maximum value, the other - type must have the same. */ - if (max1 == NULL_TREE && max2 == NULL_TREE) - max_equal_p = true; - else if (max1 && max2 && operand_equal_p (max1, max2, 0)) - max_equal_p = true; - - if (!min_equal_p || !max_equal_p) - goto different_types; - - goto same_types; - } - - case ENUMERAL_TYPE: - { - /* FIXME lto, we cannot check bounds on enumeral types because - different front ends will produce different values. - In C, enumeral types are integers, while in C++ each element - will have its own symbolic value. We should decide how enums - are to be represented in GIMPLE and have each front end lower - to that. */ - tree v1, v2; - - /* For enumeral types, all the values must be the same. */ - if (TYPE_VALUES (t1) == TYPE_VALUES (t2)) - goto same_types; - - for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2); - v1 && v2; - v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2)) - { - tree c1 = TREE_VALUE (v1); - tree c2 = TREE_VALUE (v2); - - if (TREE_CODE (c1) == CONST_DECL) - c1 = DECL_INITIAL (c1); - - if (TREE_CODE (c2) == CONST_DECL) - c2 = DECL_INITIAL (c2); - - if (tree_int_cst_equal (c1, c2) != 1) - goto different_types; - - if (TREE_PURPOSE (v1) != TREE_PURPOSE (v2)) - goto different_types; - } - - /* If one enumeration has more values than the other, they - are not the same. */ - if (v1 || v2) - goto different_types; - - goto same_types; - } - - case RECORD_TYPE: - case UNION_TYPE: - case QUAL_UNION_TYPE: - { - tree f1, f2; - - /* For aggregate types, all the fields must be the same. */ - for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); - f1 && f2; - f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) - { - /* Different field kinds are not compatible. */ - if (TREE_CODE (f1) != TREE_CODE (f2)) - goto different_types; - /* Field decls must have the same name and offset. */ - if (TREE_CODE (f1) == FIELD_DECL - && (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2) - || !gimple_compare_field_offset (f1, f2))) - goto different_types; - /* All entities should have the same name and type. */ - if (DECL_NAME (f1) != DECL_NAME (f2) - || !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2), - state, sccstack, sccstate, sccstate_obstack)) - goto different_types; - } - - /* If one aggregate has more fields than the other, they - are not the same. */ - if (f1 || f2) - goto different_types; - - goto same_types; - } - - default: - gcc_unreachable (); - } - - /* Common exit path for types that are not compatible. */ -different_types: - state->u.same_p = 0; - goto pop; - - /* Common exit path for types that are compatible. */ -same_types: - gcc_assert (state->u.same_p == 1); - -pop: - if (state->low == state->dfsnum) - { - type_pair_t x; - - /* Pop off the SCC and set its cache values to the final - comparison result. */ - do - { - struct sccs *cstate; - x = VEC_pop (type_pair_t, *sccstack); - cstate = (struct sccs *)*pointer_map_contains (sccstate, x); - cstate->on_sccstack = false; - x->same_p[GTC_MERGE] = state->u.same_p; - } - while (x != p); - } - - return state->u.same_p; -} - -/* Return true iff T1 and T2 are structurally identical. When - FOR_MERGING_P is true the an incomplete type and a complete type - are considered different, otherwise they are considered compatible. */ - -static bool -gimple_types_compatible_p (tree t1, tree t2) -{ - VEC(type_pair_t, heap) *sccstack = NULL; - struct pointer_map_t *sccstate; - struct obstack sccstate_obstack; - type_pair_t p = NULL; - bool res; - tree leader1, leader2; - - /* Before starting to set up the SCC machinery handle simple cases. */ - - /* Check first for the obvious case of pointer identity. */ - if (t1 == t2) - return true; - - /* Check that we have two types to compare. */ - if (t1 == NULL_TREE || t2 == NULL_TREE) - return false; - - /* Can't be the same type if the types don't have the same code. */ - if (TREE_CODE (t1) != TREE_CODE (t2)) - return false; - - /* Can't be the same type if they have different CV qualifiers. */ - if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) - return false; - - if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)) - return false; - - /* Void types and nullptr types are always the same. */ - if (TREE_CODE (t1) == VOID_TYPE - || TREE_CODE (t1) == NULLPTR_TYPE) - return true; - - /* Can't be the same type if they have different alignment or mode. */ - if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2) - || TYPE_MODE (t1) != TYPE_MODE (t2)) - return false; - - /* Do some simple checks before doing three hashtable queries. */ - if (INTEGRAL_TYPE_P (t1) - || SCALAR_FLOAT_TYPE_P (t1) - || FIXED_POINT_TYPE_P (t1) - || TREE_CODE (t1) == VECTOR_TYPE - || TREE_CODE (t1) == COMPLEX_TYPE - || TREE_CODE (t1) == OFFSET_TYPE - || POINTER_TYPE_P (t1)) - { - /* Can't be the same type if they have different sign or precision. */ - if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2) - || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) - return false; - - if (TREE_CODE (t1) == INTEGER_TYPE - && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) - return false; - - /* That's all we need to check for float and fixed-point types. */ - if (SCALAR_FLOAT_TYPE_P (t1) - || FIXED_POINT_TYPE_P (t1)) - return true; - - /* For other types fall through to more complex checks. */ - } - - /* If the types have been previously registered and found equal - they still are. */ - leader1 = gimple_lookup_type_leader (t1); - leader2 = gimple_lookup_type_leader (t2); - if (leader1 == t2 - || t1 == leader2 - || (leader1 && leader1 == leader2)) - return true; - - /* 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)) - return false; - - /* If we've visited this type pair before (in the case of aggregates - with self-referential types), and we made a decision, return it. */ - p = lookup_type_pair (t1, t2); - if (p->same_p[GTC_MERGE] == 0 || p->same_p[GTC_MERGE] == 1) - { - /* We have already decided whether T1 and T2 are the - same, return the cached result. */ - return p->same_p[GTC_MERGE] == 1; - } - - /* Now set up the SCC machinery for the comparison. */ - gtc_next_dfs_num = 1; - sccstate = pointer_map_create (); - gcc_obstack_init (&sccstate_obstack); - res = gimple_types_compatible_p_1 (t1, t2, p, - &sccstack, sccstate, &sccstate_obstack); - VEC_free (type_pair_t, heap, sccstack); - pointer_map_destroy (sccstate); - obstack_free (&sccstate_obstack, NULL); - - return res; -} - - -static hashval_t -iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **, - struct pointer_map_t *, struct obstack *); - -/* 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 - of the SCC containing the callers type and return it. - SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */ - -static hashval_t -visit (tree t, struct sccs *state, hashval_t v, - VEC (tree, heap) **sccstack, - struct pointer_map_t *sccstate, - struct obstack *sccstate_obstack) -{ - struct sccs *cstate = NULL; - struct tree_int_map m; - void **slot; - - /* 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)) - && *slot) - return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, v); - - if ((slot = pointer_map_contains (sccstate, t)) != NULL) - cstate = (struct sccs *)*slot; - if (!cstate) - { - hashval_t tem; - /* Not yet visited. DFS recurse. */ - tem = iterative_hash_gimple_type (t, v, - sccstack, sccstate, sccstate_obstack); - if (!cstate) - cstate = (struct sccs *)* pointer_map_contains (sccstate, t); - state->low = MIN (state->low, cstate->low); - /* If the type is no longer on the SCC stack and thus is not part - of the parents SCC mix in its hash value. Otherwise we will - ignore the type for hashing purposes and return the unaltered - hash value. */ - if (!cstate->on_sccstack) - return tem; - } - if (cstate->dfsnum < state->dfsnum - && cstate->on_sccstack) - state->low = MIN (cstate->dfsnum, state->low); - - /* We are part of our parents SCC, skip this type during hashing - and return the unaltered hash value. */ - return v; -} - -/* Hash NAME with the previous hash value V and return it. */ - -static hashval_t -iterative_hash_name (tree name, hashval_t v) -{ - if (!name) - return v; - v = iterative_hash_hashval_t (TREE_CODE (name), v); - if (TREE_CODE (name) == TYPE_DECL) - name = DECL_NAME (name); - if (!name) - return v; - gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); - return iterative_hash_object (IDENTIFIER_HASH_VALUE (name), v); -} - -/* A type, hashvalue pair for sorting SCC members. */ - -struct type_hash_pair { - tree type; - hashval_t hash; -}; - -/* Compare two type, hashvalue pairs. */ - -static int -type_hash_pair_compare (const void *p1_, const void *p2_) -{ - const struct type_hash_pair *p1 = (const struct type_hash_pair *) p1_; - const struct type_hash_pair *p2 = (const struct type_hash_pair *) p2_; - if (p1->hash < p2->hash) - return -1; - else if (p1->hash > p2->hash) - return 1; - return 0; -} - -/* Returning a hash value for gimple type TYPE combined with VAL. - SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. - - To hash a type we end up hashing in types that are reachable. - Through pointers we can end up with cycles which messes up the - required property that we need to compute the same hash value - for structurally equivalent types. To avoid this we have to - hash all types in a cycle (the SCC) in a commutative way. The - easiest way is to not mix in the hashes of the SCC members at - all. To make this work we have to delay setting the hash - values of the SCC until it is complete. */ - -static hashval_t -iterative_hash_gimple_type (tree type, hashval_t val, - VEC(tree, heap) **sccstack, - struct pointer_map_t *sccstate, - struct obstack *sccstate_obstack) -{ - hashval_t v; - void **slot; - struct sccs *state; - - /* Not visited during this DFS walk. */ - gcc_checking_assert (!pointer_map_contains (sccstate, type)); - state = XOBNEW (sccstate_obstack, struct sccs); - *pointer_map_insert (sccstate, type) = state; - - VEC_safe_push (tree, heap, *sccstack, type); - state->dfsnum = next_dfs_num++; - state->low = state->dfsnum; - state->on_sccstack = true; - - /* Combine a few common features of types so that types are grouped into - smaller sets; when searching for existing matching types to merge, - only existing types having the same features as the new type will be - checked. */ - v = iterative_hash_name (TYPE_NAME (type), 0); - if (TYPE_NAME (type) - && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_CONTEXT (TYPE_NAME (type)) - && TYPE_P (DECL_CONTEXT (TYPE_NAME (type)))) - v = visit (DECL_CONTEXT (TYPE_NAME (type)), state, v, - sccstack, sccstate, sccstate_obstack); - v = iterative_hash_hashval_t (TREE_CODE (type), v); - v = iterative_hash_hashval_t (TYPE_QUALS (type), v); - v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v); - - /* Do not hash the types size as this will cause differences in - hash values for the complete vs. the incomplete type variant. */ - - /* Incorporate common features of numerical types. */ - if (INTEGRAL_TYPE_P (type) - || SCALAR_FLOAT_TYPE_P (type) - || FIXED_POINT_TYPE_P (type)) - { - v = iterative_hash_hashval_t (TYPE_PRECISION (type), v); - v = iterative_hash_hashval_t (TYPE_MODE (type), v); - v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v); - } - - /* For pointer and reference types, fold in information about the type - pointed to. */ - if (POINTER_TYPE_P (type)) - v = visit (TREE_TYPE (type), state, v, - sccstack, sccstate, sccstate_obstack); - - /* For integer types hash the types min/max values and the string flag. */ - if (TREE_CODE (type) == INTEGER_TYPE) - { - /* OMP lowering can introduce error_mark_node in place of - random local decls in types. */ - if (TYPE_MIN_VALUE (type) != error_mark_node) - v = iterative_hash_expr (TYPE_MIN_VALUE (type), v); - if (TYPE_MAX_VALUE (type) != error_mark_node) - v = iterative_hash_expr (TYPE_MAX_VALUE (type), v); - v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v); - } - - /* For array types hash the domain and the string flag. */ - if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) - { - v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v); - v = visit (TYPE_DOMAIN (type), state, v, - sccstack, sccstate, sccstate_obstack); - } - - /* Recurse for aggregates with a single element type. */ - if (TREE_CODE (type) == ARRAY_TYPE - || TREE_CODE (type) == COMPLEX_TYPE - || TREE_CODE (type) == VECTOR_TYPE) - v = visit (TREE_TYPE (type), state, v, - sccstack, sccstate, sccstate_obstack); - - /* Incorporate function return and argument types. */ - if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) - { - unsigned na; - tree p; - - /* 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); - - /* Check result and argument types. */ - v = visit (TREE_TYPE (type), state, v, - sccstack, sccstate, sccstate_obstack); - for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p)) - { - v = visit (TREE_VALUE (p), state, v, - sccstack, sccstate, sccstate_obstack); - na++; - } - - v = iterative_hash_hashval_t (na, v); - } - - if (RECORD_OR_UNION_TYPE_P (type)) - { - unsigned nf; - tree f; - - for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f)) - { - v = iterative_hash_name (DECL_NAME (f), v); - v = visit (TREE_TYPE (f), state, v, - sccstack, sccstate, sccstate_obstack); - nf++; - } - - v = iterative_hash_hashval_t (nf, v); - } - - /* Record hash for us. */ - state->u.hash = v; - - /* See if we found an SCC. */ - if (state->low == state->dfsnum) - { - tree x; - struct tree_int_map *m; - - /* Pop off the SCC and set its hash values. */ - x = VEC_pop (tree, *sccstack); - /* Optimize SCC size one. */ - if (x == type) - { - state->on_sccstack = false; - m = ggc_alloc_cleared_tree_int_map (); - m->base.from = x; - m->to = v; - slot = htab_find_slot (type_hash_cache, m, INSERT); - gcc_assert (!*slot); - *slot = (void *) m; - } - else - { - struct sccs *cstate; - unsigned first, i, size, j; - struct type_hash_pair *pairs; - /* Pop off the SCC and build an array of type, hash pairs. */ - first = VEC_length (tree, *sccstack) - 1; - while (VEC_index (tree, *sccstack, first) != type) - --first; - size = VEC_length (tree, *sccstack) - first + 1; - pairs = XALLOCAVEC (struct type_hash_pair, size); - i = 0; - cstate = (struct sccs *)*pointer_map_contains (sccstate, x); - cstate->on_sccstack = false; - pairs[i].type = x; - pairs[i].hash = cstate->u.hash; - do - { - x = VEC_pop (tree, *sccstack); - cstate = (struct sccs *)*pointer_map_contains (sccstate, x); - cstate->on_sccstack = false; - ++i; - pairs[i].type = x; - pairs[i].hash = cstate->u.hash; - } - while (x != type); - gcc_assert (i + 1 == size); - /* Sort the arrays of type, hash pairs so that when we mix in - all members of the SCC the hash value becomes independent on - the order we visited the SCC. Disregard hashes equal to - the hash of the type we mix into because we cannot guarantee - a stable sort for those across different TUs. */ - qsort (pairs, size, sizeof (struct type_hash_pair), - type_hash_pair_compare); - for (i = 0; i < size; ++i) - { - hashval_t hash; - m = ggc_alloc_cleared_tree_int_map (); - m->base.from = pairs[i].type; - hash = pairs[i].hash; - /* Skip same hashes. */ - for (j = i + 1; j < size && pairs[j].hash == pairs[i].hash; ++j) - ; - for (; j < size; ++j) - hash = iterative_hash_hashval_t (pairs[j].hash, hash); - for (j = 0; pairs[j].hash != pairs[i].hash; ++j) - hash = iterative_hash_hashval_t (pairs[j].hash, hash); - m->to = hash; - if (pairs[i].type == type) - v = hash; - slot = htab_find_slot (type_hash_cache, m, INSERT); - gcc_assert (!*slot); - *slot = (void *) m; - } - } - } - - return iterative_hash_hashval_t (v, val); -} - - -/* Returns a hash value for P (assumed to be a type). The hash value - is computed using some distinguishing features of the type. Note - that we cannot use pointer hashing here as we may be dealing with - two distinct instances of the same type. - - This function should produce the same hash value for two compatible - types according to gimple_types_compatible_p. */ - -static hashval_t -gimple_type_hash (const void *p) -{ - const_tree t = (const_tree) p; - VEC(tree, heap) *sccstack = NULL; - struct pointer_map_t *sccstate; - struct obstack sccstate_obstack; - hashval_t val; - void **slot; - struct tree_int_map m; - - if (type_hash_cache == NULL) - 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)) - && *slot) - return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, 0); - - /* Perform a DFS walk and pre-hash all reachable types. */ - next_dfs_num = 1; - sccstate = pointer_map_create (); - gcc_obstack_init (&sccstate_obstack); - val = iterative_hash_gimple_type (CONST_CAST_TREE (t), 0, - &sccstack, sccstate, &sccstate_obstack); - VEC_free (tree, heap, sccstack); - pointer_map_destroy (sccstate); - obstack_free (&sccstate_obstack, NULL); - - return val; -} - /* Returning a hash value for gimple type TYPE combined with VAL. The hash value returned is equal for types considered compatible @@ -4232,84 +3186,7 @@ gimple_canonical_type_hash (const void *p) } -/* Returns nonzero if P1 and P2 are equal. */ - -static int -gimple_type_eq (const void *p1, const void *p2) -{ - const_tree t1 = (const_tree) p1; - const_tree t2 = (const_tree) p2; - return gimple_types_compatible_p (CONST_CAST_TREE (t1), - CONST_CAST_TREE (t2)); -} - - -/* Worker for gimple_register_type. - Register type T in the global type table gimple_types. - When REGISTERING_MV is false first recurse for the main variant of T. */ - -static tree -gimple_register_type_1 (tree t, bool registering_mv) -{ - void **slot; - gimple_type_leader_entry *leader; - - /* If we registered this type before return the cached result. */ - leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE]; - if (leader->type == t) - return leader->leader; - - /* Always register the main variant first. This is important so we - pick up the non-typedef variants as canonical, otherwise we'll end - up taking typedef ids for structure tags during comparison. - It also makes sure that main variants will be merged to main variants. - As we are operating on a possibly partially fixed up type graph - do not bother to recurse more than once, otherwise we may end up - walking in circles. - If we are registering a main variant it will either remain its - own main variant or it will be merged to something else in which - case we do not care for the main variant leader. */ - if (!registering_mv - && TYPE_MAIN_VARIANT (t) != t) - gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true); - - /* See if we already have an equivalent type registered. */ - slot = htab_find_slot (gimple_types, t, INSERT); - if (*slot - && *(tree *)slot != t) - { - tree new_type = (tree) *((tree *) slot); - leader->type = t; - leader->leader = new_type; - return new_type; - } - - /* If not, insert it to the cache and the hash. */ - leader->type = t; - leader->leader = t; - *slot = (void *) t; - return t; -} - -/* Register type T in the global type table gimple_types. - If another type T', compatible with T, already existed in - gimple_types then return T', otherwise return T. This is used by - LTO to merge identical types read from different TUs. */ - -tree -gimple_register_type (tree t) -{ - gcc_assert (TYPE_P (t)); - - if (!gimple_type_leader) - gimple_type_leader = ggc_alloc_cleared_vec_gimple_type_leader_entry_s - (GIMPLE_TYPE_LEADER_SIZE); - - if (gimple_types == NULL) - gimple_types = htab_create_ggc (16381, gimple_type_hash, gimple_type_eq, 0); - return gimple_register_type_1 (t, false); -} /* The TYPE_CANONICAL merging machinery. It should closely resemble the middle-end types_compatible_p function. It needs to avoid @@ -4583,48 +3460,28 @@ gimple_register_canonical_type (tree t) /* Show statistics on references to the global type table gimple_types. */ void -print_gimple_types_stats (void) -{ - if (gimple_types) - fprintf (stderr, "GIMPLE type table: size %ld, %ld elements, " - "%ld searches, %ld collisions (ratio: %f)\n", - (long) htab_size (gimple_types), - (long) htab_elements (gimple_types), - (long) gimple_types->searches, - (long) gimple_types->collisions, - 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"); +print_gimple_types_stats (const char *pfx) +{ if (gimple_canonical_types) - fprintf (stderr, "GIMPLE canonical type table: size %ld, %ld elements, " - "%ld searches, %ld collisions (ratio: %f)\n", + fprintf (stderr, "[%s] GIMPLE canonical type table: size %ld, " + "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx, (long) htab_size (gimple_canonical_types), (long) htab_elements (gimple_canonical_types), (long) gimple_canonical_types->searches, (long) gimple_canonical_types->collisions, htab_collisions (gimple_canonical_types)); else - fprintf (stderr, "GIMPLE canonical type table is empty\n"); + fprintf (stderr, "[%s] GIMPLE canonical type table is empty\n", pfx); if (canonical_type_hash_cache) - fprintf (stderr, "GIMPLE canonical type hash table: size %ld, %ld elements, " - "%ld searches, %ld collisions (ratio: %f)\n", + fprintf (stderr, "[%s] GIMPLE canonical type hash table: size %ld, " + "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx, (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 canonical type hash table is empty\n"); + fprintf (stderr, "[%s] GIMPLE canonical type hash table is empty\n", pfx); } /* Free the gimple type hashtables used for LTO type merging. */ @@ -4632,36 +3489,16 @@ print_gimple_types_stats (void) void free_gimple_type_tables (void) { - /* Last chance to print stats for the tables. */ - if (flag_lto_report) - print_gimple_types_stats (); - - if (gimple_types) - { - htab_delete (gimple_types); - gimple_types = NULL; - } if (gimple_canonical_types) { htab_delete (gimple_canonical_types); gimple_canonical_types = NULL; } - if (type_hash_cache) - { - 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 (type_pair_cache) - { - free (type_pair_cache); - type_pair_cache = NULL; - } - gimple_type_leader = NULL; } |