From fb291a1ea7ed34478ee7a3c3ce7a0bd87915e79e Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Fri, 20 May 2011 09:35:03 +0000 Subject: [PATCH] gimple.c (gimple_register_type_1): Do not fiddle with main-variant or pointer-to chains. 2011-05-20 Richard Guenther * gimple.c (gimple_register_type_1): Do not fiddle with main-variant or pointer-to chains. Delay all fixup to uniquify_nodes. lto/ * lto.c (lto_ft_common): Remove pointer-to chain teardown. (lto_ft_type): Move main-variant and pointer-to chain building ... (uniquify_nodes): ... here. Compute TYPE_CANONICAL also here, in a separate final loop. From-SVN: r173938 --- gcc/ChangeLog | 6 ++ gcc/gimple.c | 83 ++------------- gcc/lto/ChangeLog | 7 ++ gcc/lto/lto.c | 251 +++++++++++++++++++++------------------------- 4 files changed, 135 insertions(+), 212 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0cdc8a54ec4..b89b3f9a0b1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-05-20 Richard Guenther + + * gimple.c (gimple_register_type_1): Do not fiddle with + main-variant or pointer-to chains. Delay all fixup to + uniquify_nodes. + 2011-05-19 Quentin Neill * config/i386/sse.md (fma4_fmsubadd): Use . diff --git a/gcc/gimple.c b/gcc/gimple.c index e30c7adaa3b..5b03e15a1fc 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -4476,7 +4476,6 @@ gimple_register_type_1 (tree t, bool registering_mv) { void **slot; gimple_type_leader_entry *leader; - tree mv_leader; /* If we registered this type before return the cached result. */ leader = &gimple_type_leader[TYPE_UID (t) % GIMPLE_TYPE_LEADER_SIZE]; @@ -4495,91 +4494,23 @@ gimple_register_type_1 (tree t, bool registering_mv) case we do not care for the main variant leader. */ if (!registering_mv && TYPE_MAIN_VARIANT (t) != t) - mv_leader = gimple_register_type_1 (TYPE_MAIN_VARIANT (t), true); - else - mv_leader = 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); - - /* Do not merge types with different addressability. */ - gcc_assert (TREE_ADDRESSABLE (t) == TREE_ADDRESSABLE (new_type)); - - /* If t is not its main variant then make t unreachable from its - main variant list. Otherwise we'd queue up a lot of duplicates - there. */ - if (t != TYPE_MAIN_VARIANT (t)) - { - tree tem = TYPE_MAIN_VARIANT (t); - while (tem && TYPE_NEXT_VARIANT (tem) != t) - tem = TYPE_NEXT_VARIANT (tem); - if (tem) - TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t); - TYPE_NEXT_VARIANT (t) = NULL_TREE; - } - - /* If we are a pointer then remove us from the pointer-to or - reference-to chain. Otherwise we'd queue up a lot of duplicates - there. */ - if (TREE_CODE (t) == POINTER_TYPE) - { - if (TYPE_POINTER_TO (TREE_TYPE (t)) == t) - TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t); - else - { - tree tem = TYPE_POINTER_TO (TREE_TYPE (t)); - while (tem && TYPE_NEXT_PTR_TO (tem) != t) - tem = TYPE_NEXT_PTR_TO (tem); - if (tem) - TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t); - } - TYPE_NEXT_PTR_TO (t) = NULL_TREE; - } - else if (TREE_CODE (t) == REFERENCE_TYPE) - { - if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t) - TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t); - else - { - tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t)); - while (tem && TYPE_NEXT_REF_TO (tem) != t) - tem = TYPE_NEXT_REF_TO (tem); - if (tem) - TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t); - } - TYPE_NEXT_REF_TO (t) = NULL_TREE; - } - leader->type = t; leader->leader = new_type; - t = new_type; - } - else - { - leader->type = t; - leader->leader = t; - /* We're the type leader. Make our TYPE_MAIN_VARIANT valid. */ - if (TYPE_MAIN_VARIANT (t) != t - && TYPE_MAIN_VARIANT (t) != mv_leader) - { - /* Remove us from our main variant list as we are not the variant - leader and the variant leader will change. */ - tree tem = TYPE_MAIN_VARIANT (t); - while (tem && TYPE_NEXT_VARIANT (tem) != t) - tem = TYPE_NEXT_VARIANT (tem); - if (tem) - TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t); - TYPE_NEXT_VARIANT (t) = NULL_TREE; - /* Adjust our main variant. Linking us into its variant list - will happen at fixup time. */ - TYPE_MAIN_VARIANT (t) = mv_leader; - } - *slot = (void *) t; + return new_type; } + /* If not, insert it to the cache and the hash. */ + leader->type = t; + leader->leader = t; + *slot = (void *) t; return t; } diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 79e0146694d..893997a6881 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,10 @@ +2011-05-20 Richard Guenther + + * lto.c (lto_ft_common): Remove pointer-to chain teardown. + (lto_ft_type): Move main-variant and pointer-to chain building ... + (uniquify_nodes): ... here. Compute TYPE_CANONICAL also here, + in a separate final loop. + 2011-05-19 Richard Guenther * lto.c (uniquify_nodes): First register all types before diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 67e080f8389..d64ba18d592 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -259,45 +259,9 @@ static void lto_fixup_types (tree); static void lto_ft_common (tree t) { - /* The following re-creates the TYPE_REFERENCE_TO and TYPE_POINTER_TO - lists. We do not stream TYPE_REFERENCE_TO, TYPE_POINTER_TO or - TYPE_NEXT_PTR_TO and TYPE_NEXT_REF_TO. - First remove us from any pointer list we are on. */ - if (TREE_CODE (t) == POINTER_TYPE) - { - if (TYPE_POINTER_TO (TREE_TYPE (t)) == t) - TYPE_POINTER_TO (TREE_TYPE (t)) = TYPE_NEXT_PTR_TO (t); - else - { - tree tem = TYPE_POINTER_TO (TREE_TYPE (t)); - while (tem && TYPE_NEXT_PTR_TO (tem) != t) - tem = TYPE_NEXT_PTR_TO (tem); - if (tem) - TYPE_NEXT_PTR_TO (tem) = TYPE_NEXT_PTR_TO (t); - } - TYPE_NEXT_PTR_TO (t) = NULL_TREE; - } - else if (TREE_CODE (t) == REFERENCE_TYPE) - { - if (TYPE_REFERENCE_TO (TREE_TYPE (t)) == t) - TYPE_REFERENCE_TO (TREE_TYPE (t)) = TYPE_NEXT_REF_TO (t); - else - { - tree tem = TYPE_REFERENCE_TO (TREE_TYPE (t)); - while (tem && TYPE_NEXT_REF_TO (tem) != t) - tem = TYPE_NEXT_REF_TO (tem); - if (tem) - TYPE_NEXT_REF_TO (tem) = TYPE_NEXT_REF_TO (t); - } - TYPE_NEXT_REF_TO (t) = NULL_TREE; - } - /* Fixup our type. */ LTO_FIXUP_TREE (TREE_TYPE (t)); - /* Second put us on the list of pointers of the new pointed-to type - if we are a main variant. This is done in lto_ft_type after - fixing up our main variant. */ LTO_FIXUP_TREE (TREE_CHAIN (t)); } @@ -374,8 +338,6 @@ lto_ft_field_decl (tree t) static void lto_ft_type (tree t) { - tree tem, mv; - lto_ft_common (t); LTO_FIXUP_TREE (TYPE_CACHED_VALUES (t)); LTO_FIXUP_TREE (TYPE_SIZE (t)); @@ -392,67 +354,6 @@ lto_ft_type (tree t) LTO_FIXUP_TREE (t->type_non_common.binfo); LTO_FIXUP_TREE (TYPE_CONTEXT (t)); - - /* Compute the canonical type of t and fix that up. From this point - there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P - and its type-based alias problems. */ - if (!TYPE_CANONICAL (t)) - { - TYPE_CANONICAL (t) = gimple_register_canonical_type (t); - LTO_FIXUP_TREE (TYPE_CANONICAL (t)); - } - - /* The following re-creates proper variant lists while fixing up - the variant leaders. We do not stream TYPE_NEXT_VARIANT so the - variant list state before fixup is broken. */ - - /* Remove us from our main variant list if we are not the variant leader. */ - if (TYPE_MAIN_VARIANT (t) != t) - { - tem = TYPE_MAIN_VARIANT (t); - while (tem && TYPE_NEXT_VARIANT (tem) != t) - tem = TYPE_NEXT_VARIANT (tem); - if (tem) - TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t); - TYPE_NEXT_VARIANT (t) = NULL_TREE; - } - - /* Query our new main variant. */ - mv = gimple_register_type (TYPE_MAIN_VARIANT (t)); - - /* If we were the variant leader and we get replaced ourselves drop - all variants from our list. */ - if (TYPE_MAIN_VARIANT (t) == t - && mv != t) - { - tem = t; - while (tem) - { - tree tem2 = TYPE_NEXT_VARIANT (tem); - TYPE_NEXT_VARIANT (tem) = NULL_TREE; - tem = tem2; - } - } - - /* Finally adjust our main variant and fix it up. */ - TYPE_MAIN_VARIANT (t) = mv; - LTO_FIXUP_TREE (TYPE_MAIN_VARIANT (t)); - - /* As the second step of reconstructing the pointer chains put us - on the list of pointers of the new pointed-to type - if we are a main variant. See lto_ft_common for the first step. */ - if (TREE_CODE (t) == POINTER_TYPE - && TYPE_MAIN_VARIANT (t) == t) - { - TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t)); - TYPE_POINTER_TO (TREE_TYPE (t)) = t; - } - else if (TREE_CODE (t) == REFERENCE_TYPE - && TYPE_MAIN_VARIANT (t) == t) - { - TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t)); - TYPE_REFERENCE_TO (TREE_TYPE (t)) = t; - } } /* Fix up fields of a BINFO T. */ @@ -608,19 +509,21 @@ uniquify_nodes (struct data_in *data_in, unsigned from) /* Go backwards because childs streamed for the first time come as part of their parents, and hence are created after them. */ + + /* First register all types in the cache. + This makes sure to have the original structure in the type cycles + when registering them and computing hashes. */ for (i = len; i-- > from;) { tree t = VEC_index (tree, cache->nodes, i); - if (!t) + if (!t + || !TYPE_P (t)) continue; - /* Now try to find a canonical variant of T itself. */ - if (TYPE_P (t)) - gimple_register_type (t); + gimple_register_type (t); } - /* Go backwards because childs streamed for the first time come - as part of their parents, and hence are created after them. */ + /* Second fixup all trees in the new cache entries. */ for (i = len; i-- > from;) { tree t = VEC_index (tree, cache->nodes, i); @@ -631,43 +534,103 @@ uniquify_nodes (struct data_in *data_in, unsigned from) /* First fixup the fields of T. */ lto_fixup_types (t); + if (!TYPE_P (t)) + continue; + /* Now try to find a canonical variant of T itself. */ - if (TYPE_P (t)) + t = gimple_register_type (t); + + if (t == oldt) { - t = gimple_register_type (t); - if (t == oldt - && TYPE_MAIN_VARIANT (t) != t) + /* The following re-creates proper variant lists while fixing up + the variant leaders. We do not stream TYPE_NEXT_VARIANT so the + variant list state before fixup is broken. */ + tree tem, mv; + + /* Remove us from our main variant list if we are not the + variant leader. */ + if (TYPE_MAIN_VARIANT (t) != t) { - /* If this is its own type, link it into the variant chain. */ - TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)); - TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (t)) = t; + tem = TYPE_MAIN_VARIANT (t); + while (tem && TYPE_NEXT_VARIANT (tem) != t) + tem = TYPE_NEXT_VARIANT (tem); + if (tem) + TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t); + TYPE_NEXT_VARIANT (t) = NULL_TREE; + } + + /* Query our new main variant. */ + mv = gimple_register_type (TYPE_MAIN_VARIANT (t)); + + /* If we were the variant leader and we get replaced ourselves drop + all variants from our list. */ + if (TYPE_MAIN_VARIANT (t) == t + && mv != t) + { + tem = t; + while (tem) + { + tree tem2 = TYPE_NEXT_VARIANT (tem); + TYPE_NEXT_VARIANT (tem) = NULL_TREE; + tem = tem2; + } + } + + /* If we are not our own variant leader link us into our new leaders + variant list. */ + if (mv != t) + { + TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv); + TYPE_NEXT_VARIANT (mv) = t; + } + + /* Finally adjust our main variant and fix it up. */ + TYPE_MAIN_VARIANT (t) = mv; + + /* The following reconstructs the pointer chains + of the new pointed-to type if we are a main variant. We do + not stream those so they are broken before fixup. */ + if (TREE_CODE (t) == POINTER_TYPE + && TYPE_MAIN_VARIANT (t) == t) + { + TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t)); + TYPE_POINTER_TO (TREE_TYPE (t)) = t; + } + else if (TREE_CODE (t) == REFERENCE_TYPE + && TYPE_MAIN_VARIANT (t) == t) + { + TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t)); + TYPE_REFERENCE_TO (TREE_TYPE (t)) = t; } } - if (t != oldt) + + else if (RECORD_OR_UNION_TYPE_P (t)) { - if (RECORD_OR_UNION_TYPE_P (t)) - { - tree f1, f2; - if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt)) - for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt); - f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) - { - unsigned ix; - gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2)); - if (!lto_streamer_cache_lookup (cache, f2, &ix)) - gcc_unreachable (); - /* If we're going to replace an element which we'd - still visit in the next iterations, we wouldn't - handle it, so do it here. We do have to handle it - even though the field_decl itself will be removed, - as it could refer to e.g. integer_cst which we - wouldn't reach via any other way, hence they - (and their type) would stay uncollected. */ - if (ix < i) - lto_fixup_types (f2); - lto_streamer_cache_insert_at (cache, f1, ix); - } - } + tree f1, f2; + if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt)) + for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt); + f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) + { + unsigned ix; + gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2)); + if (!lto_streamer_cache_lookup (cache, f2, &ix)) + gcc_unreachable (); + /* If we're going to replace an element which we'd + still visit in the next iterations, we wouldn't + handle it, so do it here. We do have to handle it + even though the field_decl itself will be removed, + as it could refer to e.g. integer_cst which we + wouldn't reach via any other way, hence they + (and their type) would stay uncollected. */ + /* ??? We should rather make sure to replace all + references to f2 with f1. That means handling + COMPONENT_REFs and CONSTRUCTOR elements in + lto_fixup_types and special-case the field-decl + operand handling. */ + if (ix < i) + lto_fixup_types (f2); + lto_streamer_cache_insert_at (cache, f1, ix); + } /* If we found a tree that is equal to oldt replace it in the cache, so that further users (in the various LTO sections) @@ -675,6 +638,22 @@ uniquify_nodes (struct data_in *data_in, unsigned from) lto_streamer_cache_insert_at (cache, t, i); } } + + /* Finally compute the canonical type of t. From this point + there are no longer any types with TYPE_STRUCTURAL_EQUALITY_P + and its type-based alias problems. This step requires the + TYPE_POINTER_TO lists being present, so make sure it is done + last. */ + for (i = len; i-- > from;) + { + tree t = VEC_index (tree, cache->nodes, i); + if (!t + || !TYPE_P (t)) + continue; + + if (!TYPE_CANONICAL (t)) + TYPE_CANONICAL (t) = gimple_register_canonical_type (t); + } } /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.