aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r--gcc/gimple.c522
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, &gtc_visited, &gtc_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, &gtc_visited, &gtc_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;