diff options
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r-- | gcc/gimple.c | 522 |
1 files changed, 386 insertions, 136 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index 0a5f6fb97d1..e3de8344c56 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1383,7 +1383,10 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op, case GIMPLE_CALL: if (wi) - wi->is_lhs = false; + { + wi->is_lhs = false; + wi->val_only = true; + } ret = walk_tree (gimple_call_chain_ptr (stmt), callback_op, wi, pset); if (ret) @@ -1395,21 +1398,32 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op, for (i = 0; i < gimple_call_num_args (stmt); i++) { + if (wi) + wi->val_only = is_gimple_reg_type (gimple_call_arg (stmt, i)); ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi, pset); if (ret) return ret; } - if (wi) - wi->is_lhs = true; + if (gimple_call_lhs (stmt)) + { + if (wi) + { + wi->is_lhs = true; + wi->val_only = is_gimple_reg_type (gimple_call_lhs (stmt)); + } - ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset); - if (ret) - return ret; + ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset); + if (ret) + return ret; + } if (wi) - wi->is_lhs = false; + { + wi->is_lhs = false; + wi->val_only = true; + } break; case GIMPLE_CATCH: @@ -1731,7 +1745,10 @@ gimple_set_body (tree fndecl, gimple_seq seq) } -/* Return the body of GIMPLE statements for function FN. */ +/* Return the body of GIMPLE statements for function FN. After the + CFG pass, the function body doesn't exist anymore because it has + been split up into basic blocks. In this case, it returns + NULL. */ gimple_seq gimple_body (tree fndecl) @@ -2535,15 +2552,6 @@ const unsigned char gimple_rhs_class_table[] = { /* Validation of GIMPLE expressions. */ -/* Return true if OP is an acceptable tree node to be used as a GIMPLE - operand. */ - -bool -is_gimple_operand (const_tree op) -{ - return op && get_gimple_rhs_class (TREE_CODE (op)) == GIMPLE_SINGLE_RHS; -} - /* Returns true iff T is a valid RHS for an assignment to a renamed user -- or front-end generated artificial -- variable. */ @@ -2595,7 +2603,8 @@ is_gimple_condexpr (tree t) bool is_gimple_addressable (tree t) { - return (is_gimple_id (t) || handled_component_p (t) || INDIRECT_REF_P (t)); + return (is_gimple_id (t) || handled_component_p (t) + || TREE_CODE (t) == MEM_REF); } /* Return true if T is a valid gimple constant. */ @@ -2646,7 +2655,7 @@ is_gimple_address (const_tree t) op = TREE_OPERAND (op, 0); } - if (CONSTANT_CLASS_P (op) || INDIRECT_REF_P (op)) + if (CONSTANT_CLASS_P (op) || TREE_CODE (op) == MEM_REF) return true; switch (TREE_CODE (op)) @@ -2706,8 +2715,18 @@ is_gimple_invariant_address (const_tree t) return false; op = strip_invariant_refs (TREE_OPERAND (t, 0)); + if (!op) + return false; - return op && (CONSTANT_CLASS_P (op) || decl_address_invariant_p (op)); + if (TREE_CODE (op) == MEM_REF) + { + const_tree op0 = TREE_OPERAND (op, 0); + return (TREE_CODE (op0) == ADDR_EXPR + && (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)) + || decl_address_invariant_p (TREE_OPERAND (op0, 0)))); + } + + return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op); } /* Return true if T is a gimple invariant address at IPA level @@ -2924,7 +2943,7 @@ is_gimple_min_lval (tree t) { if (!(t = CONST_CAST_TREE (strip_invariant_refs (t)))) return false; - return (is_gimple_id (t) || TREE_CODE (t) == INDIRECT_REF); + return (is_gimple_id (t) || TREE_CODE (t) == MEM_REF); } /* Return true if T is a typecast operation. */ @@ -2944,6 +2963,18 @@ is_gimple_call_addr (tree t) return (TREE_CODE (t) == OBJ_TYPE_REF || is_gimple_val (t)); } +/* Return true if T is a valid address operand of a MEM_REF. */ + +bool +is_gimple_mem_ref_addr (tree t) +{ + return (is_gimple_reg (t) + || TREE_CODE (t) == INTEGER_CST + || (TREE_CODE (t) == ADDR_EXPR + && (CONSTANT_CLASS_P (TREE_OPERAND (t, 0)) + || decl_address_invariant_p (TREE_OPERAND (t, 0))))); +} + /* If T makes a function call, return the corresponding CALL_EXPR operand. Otherwise, return NULL_TREE. */ @@ -2975,10 +3006,15 @@ get_base_address (tree t) while (handled_component_p (t)) t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == MEM_REF + && TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR) + t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); + if (SSA_VAR_P (t) || TREE_CODE (t) == STRING_CST || TREE_CODE (t) == CONSTRUCTOR - || INDIRECT_REF_P (t)) + || INDIRECT_REF_P (t) + || TREE_CODE (t) == MEM_REF) return t; else return NULL_TREE; @@ -3119,23 +3155,26 @@ 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 - four possible values for SAME_P: + three possible values for SAME_P: -2: The pair (T1, T2) has just been inserted in the table. - -1: The pair (T1, T2) is currently being compared. 0: T1 and T2 are different types. 1: T1 and T2 are the same type. - This table is only used when comparing aggregate types to avoid - infinite recursion due to self-referential types. */ + 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; - int same_p; + 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); + /* Return a hash value for the type pair pointed-to by P. */ static hashval_t @@ -3186,13 +3225,32 @@ lookup_type_pair (tree t1, tree t2, htab_t *visited_p, struct obstack *ob_p) p = XOBNEW (ob_p, struct type_pair_d); p->uid1 = TYPE_UID (t1); p->uid2 = TYPE_UID (t2); - p->same_p = -2; + p->same_p[0] = -2; + p->same_p[1] = -2; *slot = (void *) p; } return p; } +/* 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; /* 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 @@ -3287,33 +3345,72 @@ gimple_compare_field_offset (tree f1, tree f2) return false; } -/* Return 1 iff T1 and T2 are structurally identical. - Otherwise, return 0. */ +/* If the type T1 and the type T2 are a complete and an incomplete + variant of the same type return true. */ -static int -gimple_types_compatible_p (tree t1, tree t2) +static bool +gimple_compatible_complete_and_incomplete_subtype_p (tree t1, tree t2) +{ + /* If one pointer points to an incomplete type variant of + the other pointed-to type they are the same. */ + if (TREE_CODE (t1) == TREE_CODE (t2) + && RECORD_OR_UNION_TYPE_P (t1) + && (!COMPLETE_TYPE_P (t1) + || !COMPLETE_TYPE_P (t2)) + && TYPE_QUALS (t1) == TYPE_QUALS (t2) + && compare_type_names_p (TYPE_MAIN_VARIANT (t1), + TYPE_MAIN_VARIANT (t2), true)) + return true; + return false; +} + +static bool +gimple_types_compatible_p_1 (tree, tree, enum gtc_mode, 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, enum gtc_mode mode, + struct sccs *state, + VEC(type_pair_t, heap) **sccstack, + struct pointer_map_t *sccstate, + struct obstack *sccstate_obstack) { - type_pair_t p = NULL; + struct sccs *cstate = NULL; + type_pair_t p; + void **slot; /* Check first for the obvious case of pointer identity. */ if (t1 == t2) - return 1; + return true; /* Check that we have two types to compare. */ if (t1 == NULL_TREE || t2 == NULL_TREE) - return 0; + return false; + + /* If the types have been previously registered and found equal + they still are. */ + if (TYPE_CANONICAL (t1) + && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)) + return true; /* Can't be the same type if the types don't have the same code. */ if (TREE_CODE (t1) != TREE_CODE (t2)) - return 0; + return false; /* Can't be the same type if they have different CV qualifiers. */ if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) - return 0; + return false; /* Void types are always the same. */ if (TREE_CODE (t1) == VOID_TYPE) - return 1; + return true; /* Do some simple checks before doing three hashtable queries. */ if (INTEGRAL_TYPE_P (t1) @@ -3329,22 +3426,17 @@ gimple_types_compatible_p (tree t1, tree t2) || TYPE_PRECISION (t1) != TYPE_PRECISION (t2) || TYPE_MODE (t1) != TYPE_MODE (t2) || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) - return 0; + return false; if (TREE_CODE (t1) == INTEGER_TYPE && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2) || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))) - return 0; + 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 1; - - /* Perform cheap tail-recursion for vector and complex types. */ - if (TREE_CODE (t1) == VECTOR_TYPE - || TREE_CODE (t1) == COMPLEX_TYPE) - return gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)); + return true; /* For integral types fall thru to more complex checks. */ } @@ -3354,35 +3446,70 @@ gimple_types_compatible_p (tree t1, tree t2) /* 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 0; + return false; } /* 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 0; + 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. */ + /* Allocate a new cache entry for this comparison. */ p = lookup_type_pair (t1, t2, >c_visited, >c_ob); - if (p->same_p == 0 || p->same_p == 1) + if (p->same_p[mode] == 0 || p->same_p[mode] == 1) { /* We have already decided whether T1 and T2 are the same, return the cached result. */ - return p->same_p == 1; + return p->same_p[mode] == 1; } - else if (p->same_p == -1) + + if ((slot = pointer_map_contains (sccstate, p)) != NULL) + cstate = (struct sccs *)*slot; + if (!cstate) { - /* We are currently comparing this pair of types, assume - that they are the same and let the caller decide. */ - return 1; + bool res; + /* Not yet visited. DFS recurse. */ + res = gimple_types_compatible_p_1 (t1, t2, mode, p, + sccstack, sccstate, sccstate_obstack); + if (!cstate) + cstate = (struct sccs *)* pointer_map_contains (sccstate, p); + 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, return its state. Otherwise we will + ignore this pair and assume equality. */ + if (!cstate->on_sccstack) + return res; } + if (cstate->dfsnum < state->dfsnum + && cstate->on_sccstack) + state->low = MIN (cstate->dfsnum, state->low); + + /* We are part of our parents SCC, skip this entry and return true. */ + return true; +} - gcc_assert (p->same_p == -2); +/* Worker for gimple_types_compatible. + SCCSTACK, SCCSTATE and SCCSTATE_OBSTACK are state for the DFS walk done. */ - /* Mark the (T1, T2) comparison in progress. */ - p->same_p = -1; +static bool +gimple_types_compatible_p_1 (tree t1, tree t2, enum gtc_mode mode, + 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[mode] == -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; /* If their attributes are not the same they can't be the same type. */ if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2))) @@ -3391,10 +3518,18 @@ gimple_types_compatible_p (tree t1, tree t2) /* Do type-specific comparisons. */ switch (TREE_CODE (t1)) { + case VECTOR_TYPE: + case COMPLEX_TYPE: + if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), mode, + 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 (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)) + if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), mode, + state, sccstack, sccstate, sccstate_obstack) || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2) || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2)) goto different_types; @@ -3442,8 +3577,8 @@ gimple_types_compatible_p (tree t1, tree t2) case METHOD_TYPE: /* Method types should belong to the same class. */ - if (!gimple_types_compatible_p (TYPE_METHOD_BASETYPE (t1), - TYPE_METHOD_BASETYPE (t2))) + if (!gtc_visit (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2), + mode, state, sccstack, sccstate, sccstate_obstack)) goto different_types; /* Fallthru */ @@ -3451,40 +3586,47 @@ gimple_types_compatible_p (tree t1, tree t2) case FUNCTION_TYPE: /* Function types are the same if the return type and arguments types are the same. */ - if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) + if ((mode != GTC_DIAG + || !gimple_compatible_complete_and_incomplete_subtype_p + (TREE_TYPE (t1), TREE_TYPE (t2))) + && !gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), mode, + state, sccstack, sccstate, sccstate_obstack)) + goto different_types; + + if (!targetm.comp_type_attributes (t1, t2)) goto different_types; + + if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)) + goto same_types; else { - if (!targetm.comp_type_attributes (t1, t2)) - goto different_types; + tree parms1, parms2; - if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)) - goto same_types; - else + for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2); + parms1 && parms2; + parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2)) { - 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 (!gimple_types_compatible_p (TREE_VALUE (parms1), - TREE_VALUE (parms2))) - goto different_types; - } - - if (parms1 || parms2) + if ((mode == GTC_MERGE + || !gimple_compatible_complete_and_incomplete_subtype_p + (TREE_VALUE (parms1), TREE_VALUE (parms2))) + && !gtc_visit (TREE_VALUE (parms1), TREE_VALUE (parms2), mode, + state, sccstack, sccstate, sccstate_obstack)) goto different_types; - - goto same_types; } + + if (parms1 || parms2) + goto different_types; + + goto same_types; } case OFFSET_TYPE: { - if (!gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)) - || !gimple_types_compatible_p (TYPE_OFFSET_BASETYPE (t1), - TYPE_OFFSET_BASETYPE (t2))) + if (!gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), mode, + state, sccstack, sccstate, sccstate_obstack) + || !gtc_visit (TYPE_OFFSET_BASETYPE (t1), + TYPE_OFFSET_BASETYPE (t2), mode, + state, sccstack, sccstate, sccstate_obstack)) goto different_types; goto same_types; @@ -3500,34 +3642,15 @@ gimple_types_compatible_p (tree t1, tree t2) /* If one pointer points to an incomplete type variant of the other pointed-to type they are the same. */ - if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)) - && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t1)) - && (!COMPLETE_TYPE_P (TREE_TYPE (t1)) - || !COMPLETE_TYPE_P (TREE_TYPE (t2))) - && TYPE_QUALS (TREE_TYPE (t1)) == TYPE_QUALS (TREE_TYPE (t2)) - && compare_type_names_p (TYPE_MAIN_VARIANT (TREE_TYPE (t1)), - TYPE_MAIN_VARIANT (TREE_TYPE (t2)), true)) - { - /* Replace the pointed-to incomplete type with the - complete one. - ??? This simple name-based merging causes at least some - of the ICEs in canonicalizing FIELD_DECLs during stmt - read. For example in GCC we have two different struct deps - and we mismatch the use in struct cpp_reader in sched-int.h - vs. mkdeps.c. Of course the whole exercise is for TBAA - with structs which contain pointers to incomplete types - in one unit and to complete ones in another. So we - probably should merge these types only with more context. */ - if (COMPLETE_TYPE_P (TREE_TYPE (t2))) - TREE_TYPE (t1) = TREE_TYPE (t2); - else - TREE_TYPE (t2) = TREE_TYPE (t1); - goto same_types; - } + if (mode == GTC_DIAG + && gimple_compatible_complete_and_incomplete_subtype_p + (TREE_TYPE (t1), TREE_TYPE (t2))) + goto same_types; /* Otherwise, pointer and reference types are the same if the pointed-to types are the same. */ - if (gimple_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) + if (gtc_visit (TREE_TYPE (t1), TREE_TYPE (t2), mode, + state, sccstack, sccstate, sccstate_obstack)) goto same_types; goto different_types; @@ -3622,8 +3745,8 @@ gimple_types_compatible_p (tree t1, tree t2) if (DECL_NAME (f1) != DECL_NAME (f2) || DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2) || !gimple_compare_field_offset (f1, f2) - || !gimple_types_compatible_p (TREE_TYPE (f1), - TREE_TYPE (f2))) + || !gtc_visit (TREE_TYPE (f1), TREE_TYPE (f2), mode, + state, sccstack, sccstate, sccstate_obstack)) goto different_types; } @@ -3641,32 +3764,141 @@ gimple_types_compatible_p (tree t1, tree t2) /* Common exit path for types that are not compatible. */ different_types: - p->same_p = 0; - return 0; + state->u.same_p = 0; + goto pop; /* Common exit path for types that are compatible. */ same_types: - p->same_p = 1; - return 1; -} + state->u.same_p = 1; + goto pop; +pop: + if (state->low == state->dfsnum) + { + type_pair_t x; + /* Pop off the SCC and set its cache values. */ + 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[mode] = cstate->u.same_p; + } + while (x != p); + } + return state->u.same_p; +} -/* 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. */ +/* 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. */ -struct sccs +bool +gimple_types_compatible_p (tree t1, tree t2, enum gtc_mode mode) { - unsigned int dfsnum; - unsigned int low; - bool on_sccstack; - hashval_t hash; -}; + VEC(type_pair_t, heap) *sccstack = NULL; + struct pointer_map_t *sccstate; + struct obstack sccstate_obstack; + type_pair_t p = NULL; + bool res; + + /* 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; + + /* If the types have been previously registered and found equal + they still are. */ + if (TYPE_CANONICAL (t1) + && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)) + return true; + + /* 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; + + /* Void types are always the same. */ + if (TREE_CODE (t1) == VOID_TYPE) + return true; + + /* 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) + { + /* Can't be the same type if they have different alignment, + sign, precision or mode. */ + if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2) + || TYPE_PRECISION (t1) != TYPE_PRECISION (t2) + || TYPE_MODE (t1) != TYPE_MODE (t2) + || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) + return false; + + if (TREE_CODE (t1) == INTEGER_TYPE + && (TYPE_IS_SIZETYPE (t1) != TYPE_IS_SIZETYPE (t2) + || 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 integral types fall thru to more complex checks. */ + } + + else if (AGGREGATE_TYPE_P (t1) || POINTER_TYPE_P (t1)) + { + /* 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; + } + + /* 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, >c_visited, >c_ob); + if (p->same_p[mode] == 0 || p->same_p[mode] == 1) + { + /* We have already decided whether T1 and T2 are the + same, return the cached result. */ + return p->same_p[mode] == 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, mode, p, + &sccstack, sccstate, &sccstate_obstack); + VEC_free (type_pair_t, heap, sccstack); + pointer_map_destroy (sccstate); + obstack_free (&sccstate_obstack, NULL); + + return res; +} -static unsigned int next_dfs_num; static hashval_t iterative_hash_gimple_type (tree, hashval_t, VEC(tree, heap) **, @@ -3844,13 +4076,29 @@ iterative_hash_gimple_type (tree type, hashval_t val, v = visit (TYPE_METHOD_BASETYPE (type), state, v, sccstack, sccstate, sccstate_obstack); - v = visit (TREE_TYPE (type), state, v, - sccstack, sccstate, sccstate_obstack); + /* 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); + } + else + 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); + /* For argument types allow mismatch in completeness. */ + if (RECORD_OR_UNION_TYPE_P (TREE_VALUE (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); + } + else + v = visit (TREE_VALUE (p), state, v, + sccstack, sccstate, sccstate_obstack); na++; } @@ -3878,7 +4126,7 @@ iterative_hash_gimple_type (tree type, hashval_t val, } /* Record hash for us. */ - state->hash = v; + state->u.hash = v; /* See if we found an SCC. */ if (state->low == state->dfsnum) @@ -3894,7 +4142,7 @@ iterative_hash_gimple_type (tree type, hashval_t val, cstate = (struct sccs *)*pointer_map_contains (sccstate, x); cstate->on_sccstack = false; slot = pointer_map_insert (type_hash_cache, x); - *slot = (void *) (size_t) cstate->hash; + *slot = (void *) (size_t) cstate->u.hash; } while (x != type); } @@ -3948,7 +4196,8 @@ 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)); + return gimple_types_compatible_p (CONST_CAST_TREE (t1), + CONST_CAST_TREE (t2), GTC_MERGE); } @@ -4418,7 +4667,7 @@ count_ptr_derefs (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; } - if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr) + if (TREE_CODE (*tp) == MEM_REF && TREE_OPERAND (*tp, 0) == count_p->ptr) { if (wi_p->is_lhs) count_p->num_stores++; @@ -4491,6 +4740,7 @@ get_base_loadstore (tree op) op = TREE_OPERAND (op, 0); if (DECL_P (op) || INDIRECT_REF_P (op) + || TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF) return op; return NULL_TREE; |