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


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.


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]