On Thu, Apr 21, 2011 at 3:46 PM, Michael Matz <m...@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) \
>

Reply via email to