aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@google.com>2009-02-28 21:17:22 +0000
committerDiego Novillo <dnovillo@google.com>2009-02-28 21:17:22 +0000
commit92fd58f72029a569f7c90547ba160e6e662822fa (patch)
treedc1f058d8b0e2be7156e7acc9be519602624697b /gcc
parent9ea72b7cdeb7dfba591c2e7a6a65b9b35373d8f0 (diff)
* gimple.c (gimple_same_type_p): Move from lto-symtab.c.
Rename from lto_same_type_p. Update all users. Compare TYPE_QUALS and TYPE_ATTRIBUTES. * gimple.h (gimple_same_type_p): Declare. * lto-tree-in.h: Fix comment. * tree.c (free_lang_data_in_type): Remove variants that are the same gimple type as the main variant. * lto-symtab.c (lto_merge_qualifiers): Merge in both directions. (lto_merge_types): Always merge qualifiers for merged ARRAY_TYPEs. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lto@144495 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog.lto14
-rw-r--r--gcc/gimple.c187
-rw-r--r--gcc/gimple.h1
-rw-r--r--gcc/lto-symtab.c232
-rw-r--r--gcc/lto-tree-in.h2
-rw-r--r--gcc/tree.c21
6 files changed, 254 insertions, 203 deletions
diff --git a/gcc/ChangeLog.lto b/gcc/ChangeLog.lto
index 54dccdf753f..25810e23557 100644
--- a/gcc/ChangeLog.lto
+++ b/gcc/ChangeLog.lto
@@ -1,3 +1,17 @@
+2009-02-27 Diego Novillo <dnovillo@google.com>
+
+ * gimple.c (gimple_same_type_p): Move from lto-symtab.c.
+ Rename from lto_same_type_p. Update all users.
+ Compare TYPE_QUALS and TYPE_ATTRIBUTES.
+ * gimple.h (gimple_same_type_p): Declare.
+ * lto-tree-in.h: Fix comment.
+ * tree.c (free_lang_data_in_type): Remove variants that
+ are the same gimple type as the main variant.
+ * lto-symtab.c (lto_merge_qualifiers): Merge in both
+ directions.
+ (lto_merge_types): Always merge qualifiers for merged
+ ARRAY_TYPEs.
+
2009-02-24 Rafael Avila de Espindola <espindola@google.com>
* ipa.c (cgraph_remove_unreachable_nodes): Search all clones.
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 4ab5990618e..e28a7fdd374 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -3236,4 +3236,191 @@ gimple_types_compatible_p (tree type1, tree type2)
return 0;
}
+
+/* Returns true iff T1 and T2 are the same type. */
+
+bool
+gimple_same_type_p (tree t1, tree t2)
+{
+ /* 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 (t1))
+ return false;
+
+ /* If their attributes are not the same they can't be the same type. */
+ if (!attribute_list_equal (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2)))
+ return false;
+
+ switch (TREE_CODE (t1))
+ {
+ case VOID_TYPE:
+ /* Void types are the same in all translation units. */
+ return true;
+
+ case INTEGER_TYPE:
+ case BOOLEAN_TYPE:
+ /* Corresponding integral types are the same. */
+ return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && TYPE_UNSIGNED (t1) == TYPE_UNSIGNED (t2)
+ && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+ && TYPE_ALIGN (t1) == TYPE_ALIGN (t2)
+ && TYPE_STRING_FLAG (t1) == TYPE_STRING_FLAG (t2));
+
+ case REAL_TYPE:
+ /* Corresponding float types are the same. */
+ return (TYPE_PRECISION (t1) == TYPE_PRECISION (t2)
+ && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+ && TYPE_ALIGN (t1) == TYPE_ALIGN (t2));
+
+ 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_same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+ || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
+ return false;
+ 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 || !i2)
+ return (!i1 && !i2);
+ 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);
+
+ /* If the array types both have unspecified bounds, then
+ MAX_{1,2} will be NULL_TREE. */
+ if (min1 && min2 && !max1 && !max2)
+ return (integer_zerop (min1)
+ && integer_zerop (min2));
+
+ /* Otherwise, we need the bounds to be fully
+ specified. */
+ if (!min1 || !min2 || !max1 || !max2)
+ return false;
+ else if (TREE_CODE (min1) != INTEGER_CST
+ || TREE_CODE (min2) != INTEGER_CST
+ || TREE_CODE (max1) != INTEGER_CST
+ || TREE_CODE (max2) != INTEGER_CST)
+ return false;
+ else if (tree_int_cst_equal (min1, min2))
+ return tree_int_cst_equal (max1, max2);
+ else
+ {
+ tree nelts1 = array_type_nelts (t1);
+ tree nelts2 = array_type_nelts (t2);
+
+ if (!nelts1 || !nelts2)
+ return false;
+
+ if (TREE_CODE (nelts1) != INTEGER_CST
+ || TREE_CODE (nelts2) != INTEGER_CST)
+ return false;
+
+ return tree_int_cst_equal (nelts1, nelts2);
+ }
+ }
+ }
+
+ case FUNCTION_TYPE:
+ /* Function types are the same if the return type and arguments types
+ are the same. */
+ if (!gimple_same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ return false;
+ else
+ {
+ tree parms1 = TYPE_ARG_TYPES (t1);
+ tree parms2 = TYPE_ARG_TYPES (t2);
+ if (parms1 == parms2)
+ return true;
+ else
+ {
+ while (parms1 && parms2)
+ {
+ if (!gimple_same_type_p (TREE_VALUE (parms1),
+ TREE_VALUE (parms2)))
+ return false;
+ parms1 = TREE_CHAIN (parms1);
+ parms2 = TREE_CHAIN (parms2);
+ }
+ return !parms1 && !parms2;
+ }
+ }
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ /* Pointer and reference types are the same if the pointed-to types are
+ the same. */
+ return gimple_same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
+
+ case ENUMERAL_TYPE:
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ /* Enumeration and class types are the same if they have the same
+ name. */
+ {
+ tree variant1 = TYPE_MAIN_VARIANT (t1);
+ tree variant2 = TYPE_MAIN_VARIANT (t2);
+ tree name1 = TYPE_NAME (t1);
+ tree name2 = TYPE_NAME (t2);
+ if (!name1 || !name2)
+ /* Presumably, anonymous types are all unique. */
+ return false;
+
+ if (TREE_CODE (name1) == TYPE_DECL)
+ {
+ name1 = DECL_NAME (name1);
+ if (!name1)
+ return false;
+ }
+ gcc_assert (TREE_CODE (name1) == IDENTIFIER_NODE);
+
+ if (TREE_CODE (name2) == TYPE_DECL)
+ {
+ name2 = DECL_NAME (name2);
+ if (!name2)
+ return false;
+ }
+ gcc_assert (TREE_CODE (name2) == IDENTIFIER_NODE);
+
+ /* Identifiers can be compared with pointer equality rather
+ than a string comparison. */
+ if (name1 == name2)
+ return true;
+
+ /* If either type has a variant type, compare that. This finds
+ the case where a struct is typedef'ed in one module but referred
+ to as 'struct foo' in the other; here, the main type for one is
+ 'foo', and for the other 'foo_t', but the variants have the same
+ name 'foo'. */
+ if (variant1 != t1 || variant2 != t2)
+ return gimple_same_type_p (variant1, variant2);
+ else
+ return false;
+ }
+
+ /* FIXME: add pointer to member types. */
+ default:
+ return false;
+ }
+}
+
#include "gt-gimple.h"
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 441c00960c2..352e453d7ef 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -916,6 +916,7 @@ extern tree get_call_expr_in (tree t);
extern void recalculate_side_effects (tree);
extern int gimple_types_compatible_p (tree, tree);
+extern bool gimple_same_type_p (tree, tree);
/* In gimplify.c */
extern tree create_tmp_var_raw (tree, const char *);
diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c
index cb7037965c6..e35d23d2e4d 100644
--- a/gcc/lto-symtab.c
+++ b/gcc/lto-symtab.c
@@ -143,201 +143,31 @@ lto_symtab_maybe_init_hash_tables (void)
}
}
-/* Returns true iff TYPE_1 and TYPE_2 are the same type. */
-
-static bool
-lto_same_type_p (tree type_1, tree type_2)
-{
- unsigned int code;
-
- /* Check first for the obvious case of pointer identity. */
- if (type_1 == type_2)
- return true;
-
- /* Check that we have two types to compare. */
- if (type_1 == NULL_TREE || type_2 == NULL_TREE)
- return false;
-
- /* Can't be the same type if the types don't have the same code. */
- code = TREE_CODE (type_1);
- if (code != TREE_CODE (type_2))
- return false;
-
- /* "If GNU attributes are present, types which could be the same be it not
- for their GNU attributes may in fact be different due to the use of GNU
- attributes." Hmmm. Punt on this for now and assume they're different
- if we see attributes on either type. */
- if (TYPE_ATTRIBUTES (type_1) || TYPE_ATTRIBUTES (type_2))
- return false;
-
- switch (code)
- {
- case VOID_TYPE:
- /* Void types are the same in all translation units. */
- return true;
-
- case INTEGER_TYPE:
- case BOOLEAN_TYPE:
- /* Corresponding integral types are the same. */
- return (TYPE_PRECISION (type_1) == TYPE_PRECISION (type_2)
- && TYPE_UNSIGNED (type_1) == TYPE_UNSIGNED (type_2)
- && tree_int_cst_equal (TYPE_SIZE (type_1), TYPE_SIZE (type_2))
- && TYPE_ALIGN (type_1) == TYPE_ALIGN (type_2)
- && TYPE_STRING_FLAG (type_1) == TYPE_STRING_FLAG (type_2));
-
- case REAL_TYPE:
- /* Corresponding float types are the same. */
- return (TYPE_PRECISION (type_1) == TYPE_PRECISION (type_2)
- && tree_int_cst_equal (TYPE_SIZE (type_1), TYPE_SIZE (type_2))
- && TYPE_ALIGN (type_1) == TYPE_ALIGN (type_2));
-
- case ARRAY_TYPE:
- /* Array types are the same if the element types are the same and
- the number of elements are the same. */
- if (!lto_same_type_p (TREE_TYPE (type_1), TREE_TYPE (type_2))
- || TYPE_STRING_FLAG (type_1) != TYPE_STRING_FLAG (type_2))
- return false;
- else
- {
- tree index_1 = TYPE_DOMAIN (type_1);
- tree index_2 = TYPE_DOMAIN (type_2);
- /* For an incomplete external array, the type domain can be
- NULL_TREE. Check this condition also. */
- if (!index_1 || !index_2)
- return (!index_1 && !index_2);
- else
- {
- tree min_1 = TYPE_MIN_VALUE (index_1);
- tree min_2 = TYPE_MIN_VALUE (index_2);
- tree max_1 = TYPE_MAX_VALUE (index_1);
- tree max_2 = TYPE_MAX_VALUE (index_2);
- /* If the array types both have unspecified bounds, then
- MAX_{1,2} will be NULL_TREE. */
- if (min_1 && min_2 && !max_1 && !max_2)
- return (integer_zerop (min_1)
- && integer_zerop (min_2));
- /* Otherwise, we need the bounds to be fully
- specified. */
- if (!min_1 || !min_2 || !max_1 || !max_2)
- return false;
- if (TREE_CODE (min_1) != INTEGER_CST
- || TREE_CODE (min_2) != INTEGER_CST
- || TREE_CODE (max_1) != INTEGER_CST
- || TREE_CODE (max_2) != INTEGER_CST)
- return false;
- if (tree_int_cst_equal (min_1, min_2))
- return tree_int_cst_equal (max_1, max_2);
- else
- {
- tree nelts_1 = array_type_nelts (type_1);
- tree nelts_2 = array_type_nelts (type_2);
- if (! nelts_1 || ! nelts_2)
- return false;
- if (TREE_CODE (nelts_1) != INTEGER_CST
- || TREE_CODE (nelts_2) != INTEGER_CST)
- return false;
- return tree_int_cst_equal (nelts_1, nelts_2);
- }
- }
- }
-
- case FUNCTION_TYPE:
- /* Function types are the same if the return type and arguments types
- are the same. */
- if (!lto_same_type_p (TREE_TYPE (type_1), TREE_TYPE (type_2)))
- return false;
- else
- {
- tree parms_1 = TYPE_ARG_TYPES (type_1);
- tree parms_2 = TYPE_ARG_TYPES (type_2);
- if (parms_1 == parms_2)
- return true;
- else
- {
- while (parms_1 && parms_2)
- {
- if (!lto_same_type_p (TREE_VALUE (parms_1),
- TREE_VALUE (parms_2)))
- return false;
- parms_1 = TREE_CHAIN (parms_1);
- parms_2 = TREE_CHAIN (parms_2);
- }
- return !parms_1 && !parms_2;
- }
- }
-
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- /* Pointer and reference types are the same if the pointed-to types are
- the same. */
- return lto_same_type_p (TREE_TYPE (type_1), TREE_TYPE (type_2));
-
- case ENUMERAL_TYPE:
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- /* Enumeration and class types are the same if they have the same
- name. */
- {
- tree variant_1 = TYPE_MAIN_VARIANT (type_1);
- tree variant_2 = TYPE_MAIN_VARIANT (type_2);
- tree name_1 = TYPE_NAME (type_1);
- tree name_2 = TYPE_NAME (type_2);
- if (!name_1 || !name_2)
- /* Presumably, anonymous types are all unique. */
- return false;
-
- if (TREE_CODE (name_1) == TYPE_DECL)
- {
- name_1 = DECL_NAME (name_1);
- if (! name_1)
- return false;
- }
- gcc_assert (TREE_CODE (name_1) == IDENTIFIER_NODE);
-
- if (TREE_CODE (name_2) == TYPE_DECL)
- {
- name_2 = DECL_NAME (name_2);
- if (! name_2)
- return false;
- }
- gcc_assert (TREE_CODE (name_2) == IDENTIFIER_NODE);
-
- /* Identifiers can be compared with pointer equality rather
- than a string comparison. */
- if (name_1 == name_2)
- return true;
-
- /* If either type has a variant type, compare that. This finds
- the case where a struct is typedef'ed in one module but referred
- to as 'struct foo' in the other; here, the main type for one is
- 'foo', and for the other 'foo_t', but the variants have the same
- name 'foo'. */
- if (variant_1 != type_1 || variant_2 != type_2)
- return lto_same_type_p (variant_1, variant_2);
- else
- return false;
- }
-
- /* FIXME: add pointer to member types. */
- default:
- return false;
- }
-}
-
-/* Transfer TYPE_2 qualifiers to TYPE_1 so that TYPE_1's qualifiers are
- conservatively correct with respect to optimization done before the
- merge. */
+/* Transfer qualifiers between TYPE_1 and TYPE_2 so that qualifiers
+ for both types are conservatively correct with respect to
+ optimization done before the merge. */
static void
lto_merge_qualifiers (tree type_1, tree type_2)
{
+ /* If one is volatile, the other should also be. */
if (TYPE_VOLATILE (type_2))
- TYPE_VOLATILE (type_1) = TYPE_VOLATILE (type_2);
- if (! TYPE_READONLY (type_2))
- TYPE_READONLY (type_1) = TYPE_READONLY (type_2);
- if (! TYPE_RESTRICT (type_2))
- TYPE_RESTRICT (type_1) = TYPE_RESTRICT (type_2);
+ TYPE_VOLATILE (type_1) = 1;
+ else if (TYPE_VOLATILE (type_1))
+ TYPE_VOLATILE (type_2) = 1;
+
+ /* If one type is writable, the other should also be. */
+ if (!TYPE_READONLY (type_2))
+ TYPE_READONLY (type_1) = 0;
+ else if (!TYPE_READONLY (type_1))
+ TYPE_READONLY (type_2) = 0;
+
+ /* If one type does not have the restrict qualifier, the other
+ should not have it either. */
+ if (!TYPE_RESTRICT (type_2))
+ TYPE_RESTRICT (type_1) = 0;
+ else if (!TYPE_RESTRICT (type_1))
+ TYPE_RESTRICT (type_2) = 0;
}
/* If TYPE_1 and TYPE_2 can be merged to form a common type, do it.
@@ -349,23 +179,21 @@ static tree
lto_merge_types (tree type_1, tree type_2)
{
if (TREE_CODE (type_1) == ARRAY_TYPE
- && (TREE_CODE (type_2) == ARRAY_TYPE)
- && ! TYPE_ATTRIBUTES (type_1) && ! TYPE_ATTRIBUTES (type_2)
- && (lto_same_type_p (TREE_TYPE (type_1), TREE_TYPE (type_2))))
+ && TREE_CODE (type_2) == ARRAY_TYPE
+ && !TYPE_ATTRIBUTES (type_1)
+ && !TYPE_ATTRIBUTES (type_2)
+ && gimple_same_type_p (TREE_TYPE (type_1), TREE_TYPE (type_2)))
{
+ lto_merge_qualifiers (type_1, type_2);
+
if (COMPLETE_TYPE_P (type_1) && !COMPLETE_TYPE_P (type_2))
- {
- lto_merge_qualifiers (type_1, type_2);
- return type_1;
- }
+ return type_1;
else if (COMPLETE_TYPE_P (type_2) && !COMPLETE_TYPE_P (type_1))
- {
- lto_merge_qualifiers (type_2, type_1);
- return type_2;
- }
+ return type_2;
else
return NULL_TREE;
}
+
return NULL_TREE;
}
@@ -427,7 +255,7 @@ lto_symtab_compatible (tree old_decl, tree new_decl)
}
}
- if (!lto_same_type_p (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
+ if (!gimple_same_type_p (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
{
/* Allow an array type with unspecified bounds to
be merged with an array type whose bounds are specified, so
diff --git a/gcc/lto-tree-in.h b/gcc/lto-tree-in.h
index d92ca575154..bfd1856a8a1 100644
--- a/gcc/lto-tree-in.h
+++ b/gcc/lto-tree-in.h
@@ -98,7 +98,7 @@ lto_input_constructors_and_inits (struct lto_file_decl_data* file_data,
const char *data);
-/* lto-symtab.c */
+/* In lto-symtab.c. */
/* The NEW_VAR (a VAR_DECL) has just been read with resolution RESOLUTION. If
there is an existing variable with the same name, merge the declaration for
diff --git a/gcc/tree.c b/gcc/tree.c
index 5443fa70af1..8e94d0c0a2b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -3894,6 +3894,27 @@ free_lang_data_in_type (tree type)
scoping and should not be part of the IR.
FIXME lto: This will break debug info generation. */
TYPE_CONTEXT (type) = NULL_TREE;
+
+ /* Remove type variants that are the same gimple type as the main
+ variant. This is both wasteful and it may introduce infinite
+ loops when the types are read from disk (since the variant will
+ be the same type as the main variant, traversing type variants
+ will get into an infinite loop). */
+ if (TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (type)))
+ {
+ tree main_variant = TYPE_MAIN_VARIANT (type);
+ tree *tp = &TYPE_NEXT_VARIANT (main_variant);
+
+ while (*tp)
+ {
+ /* If *TP is the same GIMPLE type as MAIN_VARIANT, then it's
+ not necessary to have it in the list of variants. */
+ if (gimple_same_type_p (*tp, main_variant))
+ *tp = TYPE_NEXT_VARIANT (*tp);
+ else
+ tp = &TYPE_NEXT_VARIANT (*tp);
+ }
+ }
}