diff options
author | Diego Novillo <dnovillo@google.com> | 2009-03-10 15:24:46 +0000 |
---|---|---|
committer | Diego Novillo <dnovillo@google.com> | 2009-03-10 15:24:46 +0000 |
commit | 50d00be3ce00f27ca6f51c48c684ca8c7490e841 (patch) | |
tree | 197efd2fa202804dea7abd3788d8c79890846e93 /gcc | |
parent | 59542774f84839cf9bd3c73c03bebd5657aeae28 (diff) |
2009-03-10 Diego Novillo <dnovillo@google.com>
Revert:
2009-03-09 Diego Novillo <dnovillo@google.com>
* tree.c (free_lang_data_in_type): Remove all variants
except the main variant of TYPE.
* gimple.c (struct type_pair_d): Define.
(type_pair_t): Define.
(type_pair_hash): New.
(type_pair_eq): New.
(lookup_type_pair): New.
(gimple_compare_types): Factor out of gimple_types_compatible_p.
Compare type sizes, alignment, precision, mode and sign.
Compare values for enumeral types.
Compare all fields of structures and unions.
Fix comparison of TYPE_QUALS.
Compare TYPE_IS_SIZETYPE for integer types.
(gimple_types_compatible_p): Call gimple_compare_types.
(gimple_same_type_p): Remove. Update all callers.
* gimple.h (gimple_same_type_p): Remove.
2009-03-10 Diego Novillo <dnovillo@google.com>
Revert:
2009-03-09 Simon Baldwin <simonb@google.com>
* g++.dg/lto/20090302_0.C: New.
* g++.dg/lto/20090302_1.C: New.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lto@144749 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog.lto | 23 | ||||
-rw-r--r-- | gcc/gimple.c | 368 | ||||
-rw-r--r-- | gcc/gimple.h | 1 | ||||
-rw-r--r-- | gcc/lto-symtab.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog.lto | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lto/20090302_0.C | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lto/20090302_1.C | 7 | ||||
-rw-r--r-- | gcc/tree.c | 27 |
8 files changed, 171 insertions, 277 deletions
diff --git a/gcc/ChangeLog.lto b/gcc/ChangeLog.lto index 92e29d69fd5..10fc8afdef3 100644 --- a/gcc/ChangeLog.lto +++ b/gcc/ChangeLog.lto @@ -1,3 +1,26 @@ +2009-03-10 Diego Novillo <dnovillo@google.com> + + Revert: + + 2009-03-09 Diego Novillo <dnovillo@google.com> + + * tree.c (free_lang_data_in_type): Remove all variants + except the main variant of TYPE. + * gimple.c (struct type_pair_d): Define. + (type_pair_t): Define. + (type_pair_hash): New. + (type_pair_eq): New. + (lookup_type_pair): New. + (gimple_compare_types): Factor out of gimple_types_compatible_p. + Compare type sizes, alignment, precision, mode and sign. + Compare values for enumeral types. + Compare all fields of structures and unions. + Fix comparison of TYPE_QUALS. + Compare TYPE_IS_SIZETYPE for integer types. + (gimple_types_compatible_p): Call gimple_compare_types. + (gimple_same_type_p): Remove. Update all callers. + * gimple.h (gimple_same_type_p): Remove. + 2009-03-10 Simon Baldwin <simonb@google.com> * lto-opts.c (lto_read_file_options): Corrected function comment. diff --git a/gcc/gimple.c b/gcc/gimple.c index 0a5563537e7..e28a7fdd374 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -3193,169 +3193,102 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip) } -/* Structure used to maintain a cache of some type pairs compared by - gimple_compare_types when comparing aggregate types. There are - four 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. */ -struct type_pair_d -{ - tree t1; - tree t2; - int same_p; -}; -typedef struct type_pair_d *type_pair_t; - -/* Return a hash value for the type pair pointed-to by P. */ - -static hashval_t -type_pair_hash (const void *p) -{ - const struct type_pair_d *pair = (const struct type_pair_d *) p; - hashval_t val = iterative_hash_hashval_t (htab_hash_pointer (pair->t1), 0); - return iterative_hash_hashval_t (htab_hash_pointer (pair->t2), val); -} - -/* Compare two type pairs pointed-to by P1 and P2. */ +/* Return 1 if TYPE1 and TYPE2 are structurally compatible. */ -static int -type_pair_eq (const void *p1, const void *p2) +int +gimple_types_compatible_p (tree type1, tree type2) { - const struct type_pair_d *pair1 = (const struct type_pair_d *) p1; - const struct type_pair_d *pair2 = (const struct type_pair_d *) p2; - return (pair1->t1 == pair2->t1 && pair1->t2 == pair2->t2); -} - + /* Types are trivially compatible with themselves. */ + if (type1 == type2) + return 1; -/* Lookup the pair of types T1 and T2 in *VISITED_P. Insert a new - entry if none existed. */ + /* Only types with the same code can be compatible. */ + if (TREE_CODE (type1) != TREE_CODE (type2)) + return 0; -static type_pair_t -lookup_type_pair (tree t1, tree t2, htab_t *visited_p) -{ - struct type_pair_d pair; - type_pair_t p; - void **slot; + /* If the main variants or their canonical type are the same, then + they are compatible. */ + if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2) + || TYPE_CANONICAL (type1) == TYPE_CANONICAL (type2)) + return 1; - if (*visited_p == NULL) - *visited_p = htab_create (13, type_pair_hash, type_pair_eq, free); + /* In the case of aggregates, check structural equality. Note that + at this point, TYPE1 and TYPE2 are guaranteed to have the same + code already. */ + if (TREE_CODE (type1) == RECORD_TYPE + || TREE_CODE (type1) == UNION_TYPE + || TREE_CODE (type1) == QUAL_UNION_TYPE) + { + tree f1, f2; - pair.t1 = t1; - pair.t2 = t2; - pair.same_p = -2; - slot = htab_find_slot (*visited_p, &pair, INSERT); + for (f1 = TYPE_FIELDS (type1), f2 = TYPE_FIELDS (type2); + f1 && f2; + f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) + if (!gimple_types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2))) + return 0; - if (*slot) - p = *((type_pair_t *) slot); - else - { - p = XCNEW (struct type_pair_d); - p->t1 = t1; - p->t2 = t2; - p->same_p = -2; - *slot = (void *) p; + /* If one aggregate is bigger than the other, then they are not + compatible. */ + return f1 || f2 ? 0 : 1; } - return p; + /* In any other case, the two types are not compatible. */ + return 0; } -/* Recursive helper for gimple_types_compatible_p. Return 1 iff T1 - and T2 are structurally identical. Otherwise, return 0. - VISITED_P points to a hash table of type pairs that have been - visited while comparing aggregate types. This prevents infinite - recursion when comparing aggregates with self-referential fields. */ +/* Returns true iff T1 and T2 are the same type. */ -static int -gimple_compare_types (tree t1, tree t2, htab_t *visited_p) +bool +gimple_same_type_p (tree t1, tree t2) { /* 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; /* Can't be the same type if the types don't have the same code. */ if (TREE_CODE (t1) != TREE_CODE (t2)) - return 0; - - /* Void types are always the same. */ - if (TREE_CODE (t1) == VOID_TYPE) - return 1; - - /* Can't be the same type if they have different size, alignment, - sign, precision or mode. Note that from now on, comparisons - between *_CST nodes must be done using tree_int_cst_equal because - we cannot assume that constants from T1 and T2 will be shared - since T1 and T2 are distinct pointers. */ - if (!tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)) - || !tree_int_cst_equal (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2)) - || 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 0; + return false; /* Can't be the same type if they have different CV qualifiers. */ - if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) - return 0; + 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 0; - - /* For numerical types, the bounds must coincide. */ - if (INTEGRAL_TYPE_P (t1) - || SCALAR_FLOAT_TYPE_P (t1) - || FIXED_POINT_TYPE_P (t1)) - { - /* If either type has a minimum value, the other type must have - the same. */ - if (TYPE_MIN_VALUE (t1) && TYPE_MIN_VALUE (t2)) - { - if (!tree_int_cst_equal (TYPE_MIN_VALUE (t1), TYPE_MIN_VALUE (t2))) - return 0; - } - else if (TYPE_MIN_VALUE (t1) || TYPE_MIN_VALUE (t2)) - return 0; - - /* Likewise, if either type has a maximum value, the other type - must have the same. */ - if (TYPE_MAX_VALUE (t1) && TYPE_MAX_VALUE (t2)) - { - if (!tree_int_cst_equal (TYPE_MAX_VALUE (t1), TYPE_MAX_VALUE (t2))) - return 0; - } - else if (TYPE_MAX_VALUE (t1) || TYPE_MAX_VALUE (t2)) - return 0; - } + return false; - /* Do type-specific comparisons. */ switch (TREE_CODE (t1)) { + case VOID_TYPE: + /* Void types are the same in all translation units. */ + return true; + case INTEGER_TYPE: case BOOLEAN_TYPE: - return (TYPE_IS_SIZETYPE (t1) == TYPE_IS_SIZETYPE (t2) + /* 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: - /* We've checked every other important attribute already. */ - return 1; + /* 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_compare_types (TREE_TYPE (t1), TREE_TYPE (t2), visited_p) + if (!gimple_same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) - return 0; + return false; else { tree i1 = TYPE_DOMAIN (t1); @@ -3373,19 +3306,20 @@ gimple_compare_types (tree t1, tree t2, htab_t *visited_p) tree max2 = TYPE_MAX_VALUE (i2); /* If the array types both have unspecified bounds, then - MAX{1,2} will be NULL_TREE. */ + MAX_{1,2} will be NULL_TREE. */ if (min1 && min2 && !max1 && !max2) - return (integer_zerop (min1) && integer_zerop (min2)); + return (integer_zerop (min1) + && integer_zerop (min2)); /* Otherwise, we need the bounds to be fully specified. */ if (!min1 || !min2 || !max1 || !max2) - return 0; + 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 0; + || 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 @@ -3394,11 +3328,11 @@ gimple_compare_types (tree t1, tree t2, htab_t *visited_p) tree nelts2 = array_type_nelts (t2); if (!nelts1 || !nelts2) - return 0; + return false; if (TREE_CODE (nelts1) != INTEGER_CST || TREE_CODE (nelts2) != INTEGER_CST) - return 0; + return false; return tree_int_cst_equal (nelts1, nelts2); } @@ -3408,22 +3342,21 @@ gimple_compare_types (tree t1, tree t2, htab_t *visited_p) case FUNCTION_TYPE: /* Function types are the same if the return type and arguments types are the same. */ - if (!gimple_compare_types (TREE_TYPE (t1), TREE_TYPE (t2), visited_p)) - return 0; + 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 1; + return true; else { while (parms1 && parms2) { - if (!gimple_compare_types (TREE_VALUE (parms1), - TREE_VALUE (parms2), - visited_p)) - return 0; + if (!gimple_same_type_p (TREE_VALUE (parms1), + TREE_VALUE (parms2))) + return false; parms1 = TREE_CHAIN (parms1); parms2 = TREE_CHAIN (parms2); } @@ -3433,130 +3366,61 @@ gimple_compare_types (tree t1, tree t2, htab_t *visited_p) 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)) - return 0; - - /* Otherwise, pointer and reference types are the same if the - pointed-to types are the same. */ - return gimple_compare_types (TREE_TYPE (t1), TREE_TYPE (t2), - visited_p); - } + /* 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: - { - /* For enumeral types, all the values must be the same. */ - tree v1, v2; - - 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) - return 0; - } - - /* If one enumeration has more values than the other, they - are not the same. */ - return v1 || v2 ? 0 : 1; - } - case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: - { - /* For aggregate types, all the fields must be the same. - Use *VISITED_P to mark pairs of fields visited to - avoid infinite loops due to self-referential types. */ - tree f1, f2; - type_pair_t p; - - p = lookup_type_pair (t1, t2, visited_p); - if (p->same_p == 0 || p->same_p == 1) - { - /* We have already decided whether T1 and T2 are the - same, return the cached result. */ - return p->same_p == 1; - } - else if (p->same_p == -1) - { - /* We are currently comparing this pair of types, assume - that they are the same and let the caller decide. */ - return 1; - } - - gcc_assert (p->same_p == -2); + /* 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); - /* Mark the (T1, T2) comparison in progress. */ - p->same_p = -1; + if (TREE_CODE (name2) == TYPE_DECL) + { + name2 = DECL_NAME (name2); + if (!name2) + return false; + } + gcc_assert (TREE_CODE (name2) == IDENTIFIER_NODE); - for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); - f1 && f2; - f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) - { - /* The fields must have the same name, offset and type. */ - if (DECL_NAME (f1) != DECL_NAME (f2) - || !tree_int_cst_equal (DECL_FIELD_OFFSET (f1), - DECL_FIELD_OFFSET (f2)) - || !gimple_compare_types (TREE_TYPE (f1), - TREE_TYPE (f2), - visited_p)) - { - p->same_p = 0; - return 0; - } - } + /* Identifiers can be compared with pointer equality rather + than a string comparison. */ + if (name1 == name2) + return true; - if (f1 == NULL && f2 == NULL) - { - /* If we reached the end of both aggregates, T1 and T2 - are the same. */ - p->same_p = 1; - return 1; - } - else - { - /* Otherwise, they are different. */ - p->same_p = 0; - return 0; - } - } + /* 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: - break; + return false; } - - /* The types are different. */ - return 0; } - -/* Return 1 iff T1 and T2 are the structurally identical. Otherwise, - return 0. */ - -int -gimple_types_compatible_p (tree t1, tree t2) -{ - int same_p; - htab_t visited = NULL; - - same_p = gimple_compare_types (t1, t2, &visited); - - if (visited) - htab_delete (visited); - - return same_p; -} - #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 193e1904077..e35d23d2e4d 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -182,7 +182,7 @@ lto_merge_types (tree type_1, tree type_2) && TREE_CODE (type_2) == ARRAY_TYPE && !TYPE_ATTRIBUTES (type_1) && !TYPE_ATTRIBUTES (type_2) - && gimple_types_compatible_p (TREE_TYPE (type_1), TREE_TYPE (type_2))) + && gimple_same_type_p (TREE_TYPE (type_1), TREE_TYPE (type_2))) { lto_merge_qualifiers (type_1, type_2); @@ -255,7 +255,7 @@ lto_symtab_compatible (tree old_decl, tree new_decl) } } - if (!gimple_types_compatible_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/testsuite/ChangeLog.lto b/gcc/testsuite/ChangeLog.lto index ba5ffaad8c6..bb5e37f8217 100644 --- a/gcc/testsuite/ChangeLog.lto +++ b/gcc/testsuite/ChangeLog.lto @@ -1,3 +1,12 @@ +2009-03-10 Diego Novillo <dnovillo@google.com> + + Revert: + + 2009-03-09 Simon Baldwin <simonb@google.com> + + * g++.dg/lto/20090302_0.C: New. + * g++.dg/lto/20090302_1.C: New. + 2009-03-10 Rafael Avila de Espindola <espindola@google.com> * g++.dg/lto/20090309_0.C: New. diff --git a/gcc/testsuite/g++.dg/lto/20090302_0.C b/gcc/testsuite/g++.dg/lto/20090302_0.C deleted file mode 100644 index be754271bf7..00000000000 --- a/gcc/testsuite/g++.dg/lto/20090302_0.C +++ /dev/null @@ -1,9 +0,0 @@ -/* { dg-do "link" } */ -/* { dg-options "{-fPIC -fwhopr -shared}" } */ -struct Foo { - bool Mumble(); - static void Bar() { if (foo_->Mumble()) foo_ = 0; } - static void Baz() { Bar(); } - static Foo *foo_; -}; -void Unused() { Foo::Bar(); Foo::Baz(); } diff --git a/gcc/testsuite/g++.dg/lto/20090302_1.C b/gcc/testsuite/g++.dg/lto/20090302_1.C deleted file mode 100644 index 0ccaf3c8205..00000000000 --- a/gcc/testsuite/g++.dg/lto/20090302_1.C +++ /dev/null @@ -1,7 +0,0 @@ -struct Foo { - bool Mumble(); - static void Bar() { if (foo_->Mumble()) foo_ = 0; } - static void Baz() { Bar(); } - static Foo *foo_; -}; -Foo *Foo::foo_; diff --git a/gcc/tree.c b/gcc/tree.c index a04af015e6e..8e94d0c0a2b 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -3895,13 +3895,26 @@ free_lang_data_in_type (tree type) FIXME lto: This will break debug info generation. */ TYPE_CONTEXT (type) = NULL_TREE; - /* Remove type variants other than the main variant. This is both - wasteful and it may introduce infinite loops when the types are - read from disk and merged (since the variant will be the same - type as the main variant, traversing type variants will get into - an infinite loop). */ - if (TYPE_MAIN_VARIANT (type)) - TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (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); + } + } } |