This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: better wpa [1/n]: merge types during read-in


On Thu, Apr 21, 2011 at 3:46 PM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Wed, 20 Apr 2011, Michael Matz wrote:
>
>> > It would have been nice to have the top-level tree merging as a
>> > separate patch, as I am not convinced it is correct, but see below ...
>>
>> I'll split it out.
>
> Like so (also including the other remarks).
>
> Regstrapping on x86_64-linux in progress.

Ok if it passed.

Thanks,
Richard.

>
> Ciao,
> Michael.
>
> ? ? ? ?* lto-streamer.c (lto_streamer_cache_insert_1): Accept to override
> ? ? ? ?other trees that just builtins.
> ? ? ? ?(lto_record_common_node): Don't leave NULL TYPE_CANONICAL.
>
> lto/
> ? ? ? ?* lto.c (toplevel): Include tree-flow.h.
> ? ? ? ?(lto_read_in_decl_state): Don't merge types here.
> ? ? ? ?(tree_with_vars): New static hash table.
> ? ? ? ?(remember_with_vars): New static functions.
> ? ? ? ?(LTO_FIXUP_TYPE): New macro.
> ? ? ? ?(lto_ft_common, lto_ft_decl_minimal, lto_ft_decl_common,
> ? ? ? ?lto_ft_decl_with_vis, lto_ft_decl_non_common, lto_ft_function,
> ? ? ? ?lto_ft_field_decl, lto_ft_type, lto_ft_binfo, lto_ft_constructor,
> ? ? ? ?lto_ft_expr, lto_fixup_types, uniquify_nodes): New static functions.
> ? ? ? ?(lto_read_decls): Uniquify while reading in trees.
> ? ? ? ?(lto_fixup_data_t, LTO_FIXUP_SUBTREE,
> ? ? ? ?LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE, no_fixup_p, lto_fixup_common,
> ? ? ? ?lto_fixup_decl_minimal, lto_fixup_decl_common, lto_fixup_decl_with_vis,
> ? ? ? ?lto_fixup_decl_non_common, lto_fixup_function, lto_fixup_field_decl,
> ? ? ? ?lto_fixup_type, lto_fixup_binfo, lto_fixup_constructor,
> ? ? ? ?lto_fixup_tree): Remove.
> ? ? ? ?(lto_fixup_state): Remove data argument. ?Use
> ? ? ? ?lto_symtab_prevailing_decl.
> ? ? ? ?(LTO_SET_PREVAIL, LTO_NO_PREVAIL): New macros.
> ? ? ? ?(lto_fixup_prevailing_decls): New function.
> ? ? ? ?(lto_fixup_state_aux): Argument aux is unused.
> ? ? ? ?(lto_fixup_decls): Don't allocate pointer sets, don't use
> ? ? ? ?lto_fixup_tree, use lto_fixup_prevailing_decls.
> ? ? ? ?(read_cgraph_and_symbols): Allocate and remove tree_with_vars.
> ? ? ? ?* Make-lang.in (lto/lto.o): Depend on $(TREE_FLOW_H).
>
> Index: lto-streamer.c
> ===================================================================
> *** lto-streamer.c ? ? ?(revision 172769)
> --- lto-streamer.c ? ? ?(working copy)
> *************** lto_streamer_cache_insert_1 (struct lto_
> *** 383,401 ****
> ? ? ? ?{
> ? ? ? ? ?/* If the caller wants to insert T at a specific slot
> ? ? ? ? ? ? location, and ENTRY->TO does not match *IX_P, add T to
> ! ? ? ? ? ? ?the requested location slot. ?This situation arises when
> ! ? ? ? ? ? ?streaming builtin functions.
> !
> ! ? ? ? ? ? ?For instance, on the writer side we could have two
> ! ? ? ? ? ? ?FUNCTION_DECLS T1 and T2 that are represented by the same
> ! ? ? ? ? ? ?builtin function. ?The reader will only instantiate the
> ! ? ? ? ? ? ?canonical builtin, but since T1 and T2 had been
> ! ? ? ? ? ? ?originally stored in different cache slots (S1 and S2),
> ! ? ? ? ? ? ?the reader must be able to find the canonical builtin
> ! ? ? ? ? ? ?function at slots S1 and S2. ?*/
> ! ? ? ? ? gcc_assert (lto_stream_as_builtin_p (t));
> ? ? ? ? ?ix = *ix_p;
> -
> ? ? ? ? ?lto_streamer_cache_add_to_node_array (cache, ix, t);
> ? ? ? ?}
>
> --- 383,390 ----
> ? ? ? ?{
> ? ? ? ? ?/* If the caller wants to insert T at a specific slot
> ? ? ? ? ? ? location, and ENTRY->TO does not match *IX_P, add T to
> ! ? ? ? ? ? ?the requested location slot. ?*/
> ? ? ? ? ?ix = *ix_p;
> ? ? ? ? ?lto_streamer_cache_add_to_node_array (cache, ix, t);
> ? ? ? ?}
>
> *************** lto_record_common_node (tree *nodep, VEC
> *** 513,518 ****
> --- 502,509 ----
> ? ? ? ?TYPE_CANONICAL (node) = NULL_TREE;
> ? ? ? ?node = gimple_register_type (node);
> ? ? ? ?TYPE_CANONICAL (node) = gimple_register_canonical_type (node);
> + ? ? ? if (in_lto_p)
> + ? ? ? TYPE_CANONICAL (*nodep) = TYPE_CANONICAL (node);
> ? ? ? ?*nodep = node;
> ? ? ?}
>
> Index: lto/lto.c
> ===================================================================
> *** lto/lto.c ? (revision 172769)
> --- lto/lto.c ? (working copy)
> *************** along with GCC; see the file COPYING3.
> *** 24,29 ****
> --- 24,30 ----
> ?#include "opts.h"
> ?#include "toplev.h"
> ?#include "tree.h"
> + #include "tree-flow.h"
> ?#include "diagnostic-core.h"
> ?#include "tm.h"
> ?#include "cgraph.h"
> *************** lto_read_in_decl_state (struct data_in *
> *** 215,228 ****
> ? ? ? ?tree *decls = ggc_alloc_vec_tree (size);
>
> ? ? ? ?for (j = 0; j < size; j++)
> ! ? ? ? {
> ! ? ? ? ? decls[j] = lto_streamer_cache_get (data_in->reader_cache, data[j]);
> !
> ! ? ? ? ? /* Register every type in the global type table. ?If the
> ! ? ? ? ? ? ?type existed already, use the existing type. ?*/
> ! ? ? ? ? if (TYPE_P (decls[j]))
> ! ? ? ? ? ? decls[j] = gimple_register_type (decls[j]);
> ! ? ? ? }
>
> ? ? ? ?state->streams[i].size = size;
> ? ? ? ?state->streams[i].trees = decls;
> --- 216,222 ----
> ? ? ? ?tree *decls = ggc_alloc_vec_tree (size);
>
> ? ? ? ?for (j = 0; j < size; j++)
> ! ? ? ? decls[j] = lto_streamer_cache_get (data_in->reader_cache, data[j]);
>
> ? ? ? ?state->streams[i].size = size;
> ? ? ? ?state->streams[i].trees = decls;
> *************** lto_read_in_decl_state (struct data_in *
> *** 232,237 ****
> --- 226,666 ----
> ? ?return data;
> ?}
>
> + /* A hashtable of trees that potentially refer to variables or functions
> + ? ?that must be replaced with their prevailing variant. ?*/
> + static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node))) htab_t
> + ? tree_with_vars;
> +
> + /* Remember that T is a tree that (potentially) refers to a variable
> + ? ?or function decl that may be replaced with its prevailing variant. ?*/
> + static void
> + remember_with_vars (tree t)
> + {
> + ? *(tree *) htab_find_slot (tree_with_vars, t, INSERT) = t;
> + }
> +
> + #define LTO_FIXUP_TREE(tt) \
> + ? do \
> + ? ? { \
> + ? ? ? if (tt) \
> + ? ? ? { \
> + ? ? ? ? if (TYPE_P (tt)) \
> + ? ? ? ? ? (tt) = gimple_register_type (tt); \
> + ? ? ? ? if (VAR_OR_FUNCTION_DECL_P (tt) && TREE_PUBLIC (tt)) \
> + ? ? ? ? ? remember_with_vars (t); \
> + ? ? ? } \
> + ? ? } while (0)
> +
> + static void lto_fixup_types (tree);
> +
> + /* Fix up fields of a tree_common T. ?*/
> +
> + 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));
> + }
> +
> + /* Fix up fields of a decl_minimal T. ?*/
> +
> + static void
> + lto_ft_decl_minimal (tree t)
> + {
> + ? lto_ft_common (t);
> + ? LTO_FIXUP_TREE (DECL_NAME (t));
> + ? LTO_FIXUP_TREE (DECL_CONTEXT (t));
> + }
> +
> + /* Fix up fields of a decl_common T. ?*/
> +
> + static void
> + lto_ft_decl_common (tree t)
> + {
> + ? lto_ft_decl_minimal (t);
> + ? LTO_FIXUP_TREE (DECL_SIZE (t));
> + ? LTO_FIXUP_TREE (DECL_SIZE_UNIT (t));
> + ? LTO_FIXUP_TREE (DECL_INITIAL (t));
> + ? LTO_FIXUP_TREE (DECL_ATTRIBUTES (t));
> + ? LTO_FIXUP_TREE (DECL_ABSTRACT_ORIGIN (t));
> + }
> +
> + /* Fix up fields of a decl_with_vis T. ?*/
> +
> + static void
> + lto_ft_decl_with_vis (tree t)
> + {
> + ? lto_ft_decl_common (t);
> +
> + ? /* Accessor macro has side-effects, use field-name here. */
> + ? LTO_FIXUP_TREE (t->decl_with_vis.assembler_name);
> + ? LTO_FIXUP_TREE (DECL_SECTION_NAME (t));
> + }
> +
> + /* Fix up fields of a decl_non_common T. ?*/
> +
> + static void
> + lto_ft_decl_non_common (tree t)
> + {
> + ? lto_ft_decl_with_vis (t);
> + ? LTO_FIXUP_TREE (DECL_ARGUMENT_FLD (t));
> + ? LTO_FIXUP_TREE (DECL_RESULT_FLD (t));
> + ? LTO_FIXUP_TREE (DECL_VINDEX (t));
> + }
> +
> + /* Fix up fields of a decl_non_common T. ?*/
> +
> + static void
> + lto_ft_function (tree t)
> + {
> + ? lto_ft_decl_non_common (t);
> + ? LTO_FIXUP_TREE (DECL_FUNCTION_PERSONALITY (t));
> + }
> +
> + /* Fix up fields of a field_decl T. ?*/
> +
> + static void
> + lto_ft_field_decl (tree t)
> + {
> + ? lto_ft_decl_common (t);
> + ? LTO_FIXUP_TREE (DECL_FIELD_OFFSET (t));
> + ? LTO_FIXUP_TREE (DECL_BIT_FIELD_TYPE (t));
> + ? LTO_FIXUP_TREE (DECL_QUALIFIER (t));
> + ? LTO_FIXUP_TREE (DECL_FIELD_BIT_OFFSET (t));
> + ? LTO_FIXUP_TREE (DECL_FCONTEXT (t));
> + }
> +
> + /* Fix up fields of a type 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));
> + ? LTO_FIXUP_TREE (TYPE_SIZE_UNIT (t));
> + ? LTO_FIXUP_TREE (TYPE_ATTRIBUTES (t));
> + ? LTO_FIXUP_TREE (TYPE_NAME (t));
> +
> + ? /* Accessors are for derived node types only. */
> + ? if (!POINTER_TYPE_P (t))
> + ? ? LTO_FIXUP_TREE (t->type.minval);
> + ? LTO_FIXUP_TREE (t->type.maxval);
> +
> + ? /* Accessor is for derived node types only. */
> + ? LTO_FIXUP_TREE (t->type.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. ?*/
> +
> + static void
> + lto_ft_binfo (tree t)
> + {
> + ? unsigned HOST_WIDE_INT i, n;
> + ? tree base, saved_base;
> +
> + ? lto_ft_common (t);
> + ? LTO_FIXUP_TREE (BINFO_VTABLE (t));
> + ? LTO_FIXUP_TREE (BINFO_OFFSET (t));
> + ? LTO_FIXUP_TREE (BINFO_VIRTUALS (t));
> + ? LTO_FIXUP_TREE (BINFO_VPTR_FIELD (t));
> + ? n = VEC_length (tree, BINFO_BASE_ACCESSES (t));
> + ? for (i = 0; i < n; i++)
> + ? ? {
> + ? ? ? saved_base = base = BINFO_BASE_ACCESS (t, i);
> + ? ? ? LTO_FIXUP_TREE (base);
> + ? ? ? if (base != saved_base)
> + ? ? ? VEC_replace (tree, BINFO_BASE_ACCESSES (t), i, base);
> + ? ? }
> + ? LTO_FIXUP_TREE (BINFO_INHERITANCE_CHAIN (t));
> + ? LTO_FIXUP_TREE (BINFO_SUBVTT_INDEX (t));
> + ? LTO_FIXUP_TREE (BINFO_VPTR_INDEX (t));
> + ? n = BINFO_N_BASE_BINFOS (t);
> + ? for (i = 0; i < n; i++)
> + ? ? {
> + ? ? ? saved_base = base = BINFO_BASE_BINFO (t, i);
> + ? ? ? LTO_FIXUP_TREE (base);
> + ? ? ? if (base != saved_base)
> + ? ? ? VEC_replace (tree, BINFO_BASE_BINFOS (t), i, base);
> + ? ? }
> + }
> +
> + /* Fix up fields of a CONSTRUCTOR T. ?*/
> +
> + static void
> + lto_ft_constructor (tree t)
> + {
> + ? unsigned HOST_WIDE_INT idx;
> + ? constructor_elt *ce;
> +
> + ? LTO_FIXUP_TREE (TREE_TYPE (t));
> +
> + ? for (idx = 0;
> + ? ? ? ?VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (t), idx, ce);
> + ? ? ? ?idx++)
> + ? ? {
> + ? ? ? LTO_FIXUP_TREE (ce->index);
> + ? ? ? LTO_FIXUP_TREE (ce->value);
> + ? ? }
> + }
> +
> + /* Fix up fields of an expression tree T. ?*/
> +
> + static void
> + lto_ft_expr (tree t)
> + {
> + ? int i;
> + ? lto_ft_common (t);
> + ? for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
> + ? ? LTO_FIXUP_TREE (TREE_OPERAND (t, i));
> + }
> +
> + /* Given a tree T fixup fields of T by replacing types with their merged
> + ? ?variant and other entities by an equal entity from an earlier compilation
> + ? ?unit, or an entity being canonical in a different way. ?This includes
> + ? ?for instance integer or string constants. ?*/
> +
> + static void
> + lto_fixup_types (tree t)
> + {
> + ? switch (TREE_CODE (t))
> + ? ? {
> + ? ? case IDENTIFIER_NODE:
> + ? ? ? break;
> +
> + ? ? case TREE_LIST:
> + ? ? ? LTO_FIXUP_TREE (TREE_VALUE (t));
> + ? ? ? LTO_FIXUP_TREE (TREE_PURPOSE (t));
> + ? ? ? LTO_FIXUP_TREE (TREE_CHAIN (t));
> + ? ? ? break;
> +
> + ? ? case FIELD_DECL:
> + ? ? ? lto_ft_field_decl (t);
> + ? ? ? break;
> +
> + ? ? case LABEL_DECL:
> + ? ? case CONST_DECL:
> + ? ? case PARM_DECL:
> + ? ? case RESULT_DECL:
> + ? ? case IMPORTED_DECL:
> + ? ? ? lto_ft_decl_common (t);
> + ? ? ? break;
> +
> + ? ? case VAR_DECL:
> + ? ? ? lto_ft_decl_with_vis (t);
> + ? ? ? break;
> +
> + ? ? case TYPE_DECL:
> + ? ? ? lto_ft_decl_non_common (t);
> + ? ? ? break;
> +
> + ? ? case FUNCTION_DECL:
> + ? ? ? lto_ft_function (t);
> + ? ? ? break;
> +
> + ? ? case TREE_BINFO:
> + ? ? ? lto_ft_binfo (t);
> + ? ? ? break;
> +
> + ? ? case PLACEHOLDER_EXPR:
> + ? ? ? lto_ft_common (t);
> + ? ? ? break;
> +
> + ? ? case BLOCK:
> + ? ? case TRANSLATION_UNIT_DECL:
> + ? ? case OPTIMIZATION_NODE:
> + ? ? case TARGET_OPTION_NODE:
> + ? ? ? break;
> +
> + ? ? default:
> + ? ? ? if (TYPE_P (t))
> + ? ? ? lto_ft_type (t);
> + ? ? ? else if (TREE_CODE (t) == CONSTRUCTOR)
> + ? ? ? lto_ft_constructor (t);
> + ? ? ? else if (CONSTANT_CLASS_P (t))
> + ? ? ? LTO_FIXUP_TREE (TREE_TYPE (t));
> + ? ? ? else if (EXPR_P (t))
> + ? ? ? {
> + ? ? ? ? lto_ft_expr (t);
> + ? ? ? }
> + ? ? ? else
> + ? ? ? {
> + ? ? ? ? remember_with_vars (t);
> + ? ? ? }
> + ? ? }
> + }
> +
> + /* Given a streamer cache structure DATA_IN (holding a sequence of trees
> + ? ?for one compilation unit) go over all trees starting at index FROM until the
> + ? ?end of the sequence and replace fields of those trees, and the trees
> + ? ?themself with their canonical variants as per gimple_register_type. ?*/
> +
> + static void
> + uniquify_nodes (struct data_in *data_in, unsigned from)
> + {
> + ? struct lto_streamer_cache_d *cache = data_in->reader_cache;
> + ? unsigned len = VEC_length (tree, cache->nodes);
> + ? unsigned i;
> + ? /* Go backwards because childs streamed for the first time come
> + ? ? ?as part of their parents, and hence are created after them. ?*/
> + ? for (i = len; i-- > from;)
> + ? ? {
> + ? ? ? tree t = VEC_index (tree, cache->nodes, i);
> + ? ? ? tree oldt = t;
> + ? ? ? if (!t)
> + ? ? ? continue;
> +
> + ? ? ? /* First fixup the fields of T. ?*/
> + ? ? ? lto_fixup_types (t);
> +
> + ? ? ? /* Now try to find a canonical variant of T itself. ?*/
> + ? ? ? if (TYPE_P (t))
> + ? ? ? {
> + ? ? ? ? t = gimple_register_type (t);
> + ? ? ? ? if (t == oldt
> + ? ? ? ? ? ? && 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;
> + ? ? ? ? ? }
> + ? ? ? }
> + ? ? ? if (t != oldt)
> + ? ? ? {
> + ? ? ? ? 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);
> + ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? }
> +
> + ? ? ? ? /* If we found a tree that is equal to oldt replace it in the
> + ? ? ? ? ? ?cache, so that further users (in the various LTO sections)
> + ? ? ? ? ? ?make use of it. ?*/
> + ? ? ? ? lto_streamer_cache_insert_at (cache, t, i);
> + ? ? ? }
> + ? ? }
> + }
>
> ?/* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.
> ? ? RESOLUTIONS is the set of symbols picked by the linker (read from the
> *************** lto_read_decls (struct lto_file_decl_dat
> *** 260,267 ****
> ? ?/* Read the global declarations and types. ?*/
> ? ?while (ib_main.p < ib_main.len)
> ? ? ?{
> ! ? ? ? tree t = lto_input_tree (&ib_main, data_in);
> ? ? ? ?gcc_assert (t && ib_main.p <= ib_main.len);
> ? ? ?}
>
> ? ?/* Read in lto_in_decl_state objects. ?*/
> --- 689,699 ----
> ? ?/* Read the global declarations and types. ?*/
> ? ?while (ib_main.p < ib_main.len)
> ? ? ?{
> ! ? ? ? tree t;
> ! ? ? ? unsigned from = VEC_length (tree, data_in->reader_cache->nodes);
> ! ? ? ? t = lto_input_tree (&ib_main, data_in);
> ? ? ? ?gcc_assert (t && ib_main.p <= ib_main.len);
> + ? ? ? uniquify_nodes (data_in, from);
> ? ? ?}
>
> ? ?/* Read in lto_in_decl_state objects. ?*/
> *************** lto_wpa_write_files (void)
> *** 1514,1520 ****
> ? ? ? ?fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name, part->insns);
> ? ? ? ?if (cgraph_dump_file)
> ? ? ? ?{
> ! ? ? ? ? fprintf (cgraph_dump_file, "Writting partition %s to file %s, %i insns\n",
> ? ? ? ? ? ? ? ? ? part->name, temp_filename, part->insns);
> ? ? ? ? ?fprintf (cgraph_dump_file, "cgraph nodes:");
> ? ? ? ? ?dump_cgraph_node_set (cgraph_dump_file, set);
> --- 1946,1952 ----
> ? ? ? ?fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name, part->insns);
> ? ? ? ?if (cgraph_dump_file)
> ? ? ? ?{
> ! ? ? ? ? fprintf (cgraph_dump_file, "Writing partition %s to file %s, %i insns\n",
> ? ? ? ? ? ? ? ? ? part->name, temp_filename, part->insns);
> ? ? ? ? ?fprintf (cgraph_dump_file, "cgraph nodes:");
> ? ? ? ? ?dump_cgraph_node_set (cgraph_dump_file, set);
> *************** lto_wpa_write_files (void)
> *** 1548,1963 ****
> ?}
>
>
> ! typedef struct {
> ! ? struct pointer_set_t *seen;
> ! } lto_fixup_data_t;
> !
> ! #define LTO_FIXUP_SUBTREE(t) \
> ! ? do \
> ! ? ? walk_tree (&(t), lto_fixup_tree, data, NULL); \
> ! ? while (0)
> !
> ! #define LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE(t) \
> ! ? do \
> ! ? ? { \
> ! ? ? ? if (t) \
> ! ? ? ? (t) = gimple_register_type (t); \
> ! ? ? ? walk_tree (&(t), lto_fixup_tree, data, NULL); \
> ! ? ? } \
> ! ? while (0)
> !
> ! static tree lto_fixup_tree (tree *, int *, void *);
> !
> ! /* Return true if T does not need to be fixed up recursively. ?*/
> !
> ! static inline bool
> ! no_fixup_p (tree t)
> ! {
> ! ? return (t == NULL
> ! ? ? ? ? || CONSTANT_CLASS_P (t)
> ! ? ? ? ? || TREE_CODE (t) == IDENTIFIER_NODE);
> ! }
> !
> ! /* Fix up fields of a tree_common T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_common (tree t, void *data)
> ! {
> ! ? /* 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_REGISTER_TYPE_AND_FIXUP_SUBTREE (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_fixup_type after
> ! ? ? ?fixing up our main variant. ?*/
> !
> ! ? /* This is not very efficient because we cannot do tail-recursion with
> ! ? ? ?a long chain of trees. */
> ! ? if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON))
> ! ? ? LTO_FIXUP_SUBTREE (TREE_CHAIN (t));
> ! }
> !
> ! /* Fix up fields of a decl_minimal T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_decl_minimal (tree t, void *data)
> ! {
> ! ? lto_fixup_common (t, data);
> ! ? LTO_FIXUP_SUBTREE (DECL_NAME (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_CONTEXT (t));
> ! }
> !
> ! /* Fix up fields of a decl_common T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_decl_common (tree t, void *data)
> ! {
> ! ? lto_fixup_decl_minimal (t, data);
> ! ? LTO_FIXUP_SUBTREE (DECL_SIZE (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_SIZE_UNIT (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_INITIAL (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_ATTRIBUTES (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_ABSTRACT_ORIGIN (t));
> ! }
> !
> ! /* Fix up fields of a decl_with_vis T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_decl_with_vis (tree t, void *data)
> ! {
> ! ? lto_fixup_decl_common (t, data);
> !
> ! ? /* Accessor macro has side-effects, use field-name here. */
> ! ? LTO_FIXUP_SUBTREE (t->decl_with_vis.assembler_name);
> !
> ! ? gcc_assert (no_fixup_p (DECL_SECTION_NAME (t)));
> ! }
> !
> ! /* Fix up fields of a decl_non_common T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_decl_non_common (tree t, void *data)
> ! {
> ! ? lto_fixup_decl_with_vis (t, data);
> ! ? LTO_FIXUP_SUBTREE (DECL_ARGUMENT_FLD (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_RESULT_FLD (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_VINDEX (t));
> !
> ! ? /* SAVED_TREE should not cleared by now. ?Also no accessor for base type. */
> ! ? gcc_assert (no_fixup_p (t->decl_non_common.saved_tree));
> ! }
> !
> ! /* Fix up fields of a decl_non_common T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_function (tree t, void *data)
> ! {
> ! ? lto_fixup_decl_non_common (t, data);
> ! ? LTO_FIXUP_SUBTREE (DECL_FUNCTION_PERSONALITY (t));
> ! }
> !
> ! /* Fix up fields of a field_decl T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_field_decl (tree t, void *data)
> ! {
> ! ? lto_fixup_decl_common (t, data);
> ! ? LTO_FIXUP_SUBTREE (DECL_FIELD_OFFSET (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_BIT_FIELD_TYPE (t));
> ! ? LTO_FIXUP_SUBTREE (DECL_QUALIFIER (t));
> ! ? gcc_assert (no_fixup_p (DECL_FIELD_BIT_OFFSET (t)));
> ! ? LTO_FIXUP_SUBTREE (DECL_FCONTEXT (t));
> ! }
> !
> ! /* Fix up fields of a type T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_type (tree t, void *data)
> ! {
> ! ? tree tem, mv;
> !
> ! ? lto_fixup_common (t, data);
> ! ? LTO_FIXUP_SUBTREE (TYPE_CACHED_VALUES (t));
> ! ? LTO_FIXUP_SUBTREE (TYPE_SIZE (t));
> ! ? LTO_FIXUP_SUBTREE (TYPE_SIZE_UNIT (t));
> ! ? LTO_FIXUP_SUBTREE (TYPE_ATTRIBUTES (t));
> ! ? LTO_FIXUP_SUBTREE (TYPE_NAME (t));
> !
> ! ? /* Accessors are for derived node types only. */
> ! ? if (!POINTER_TYPE_P (t))
> ! ? ? LTO_FIXUP_SUBTREE (t->type.minval);
> ! ? LTO_FIXUP_SUBTREE (t->type.maxval);
> !
> ! ? /* Accessor is for derived node types only. */
> ! ? LTO_FIXUP_SUBTREE (t->type.binfo);
> !
> ! ? if (TYPE_CONTEXT (t))
> ! ? ? {
> ! ? ? ? if (TYPE_P (TYPE_CONTEXT (t)))
> ! ? ? ? LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TYPE_CONTEXT (t));
> ! ? ? ? else
> ! ? ? ? LTO_FIXUP_SUBTREE (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_SUBTREE (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;
> ! ? ? ? }
> ! ? ? }
> !
> ! ? /* 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;
> ! ? LTO_FIXUP_SUBTREE (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_fixup_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. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_binfo (tree t, void *data)
> ! {
> ! ? unsigned HOST_WIDE_INT i, n;
> ! ? tree base, saved_base;
> !
> ! ? lto_fixup_common (t, data);
> ! ? gcc_assert (no_fixup_p (BINFO_OFFSET (t)));
> ! ? LTO_FIXUP_SUBTREE (BINFO_VTABLE (t));
> ! ? LTO_FIXUP_SUBTREE (BINFO_VIRTUALS (t));
> ! ? LTO_FIXUP_SUBTREE (BINFO_VPTR_FIELD (t));
> ! ? n = VEC_length (tree, BINFO_BASE_ACCESSES (t));
> ! ? for (i = 0; i < n; i++)
> ! ? ? {
> ! ? ? ? saved_base = base = BINFO_BASE_ACCESS (t, i);
> ! ? ? ? LTO_FIXUP_SUBTREE (base);
> ! ? ? ? if (base != saved_base)
> ! ? ? ? VEC_replace (tree, BINFO_BASE_ACCESSES (t), i, base);
> ! ? ? }
> ! ? LTO_FIXUP_SUBTREE (BINFO_INHERITANCE_CHAIN (t));
> ! ? LTO_FIXUP_SUBTREE (BINFO_SUBVTT_INDEX (t));
> ! ? LTO_FIXUP_SUBTREE (BINFO_VPTR_INDEX (t));
> ! ? n = BINFO_N_BASE_BINFOS (t);
> ! ? for (i = 0; i < n; i++)
> ! ? ? {
> ! ? ? ? saved_base = base = BINFO_BASE_BINFO (t, i);
> ! ? ? ? LTO_FIXUP_SUBTREE (base);
> ! ? ? ? if (base != saved_base)
> ! ? ? ? VEC_replace (tree, BINFO_BASE_BINFOS (t), i, base);
> ! ? ? }
> ! }
> !
> ! /* Fix up fields of a CONSTRUCTOR T. ?DATA points to fix-up states. ?*/
> !
> ! static void
> ! lto_fixup_constructor (tree t, void *data)
> ! {
> ! ? unsigned HOST_WIDE_INT idx;
> ! ? constructor_elt *ce;
> !
> ! ? LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TREE_TYPE (t));
> !
> ! ? for (idx = 0;
> ! ? ? ? ?VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (t), idx, ce);
> ! ? ? ? ?idx++)
> ! ? ? {
> ! ? ? ? LTO_FIXUP_SUBTREE (ce->index);
> ! ? ? ? LTO_FIXUP_SUBTREE (ce->value);
> ! ? ? }
> ! }
> !
> ! /* A walk_tree callback used by lto_fixup_state. TP is the pointer to the
> ! ? ?current tree. WALK_SUBTREES indicates if the subtrees will be walked.
> ! ? ?DATA is a pointer set to record visited nodes. */
> !
> ! static tree
> ! lto_fixup_tree (tree *tp, int *walk_subtrees, void *data)
> ! {
> ! ? tree t;
> ! ? lto_fixup_data_t *fixup_data = (lto_fixup_data_t *) data;
> ! ? tree prevailing;
> !
> ! ? t = *tp;
> ! ? *walk_subtrees = 0;
> ! ? if (!t || pointer_set_contains (fixup_data->seen, t))
> ! ? ? return NULL;
> !
> ! ? if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
> ! ? ? {
> ! ? ? ? prevailing = lto_symtab_prevailing_decl (t);
> !
> ! ? ? ? if (t != prevailing)
> ! ? ? ? {
> ! ? ? ? ? ?/* Also replace t with prevailing defintion. ?We don't want to
> ! ? ? ? ? ? ? insert the other defintion in the seen set as we want to
> ! ? ? ? ? ? ? replace all instances of it. ?*/
> ! ? ? ? ? *tp = prevailing;
> ! ? ? ? ? t = prevailing;
> ? ? ? ?}
> ? ? ?}
> ? ?else if (TYPE_P (t))
> ? ? ?{
> ! ? ? ? /* Replace t with the prevailing type. ?We don't want to insert the
> ! ? ? ? ? ?other type in the seen set as we want to replace all instances of it. ?*/
> ! ? ? ? t = gimple_register_type (t);
> ! ? ? ? *tp = t;
> ? ? ?}
> !
> ! ? if (pointer_set_insert (fixup_data->seen, t))
> ! ? ? return NULL;
> !
> ! ? /* walk_tree does not visit all reachable nodes that need to be fixed up.
> ! ? ? ?Hence we do special processing here for those kind of nodes. */
> ! ? switch (TREE_CODE (t))
> ? ? ?{
> ! ? ? case FIELD_DECL:
> ! ? ? ? lto_fixup_field_decl (t, data);
> ! ? ? ? break;
> !
> ! ? ? case LABEL_DECL:
> ! ? ? case CONST_DECL:
> ! ? ? case PARM_DECL:
> ! ? ? case RESULT_DECL:
> ! ? ? case IMPORTED_DECL:
> ! ? ? ? lto_fixup_decl_common (t, data);
> ! ? ? ? break;
> !
> ! ? ? case VAR_DECL:
> ! ? ? ? lto_fixup_decl_with_vis (t, data);
> ! ? ? ? break;
> !
> ! ? ? case TYPE_DECL:
> ! ? ? ? lto_fixup_decl_non_common (t, data);
> ! ? ? ? break;
> !
> ! ? ? case FUNCTION_DECL:
> ! ? ? ? lto_fixup_function (t, data);
> ! ? ? ? break;
> !
> ! ? ? case TREE_BINFO:
> ! ? ? ? lto_fixup_binfo (t, data);
> ! ? ? ? break;
> !
> ! ? ? default:
> ! ? ? ? if (TYPE_P (t))
> ! ? ? ? lto_fixup_type (t, data);
> ! ? ? ? else if (TREE_CODE (t) == CONSTRUCTOR)
> ! ? ? ? lto_fixup_constructor (t, data);
> ! ? ? ? else if (CONSTANT_CLASS_P (t))
> ! ? ? ? LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TREE_TYPE (t));
> ! ? ? ? else if (EXPR_P (t))
> ! ? ? ? {
> ! ? ? ? ? /* walk_tree only handles TREE_OPERANDs. Do the rest here. ?*/
> ! ? ? ? ? lto_fixup_common (t, data);
> ! ? ? ? ? LTO_FIXUP_SUBTREE (t->exp.block);
> ! ? ? ? ? *walk_subtrees = 1;
> ! ? ? ? }
> ! ? ? ? else
> ? ? ? ?{
> ! ? ? ? ? /* Let walk_tree handle sub-trees. ?*/
> ! ? ? ? ? *walk_subtrees = 1;
> ? ? ? ?}
> ? ? ?}
> -
> - ? return NULL;
> ?}
>
> ?/* Helper function of lto_fixup_decls. Walks the var and fn streams in STATE,
> ! ? ?replaces var and function decls with the corresponding prevailing def and
> ! ? ?records the old decl in the free-list in DATA. We also record visted nodes
> ! ? ?in the seen-set in DATA to avoid multiple visit for nodes that need not
> ! ? ?to be replaced. ?*/
>
> ?static void
> ! lto_fixup_state (struct lto_in_decl_state *state, lto_fixup_data_t *data)
> ?{
> ? ?unsigned i, si;
> ? ?struct lto_tree_ref_table *table;
> --- 1980,2085 ----
> ?}
>
>
> ! /* If TT is a variable or function decl replace it with its
> ! ? ?prevailing variant. ?*/
> ! #define LTO_SET_PREVAIL(tt) \
> ! ? do {\
> ! ? ? if ((tt) && VAR_OR_FUNCTION_DECL_P (tt)) \
> ! ? ? ? tt = lto_symtab_prevailing_decl (tt); \
> ! ? } while (0)
> !
> ! /* Ensure that TT isn't a replacable var of function decl. ?*/
> ! #define LTO_NO_PREVAIL(tt) \
> ! ? gcc_assert (!(tt) || !VAR_OR_FUNCTION_DECL_P (tt))
> !
> ! /* Given a tree T replace all fields referring to variables or functions
> ! ? ?with their prevailing variant. ?*/
> ! static void
> ! lto_fixup_prevailing_decls (tree t)
> ! {
> ! ? enum tree_code code = TREE_CODE (t);
> ! ? LTO_NO_PREVAIL (TREE_TYPE (t));
> ! ? LTO_NO_PREVAIL (TREE_CHAIN (t));
> ! ? if (DECL_P (t))
> ! ? ? {
> ! ? ? ? LTO_NO_PREVAIL (DECL_NAME (t));
> ! ? ? ? LTO_SET_PREVAIL (DECL_CONTEXT (t));
> ! ? ? ? if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> ! ? ? ? {
> ! ? ? ? ? LTO_SET_PREVAIL (DECL_SIZE (t));
> ! ? ? ? ? LTO_SET_PREVAIL (DECL_SIZE_UNIT (t));
> ! ? ? ? ? LTO_SET_PREVAIL (DECL_INITIAL (t));
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_ATTRIBUTES (t));
> ! ? ? ? ? LTO_SET_PREVAIL (DECL_ABSTRACT_ORIGIN (t));
> ! ? ? ? }
> ! ? ? ? if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
> ! ? ? ? {
> ! ? ? ? ? LTO_NO_PREVAIL (t->decl_with_vis.assembler_name);
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_SECTION_NAME (t));
> ! ? ? ? }
> ! ? ? ? if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
> ! ? ? ? {
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_ARGUMENT_FLD (t));
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_RESULT_FLD (t));
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_VINDEX (t));
> ! ? ? ? }
> ! ? ? ? if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
> ! ? ? ? LTO_SET_PREVAIL (DECL_FUNCTION_PERSONALITY (t));
> ! ? ? ? if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
> ! ? ? ? {
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_FIELD_OFFSET (t));
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_BIT_FIELD_TYPE (t));
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_QUALIFIER (t));
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_FIELD_BIT_OFFSET (t));
> ! ? ? ? ? LTO_NO_PREVAIL (DECL_FCONTEXT (t));
> ? ? ? ?}
> ? ? ?}
> ? ?else if (TYPE_P (t))
> ? ? ?{
> ! ? ? ? LTO_NO_PREVAIL (TYPE_CACHED_VALUES (t));
> ! ? ? ? LTO_SET_PREVAIL (TYPE_SIZE (t));
> ! ? ? ? LTO_SET_PREVAIL (TYPE_SIZE_UNIT (t));
> ! ? ? ? LTO_NO_PREVAIL (TYPE_ATTRIBUTES (t));
> ! ? ? ? LTO_NO_PREVAIL (TYPE_NAME (t));
> !
> ! ? ? ? LTO_SET_PREVAIL (t->type.minval);
> ! ? ? ? LTO_SET_PREVAIL (t->type.maxval);
> ! ? ? ? LTO_SET_PREVAIL (t->type.binfo);
> !
> ! ? ? ? LTO_SET_PREVAIL (TYPE_CONTEXT (t));
> !
> ! ? ? ? LTO_NO_PREVAIL (TYPE_CANONICAL (t));
> ! ? ? ? LTO_NO_PREVAIL (TYPE_MAIN_VARIANT (t));
> ! ? ? ? LTO_NO_PREVAIL (TYPE_NEXT_VARIANT (t));
> ! ? ? }
> ! ? else if (EXPR_P (t))
> ! ? ? {
> ! ? ? ? int i;
> ! ? ? ? LTO_NO_PREVAIL (t->exp.block);
> ! ? ? ? for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
> ! ? ? ? LTO_SET_PREVAIL (TREE_OPERAND (t, i));
> ? ? ?}
> ! ? else
> ? ? ?{
> ! ? ? ? switch (code)
> ? ? ? ?{
> ! ? ? ? case TREE_LIST:
> ! ? ? ? ? LTO_SET_PREVAIL (TREE_VALUE (t));
> ! ? ? ? ? LTO_SET_PREVAIL (TREE_PURPOSE (t));
> ! ? ? ? ? break;
> ! ? ? ? default:
> ! ? ? ? ? gcc_unreachable ();
> ? ? ? ?}
> ? ? ?}
> ?}
> + #undef LTO_SET_PREVAIL
> + #undef LTO_NO_PREVAIL
>
> ?/* Helper function of lto_fixup_decls. Walks the var and fn streams in STATE,
> ! ? ?replaces var and function decls with the corresponding prevailing def. ?*/
>
> ?static void
> ! lto_fixup_state (struct lto_in_decl_state *state)
> ?{
> ? ?unsigned i, si;
> ? ?struct lto_tree_ref_table *table;
> *************** lto_fixup_state (struct lto_in_decl_stat
> *** 1969,1986 ****
> ? ? ?{
> ? ? ? ?table = &state->streams[si];
> ? ? ? ?for (i = 0; i < table->size; i++)
> ! ? ? ? walk_tree (table->trees + i, lto_fixup_tree, data, NULL);
> ? ? ?}
> ?}
>
> ! /* A callback of htab_traverse. Just extract a state from SLOT and the
> ! ? ?lto_fixup_data_t object from AUX and calls lto_fixup_state. */
>
> ?static int
> ! lto_fixup_state_aux (void **slot, void *aux)
> ?{
> ? ?struct lto_in_decl_state *state = (struct lto_in_decl_state *) *slot;
> ! ? lto_fixup_state (state, (lto_fixup_data_t *) aux);
> ? ?return 1;
> ?}
>
> --- 2091,2112 ----
> ? ? ?{
> ? ? ? ?table = &state->streams[si];
> ? ? ? ?for (i = 0; i < table->size; i++)
> ! ? ? ? {
> ! ? ? ? ? tree *tp = table->trees + i;
> ! ? ? ? ? if (VAR_OR_FUNCTION_DECL_P (*tp))
> ! ? ? ? ? ? *tp = lto_symtab_prevailing_decl (*tp);
> ! ? ? ? }
> ? ? ?}
> ?}
>
> ! /* A callback of htab_traverse. Just extracts a state from SLOT
> ! ? ?and calls lto_fixup_state. */
>
> ?static int
> ! lto_fixup_state_aux (void **slot, void *aux ATTRIBUTE_UNUSED)
> ?{
> ? ?struct lto_in_decl_state *state = (struct lto_in_decl_state *) *slot;
> ! ? lto_fixup_state (state);
> ? ?return 1;
> ?}
>
> *************** static void
> *** 1991,2019 ****
> ?lto_fixup_decls (struct lto_file_decl_data **files)
> ?{
> ? ?unsigned int i;
> ! ? tree decl;
> ! ? struct pointer_set_t *seen = pointer_set_create ();
> ! ? lto_fixup_data_t data;
>
> - ? data.seen = seen;
> ? ?for (i = 0; files[i]; i++)
> ? ? ?{
> ? ? ? ?struct lto_file_decl_data *file = files[i];
> ? ? ? ?struct lto_in_decl_state *state = file->global_decl_state;
> ! ? ? ? lto_fixup_state (state, &data);
> !
> ! ? ? ? htab_traverse (file->function_decl_states, lto_fixup_state_aux, &data);
> ! ? ? }
>
> ! ? FOR_EACH_VEC_ELT (tree, lto_global_var_decls, i, decl)
> ! ? ? {
> ! ? ? ? tree saved_decl = decl;
> ! ? ? ? walk_tree (&decl, lto_fixup_tree, &data, NULL);
> ! ? ? ? if (decl != saved_decl)
> ! ? ? ? VEC_replace (tree, lto_global_var_decls, i, decl);
> ? ? ?}
> -
> - ? pointer_set_destroy (seen);
> ?}
>
> ?/* Read the options saved from each file in the command line. ?Called
> --- 2117,2136 ----
> ?lto_fixup_decls (struct lto_file_decl_data **files)
> ?{
> ? ?unsigned int i;
> ! ? htab_iterator hi;
> ! ? tree t;
> !
> ! ? FOR_EACH_HTAB_ELEMENT (tree_with_vars, t, tree, hi)
> ! ? ? lto_fixup_prevailing_decls (t);
>
> ? ?for (i = 0; files[i]; i++)
> ? ? ?{
> ? ? ? ?struct lto_file_decl_data *file = files[i];
> ? ? ? ?struct lto_in_decl_state *state = file->global_decl_state;
> ! ? ? ? lto_fixup_state (state);
>
> ! ? ? ? htab_traverse (file->function_decl_states, lto_fixup_state_aux, NULL);
> ? ? ?}
> ?}
>
> ?/* Read the options saved from each file in the command line. ?Called
> *************** read_cgraph_and_symbols (unsigned nfiles
> *** 2144,2149 ****
> --- 2261,2269 ----
> ? ? ? ?gcc_assert (num_objects == nfiles);
> ? ? ?}
>
> + ? tree_with_vars = htab_create_ggc (101, htab_hash_pointer, htab_eq_pointer,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NULL);
> +
> ? ?if (!quiet_flag)
> ? ? ?fprintf (stderr, "Reading object files:");
>
> *************** read_cgraph_and_symbols (unsigned nfiles
> *** 2211,2216 ****
> --- 2331,2338 ----
>
> ? ?/* Fixup all decls and types and free the type hash tables. ?*/
> ? ?lto_fixup_decls (all_file_decl_data);
> + ? htab_delete (tree_with_vars);
> + ? tree_with_vars = NULL;
> ? ?free_gimple_type_tables ();
> ? ?ggc_collect ();
>
> Index: lto/Make-lang.in
> ===================================================================
> *** lto/Make-lang.in ? ?(revision 172769)
> --- lto/Make-lang.in ? ?(working copy)
> *************** lto/lto-lang.o: lto/lto-lang.c $(CONFIG_
> *** 81,87 ****
> ? ? ? ?$(TARGET_H) $(LTO_H) $(GIMPLE_H) gtype-lto.h gt-lto-lto-lang.h \
> ? ? ? ?$(EXPR_H) $(LTO_STREAMER_H)
> ?lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
> ! ? ? ? toplev.h $(TREE_H) $(DIAGNOSTIC_CORE_H) $(TM_H) \
> ? ? ? ?$(CGRAPH_H) $(GGC_H) tree-ssa-operands.h $(TREE_PASS_H) \
> ? ? ? ?langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
> ? ? ? ?$(COMMON_H) debug.h $(TIMEVAR_H) $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
> --- 81,87 ----
> ? ? ? ?$(TARGET_H) $(LTO_H) $(GIMPLE_H) gtype-lto.h gt-lto-lto-lang.h \
> ? ? ? ?$(EXPR_H) $(LTO_STREAMER_H)
> ?lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
> ! ? ? ? toplev.h $(TREE_H) $(TREE_FLOW_H) $(DIAGNOSTIC_CORE_H) $(TM_H) \
> ? ? ? ?$(CGRAPH_H) $(GGC_H) tree-ssa-operands.h $(TREE_PASS_H) \
> ? ? ? ?langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
> ? ? ? ?$(COMMON_H) debug.h $(TIMEVAR_H) $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]