From patchwork Thu May 19 13:19:54 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 96373 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 04494B6F86 for ; Thu, 19 May 2011 23:20:25 +1000 (EST) Received: (qmail 8478 invoked by alias); 19 May 2011 13:20:22 -0000 Received: (qmail 8464 invoked by uid 22791); 19 May 2011 13:20:20 -0000 X-SWARE-Spam-Status: No, hits=-3.3 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 19 May 2011 13:19:56 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id CC8B087567 for ; Thu, 19 May 2011 15:19:54 +0200 (CEST) Date: Thu, 19 May 2011 15:19:54 +0200 (CEST) From: Richard Guenther To: gcc-patches@gcc.gnu.org Subject: [PATCH][?/n] Cleanup LTO type merging Message-ID: User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This moves all pointer-to, main-variant and canonical-type setup to a central place which happens after we fixed up and registered types for a set of new tree nodes. In particular delaying canonical type computation after setting up the pointer-to chains should enable a fix for PR48849 and its eventual duplicates. LTO bootstrapped and tested on x86_64-unknown-linux-gnu, kernel WPA tested, SPEC2k6 LTO build and test in progress. Richard. 2011-05-19 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. Index: gcc/lto/lto.c =================================================================== --- gcc/lto/lto.c (revision 173900) +++ gcc/lto/lto.c (working copy) @@ -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, /* 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, /* 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; } - } - if (t != oldt) - { - if (RECORD_OR_UNION_TYPE_P (t)) + + /* 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) { - 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); - } + TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t)); + TYPE_REFERENCE_TO (TREE_TYPE (t)) = t; } + } + + else 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. */ + /* ??? 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, 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. Index: gcc/gimple.c =================================================================== --- gcc/gimple.c (revision 173900) +++ gcc/gimple.c (working copy) @@ -4502,7 +4502,6 @@ gimple_register_type_1 (tree t, bool reg { 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]; @@ -4521,91 +4520,23 @@ gimple_register_type_1 (tree t, bool reg 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; }