public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][LTO] Clean up type variant handling, allow bootstrap
@ 2009-08-17 15:46 Richard Guenther
  2009-08-17 16:53 ` Diego Novillo
  0 siblings, 1 reply; 3+ messages in thread
From: Richard Guenther @ 2009-08-17 15:46 UTC (permalink / raw)
  To: gcc-patches; +Cc: Diego Novillo


This is my work-in-progress patch that enables bootstrapping with -flto
on i?86 (I'm currently checking x86_64).  The key is still the
gimple_get_alias_set hunk - all the rest is fixing fallout.

The main fixing is from properly streaming TYPE_MAIN_VARIANT and
keeping the variant chains intact (see also the trunk patches I did,
still referenced in the patch - I'm currently merging from trunk again).

In the process of debugging all this I placed a lot of asserts
throughout the code - whopr seems to depend on that we do not stream
non-canonical types, which is what the lto_fixup_* hunks and the
cache preloading hunks fix.  In the turn of fixing that I broke
the current -funsigned-char hack, so I simply removed it.

That's basically it.  I will likely remove most of the checking I
inserted before committing this, maybe keep the variant chain
verifying in free-lang-data, wrapped inside ENABLE_CHECKING.

The free_lang_data_in_block change is also odd - I am hitting
CONST_DECLs with a FUNCTION_DECL context during streaming out
of the abstract origin of a function.  But we assert that the
decl-context of all CONST_DECLs is NULL - for some reason.
The hack will pessimize debug info some more.  Why again do we
not want to stream DECL_CONTEXT properly?

I'm currently re-bootstrapping and testing this, but previous
testing shows a single regression, the -funsigned-char lto test.

Any comments?

Thanks,
Richard.

2009-08-17  Richard Guenther  <rguenther@suse.de>

	PR lto/41071
	* gimple.c (compare_type_names_p): Do not look at the
	types main variant.
	(gimple_register_type): Unlink a non-main-variant from its
	variant chain if we will use a different type for it.
	(gimple_get_alias_set): Pointers to CV qualified variants
	have the same alias-set as unqualified variants.
	* tree.c (free_lang_data_in_type): Do not free the variant chains.
	(free_lang_data_in_block): Insert hack to free lang data in
	abstract origins of the block as well.
	* lto-streamer-out.c (lto_output_ts_type_tree_pointers): Do
	not output TYPE_NEXT_VARIANT.
	(output_type_ref): Remove hack for char_type_node.
	* lto-streamer-in.c (lto_input_ts_type_tree_pointers): Do not
	input TYPE_NEXT_VARIANT but instead reconstruct it on-the-fly.
	* lto-streamer.c (lto_streamer_cache_insert_1): Add debugging code.
	Remove hack for char_type_node.
	(lto_record_common_node): Canonicalize types of nodes we record.
	(lto_get_common_nodes): Record integer and size types first.
	Defer to lto_record_common_node for registering and canonicalizing
	types.

	lto/
	* lto.c (lto_fixup_type): Fixup the types main-variant.  Keep
	the variant chains intact.
	(lto_fixup_constructor): New function.
	(lto_fixup_tree): Replace all types.  Properly fixup
	constructors and constants.


Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/gimple.c	2009-08-17 13:00:07.000000000 +0200
*************** lookup_type_pair (tree t1, tree t2, htab
*** 3185,3192 ****
  static bool
  compare_type_names_p (tree t1, tree t2)
  {
-   tree variant1 = TYPE_MAIN_VARIANT (t1);
-   tree variant2 = TYPE_MAIN_VARIANT (t2);
    tree name1 = TYPE_NAME (t1);
    tree name2 = TYPE_NAME (t2);
  
--- 3185,3190 ----
*************** compare_type_names_p (tree t1, tree t2)
*** 3215,3228 ****
    if (name1 == name2)
      return true;
  
-   /* If either type has a variant type, compare that.  This finds
-      the case where a struct is typedef'ed in one module but referred
-      to as 'struct foo' in the other; here, the main type for one is
-      'foo', and for the other 'foo_t', but the variants have the same
-      name 'foo'.  */
-   if (variant1 != t1 || variant2 != t2)
-     return compare_type_names_p (variant1, variant2);
- 
    return false;
  }
  
--- 3213,3218 ----
*************** gimple_register_type (tree t)
*** 3908,3928 ****
      }
  
    slot = htab_find_slot (gimple_types, t, INSERT);
!   if (*slot)
      {
!       tree new_type = (tree) *((tree *) slot);
  
        /* Do not merge types with different addressability.  */
        gcc_assert (TREE_ADDRESSABLE (t) == TREE_ADDRESSABLE (new_type));
  
        if (getenv ("MERGE_TYPE_DEBUG"))
  	{
! 	  if (t != new_type)
  	    {
! 	      fprintf (stderr, "Merged with existing compatible type: %p - ",
! 		  *slot);
! 	      print_generic_stmt (stderr, new_type, 0);
  	    }
  	}
  
        t = new_type;
--- 3898,3931 ----
      }
  
    slot = htab_find_slot (gimple_types, t, INSERT);
!   if (*slot
!       && *(tree *)slot != t)
      {
!       tree new_type = *((tree *) slot);
  
        /* Do not merge types with different addressability.  */
        gcc_assert (TREE_ADDRESSABLE (t) == TREE_ADDRESSABLE (new_type));
  
        if (getenv ("MERGE_TYPE_DEBUG"))
  	{
! 	  fprintf (stderr, "Merged with existing compatible type: %p - ", *slot);
! 	  print_generic_stmt (stderr, new_type, 0);
! 	}
! 
!       /* If t is not its main variant then make t unreachable from its
!          main variant list.  Otherwise we'd queue up a lot of duplicates
! 	 here.  */
!       if (t != TYPE_MAIN_VARIANT (t))
! 	{
! 	  tree tem = TYPE_MAIN_VARIANT (t);
! 	  while (tem && TYPE_NEXT_VARIANT (tem) != t)
! 	    tem = TYPE_NEXT_VARIANT (tem);
! 	  if (tem)
  	    {
! 	      TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t);
! 	      TYPE_NEXT_VARIANT (t) = NULL_TREE;
  	    }
+ 	  gcc_assert (TYPE_NEXT_VARIANT (t) == NULL_TREE);
  	}
  
        t = new_type;
*************** gimple_get_alias_set (tree t)
*** 4183,4188 ****
--- 4186,4221 ----
        if (t1 != t)
  	return get_alias_set (t1);
      }
+   else if (POINTER_TYPE_P (t))
+     {
+       tree t1;
+ 
+       /* Unfortunately, there is no canonical form of a pointer type.
+ 	 In particular, if we have `typedef int I', then `int *', and
+ 	 `I *' are different types.  So, we have to pick a canonical
+ 	 representative.  We do this below.
+ 
+ 	 Technically, this approach is actually more conservative that
+ 	 it needs to be.  In particular, `const int *' and `int *'
+ 	 should be in different alias sets, according to the C and C++
+ 	 standard, since their types are not the same, and so,
+ 	 technically, an `int **' and `const int **' cannot point at
+ 	 the same thing.
+ 
+ 	 But, the standard is wrong.  In particular, this code is
+ 	 legal C++:
+ 
+ 	 int *ip;
+ 	 int **ipp = &ip;
+ 	 const int* const* cipp = ipp;
+ 	 And, it doesn't make sense for that to be legal unless you
+ 	 can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
+ 	 the pointed-to types.  This issue has been reported to the
+ 	 C++ committee.  */
+       t1 = build_type_no_quals (t);
+       if (t1 != t)
+ 	return get_alias_set (t1);
+     }
  
    return -1;
  }
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/lto/lto.c	2009-08-17 13:00:07.000000000 +0200
*************** lto_fixup_field_decl (tree t, void *data
*** 1202,1207 ****
--- 1202,1209 ----
  static void
  lto_fixup_type (tree t, void *data)
  {
+   tree tem;
+ 
    lto_fixup_common (t, data);
    LTO_FIXUP_SUBTREE (TYPE_CACHED_VALUES (t));
    LTO_FIXUP_SUBTREE (TYPE_SIZE (t));
*************** lto_fixup_type (tree t, void *data)
*** 1215,1221 ****
    LTO_FIXUP_SUBTREE (t->type.minval);
    LTO_FIXUP_SUBTREE (t->type.maxval);
  
!   LTO_FIXUP_SUBTREE (TYPE_NEXT_VARIANT (t));
    LTO_FIXUP_SUBTREE (TYPE_MAIN_VARIANT (t));
  
    /* Accessor is for derived node types only. */
--- 1217,1262 ----
    LTO_FIXUP_SUBTREE (t->type.minval);
    LTO_FIXUP_SUBTREE (t->type.maxval);
  
!   /* When we get a new main variant type unlink us from the old
!      variant list and put us on the new one.  This will queue up
!      a lot of variant types which we might want to unlink
!      automatically in gimple_register_type.  */
!   tem = gimple_register_type (TYPE_MAIN_VARIANT (t));
!   if (tem != TYPE_MAIN_VARIANT (t))
!     {
!       /* Unlink us from the chain.  If we were a main variant, adjust
!          our siblings first - they will unlink themselves.  */
!       if (TYPE_MAIN_VARIANT (t) == t)
! 	LTO_FIXUP_SUBTREE (TYPE_NEXT_VARIANT (t));
!       else
! 	{
! 	  tree tem2 = TYPE_MAIN_VARIANT (t);
! 	  while (tem2 && TYPE_NEXT_VARIANT (tem2) != t)
! 	    tem2 = TYPE_NEXT_VARIANT (tem2);
! 	  /* We might be not on our main variants list as we are
! 	     unlinked from it in gimple_register_type in case we
! 	     have a duplicate.  */
! 	  if (tem2)
! 	    {
! 	      TYPE_NEXT_VARIANT (tem2) = TYPE_NEXT_VARIANT (t);
! 	      TYPE_NEXT_VARIANT (t) = NULL_TREE;
! 	    }
! 	}
!       gcc_assert (TYPE_NEXT_VARIANT (t) == NULL_TREE);
! 
!       /* If we became our main variant, there is nothing to do.
!          Else link us in the list of variants.  */
!       if (tem == t)
! 	;
!       else
! 	{
! 	  TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (tem);
! 	  TYPE_NEXT_VARIANT (tem) = t;
! 	}
! 
!       /* Finally update our main variant link.  */
!       TYPE_MAIN_VARIANT (t) = tem;
!     }
    LTO_FIXUP_SUBTREE (TYPE_MAIN_VARIANT (t));
  
    /* Accessor is for derived node types only. */
*************** lto_fixup_binfo (tree t, void *data)
*** 1259,1264 ****
--- 1300,1324 ----
      }
  }
  
+ /* 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. */
*************** lto_fixup_tree (tree *tp, int *walk_subt
*** 1312,1317 ****
--- 1372,1384 ----
  	  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;
+     }
  
    pointer_set_insert (fixup_data->seen, t);
  
*************** lto_fixup_tree (tree *tp, int *walk_subt
*** 1350,1355 ****
--- 1417,1426 ----
      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.  */
Index: gcc/tree.c
===================================================================
*** gcc/tree.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/tree.c	2009-08-17 16:18:11.000000000 +0200
*************** free_lang_data_in_type (tree type)
*** 4223,4237 ****
    /* FIXME lto: This will break debug info generation.  */
    TYPE_STUB_DECL (type) = NULL_TREE;
  
!   /* Remove type variants other than the main variant.  This is both
!      wasteful and it may introduce infinite loops when the types are
!      read from disk and merged (since the variant will be the same
!      type as the main variant, traversing type variants will get into
!      an infinite loop).  */
!   if (TYPE_MAIN_VARIANT (type))
!     TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (type)) = NULL_TREE;
! 
!   TYPE_NEXT_VARIANT (type) = NULL_TREE;
  }
  
  
--- 4223,4244 ----
    /* FIXME lto: This will break debug info generation.  */
    TYPE_STUB_DECL (type) = NULL_TREE;
  
!     {
!       tree tem = TYPE_MAIN_VARIANT (type);
!       while (tem && tem != type)
! 	{
! 	  gcc_assert (TYPE_MAIN_VARIANT (tem) == TYPE_MAIN_VARIANT (type));
! 	  gcc_assert (TYPE_NEXT_VARIANT (tem) != tem);
! 	  tem = TYPE_NEXT_VARIANT (tem);
! 	}
!       gcc_assert (tem != NULL_TREE);
!       while (TYPE_NEXT_VARIANT (tem))
! 	{
! 	  gcc_assert (TYPE_MAIN_VARIANT (tem) == TYPE_MAIN_VARIANT (type));
! 	  gcc_assert (TYPE_NEXT_VARIANT (tem) != tem);
! 	  tem = TYPE_NEXT_VARIANT (tem);
! 	}
!     }
  }
  
  
*************** free_lang_data_in_block (tree fn, tree b
*** 4288,4293 ****
--- 4295,4316 ----
  	tp = &TREE_CHAIN (*tp);
      }
  
+   /* Also remove the vars from the abstract origin as we stream that out
+      being confused about CONST_DECLs with non-NULL DECL_CONTEXT.
+      FIXME lto.  Better would be to allow non-NULL DECL_CONTEXT there.  */
+   if (BLOCK_ABSTRACT_ORIGIN (block)
+       && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block)) == BLOCK)
+     {
+       tp = &BLOCK_VARS (BLOCK_ABSTRACT_ORIGIN (block));
+       while (*tp)
+ 	{
+ 	  if (!pointer_set_contains (locals, *tp))
+ 	    *tp = TREE_CHAIN (*tp);
+ 	  else
+ 	    tp = &TREE_CHAIN (*tp);
+ 	}
+     }
+ 
    for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
      free_lang_data_in_block (fn, t, locals);
  }
Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/lto-streamer-out.c	2009-08-17 16:20:07.000000000 +0200
*************** output_record_start (struct output_block
*** 367,378 ****
  static void
  output_type_ref (struct output_block *ob, tree node)
  {
-   /* FIXME lto.  This is a hack, the use of -funsigned-char should be
-      reflected in the IL by changing every reference to char_type_node
-      into unsigned_char_type_node in pass_ipa_free_lang_data.  */
-   if (flag_signed_char == 0 && node == char_type_node)
-     node = unsigned_char_type_node;
- 
    output_record_start (ob, LTO_type_ref);
    lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
  }
--- 367,372 ----
*************** lto_output_ts_type_tree_pointers (struct
*** 1072,1078 ****
    lto_output_tree_or_ref (ob, TYPE_NAME (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MINVAL (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MAXVAL (expr), ref_p);
!   lto_output_tree_or_ref (ob, TYPE_NEXT_VARIANT (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MAIN_VARIANT (expr), ref_p);
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
--- 1066,1092 ----
    lto_output_tree_or_ref (ob, TYPE_NAME (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MINVAL (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MAXVAL (expr), ref_p);
!     {
!       tree tem = TYPE_MAIN_VARIANT (expr);
!       while (tem && tem != expr)
! 	{
! 	  gcc_assert (TYPE_MAIN_VARIANT (tem) == TYPE_MAIN_VARIANT (expr));
! 	  gcc_assert (TYPE_NEXT_VARIANT (tem) != tem);
! 	  tem = TYPE_NEXT_VARIANT (tem);
! 	}
!       /* We can end up refering to types we shouldn't refer to but
!          which register_gimple_type assigned to something else.
! 	 Odd but happens.  Should be harmless.  */
!       gcc_assert (tem != NULL_TREE);
!       while (tem && TYPE_NEXT_VARIANT (tem))
! 	{
! 	  gcc_assert (TYPE_MAIN_VARIANT (tem) == TYPE_MAIN_VARIANT (expr));
! 	  gcc_assert (TYPE_NEXT_VARIANT (tem) != tem);
! 	  tem = TYPE_NEXT_VARIANT (tem);
! 	}
!     }
!   /* Do not output TYPE_NEXT_VARIANT, it will be re-constructed on-the-fly
!      on read-in.  */
    lto_output_tree_or_ref (ob, TYPE_MAIN_VARIANT (expr), ref_p);
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
*************** lto_write_tree (struct output_block *ob,
*** 1385,1390 ****
--- 1399,1409 ----
  {
    struct bitpack_d *bp;
  
+   /* If we are streaming out a type make sure it is the canonical variant.  */
+   if (flag_wpa
+       && TYPE_P (expr))
+     gcc_assert (expr == gimple_register_type (expr));
+ 
    /* Write the header, containing everything needed to materialize
       EXPR on the reading side.  */
    lto_output_tree_header (ob, expr, ix);
Index: gcc/lto-streamer-in.c
===================================================================
*** gcc/lto-streamer-in.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/lto-streamer-in.c	2009-08-17 13:00:07.000000000 +0200
*************** lto_input_ts_type_tree_pointers (struct
*** 1990,1997 ****
    TYPE_NAME (expr) = lto_input_tree (ib, data_in);
    TYPE_MINVAL (expr) = lto_input_tree (ib, data_in);
    TYPE_MAXVAL (expr) = lto_input_tree (ib, data_in);
-   TYPE_NEXT_VARIANT (expr) = lto_input_tree (ib, data_in);
    TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
    TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
--- 1990,2004 ----
    TYPE_NAME (expr) = lto_input_tree (ib, data_in);
    TYPE_MINVAL (expr) = lto_input_tree (ib, data_in);
    TYPE_MAXVAL (expr) = lto_input_tree (ib, data_in);
    TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
+   /* Queue the node in the main variant chain.  We can't stream the
+      next variant because we might pick up a common tree node as
+      our main variant.  */
+   if (TYPE_MAIN_VARIANT (expr) != expr)
+     {
+       TYPE_NEXT_VARIANT (expr) = TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (expr));
+       TYPE_NEXT_VARIANT (TYPE_MAIN_VARIANT (expr)) = expr;
+     }
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
    TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
Index: gcc/cp/decl.c
===================================================================
*** gcc/cp/decl.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/cp/decl.c	2009-08-17 13:00:07.000000000 +0200
*************** build_ptrmemfunc_type (tree type)
*** 7056,7065 ****
    /* If this is not the unqualified form of this pointer-to-member
       type, set the TYPE_MAIN_VARIANT for this type to be the
       unqualified type.  Since they are actually RECORD_TYPEs that are
!      not variants of each other, we must do this manually.  */
    if (cp_type_quals (type) != TYPE_UNQUALIFIED)
      {
!       t = build_qualified_type (t, cp_type_quals (type));
        TYPE_MAIN_VARIANT (t) = unqualified_variant;
        TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
        TYPE_NEXT_VARIANT (unqualified_variant) = t;
--- 7056,7069 ----
    /* If this is not the unqualified form of this pointer-to-member
       type, set the TYPE_MAIN_VARIANT for this type to be the
       unqualified type.  Since they are actually RECORD_TYPEs that are
!      not variants of each other, we must do this manually.
!      As we just built a new type there is no need to do yet another copy.  */
    if (cp_type_quals (type) != TYPE_UNQUALIFIED)
      {
!       int type_quals = cp_type_quals (type);
!       TYPE_READONLY (t) = (type_quals & TYPE_QUAL_CONST) != 0;
!       TYPE_VOLATILE (t) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
!       TYPE_RESTRICT (t) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
        TYPE_MAIN_VARIANT (t) = unqualified_variant;
        TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
        TYPE_NEXT_VARIANT (unqualified_variant) = t;
*************** finish_enum (tree enumtype)
*** 11164,11170 ****
        /* Set the underlying type of the enumeration type to the
           computed enumeration type, restricted to the enumerator
           values. */
!       ENUM_UNDERLYING_TYPE (enumtype) = copy_node (underlying_type);
        set_min_and_max_values_for_integral_type 
          (ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
      }
--- 11168,11175 ----
        /* Set the underlying type of the enumeration type to the
           computed enumeration type, restricted to the enumerator
           values. */
!       ENUM_UNDERLYING_TYPE (enumtype)
! 	= build_distinct_type_copy (underlying_type);
        set_min_and_max_values_for_integral_type 
          (ENUM_UNDERLYING_TYPE (enumtype), precision, unsignedp);
      }
Index: gcc/cp/tree.c
===================================================================
*** gcc/cp/tree.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/cp/tree.c	2009-08-17 13:00:07.000000000 +0200
*************** cp_build_reference_type (tree to_type, b
*** 700,711 ****
      if (TYPE_REF_IS_RVALUE (t))
        return t;
  
!   t = copy_node (lvalue_ref);
  
    TYPE_REF_IS_RVALUE (t) = true;
    TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (lvalue_ref);
    TYPE_NEXT_REF_TO (lvalue_ref) = t;
-   TYPE_MAIN_VARIANT (t) = t;
  
    if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
      SET_TYPE_STRUCTURAL_EQUALITY (t);
--- 700,710 ----
      if (TYPE_REF_IS_RVALUE (t))
        return t;
  
!   t = build_distinct_type_copy (lvalue_ref);
  
    TYPE_REF_IS_RVALUE (t) = true;
    TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (lvalue_ref);
    TYPE_NEXT_REF_TO (lvalue_ref) = t;
  
    if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
      SET_TYPE_STRUCTURAL_EQUALITY (t);
Index: gcc/fortran/trans-expr.c
===================================================================
*** gcc/fortran/trans-expr.c.orig	2009-08-17 12:59:36.000000000 +0200
--- gcc/fortran/trans-expr.c	2009-08-17 13:00:07.000000000 +0200
*************** gfc_trans_scalar_assign (gfc_se * lse, g
*** 4432,4460 ****
  	  gfc_add_expr_to_block (&block, tmp);
  	}
      }
    else
      {
        gfc_add_block_to_block (&block, &lse->pre);
        gfc_add_block_to_block (&block, &rse->pre);
  
-       /* TODO This is rather obviously the wrong place to do this.
- 	 However, a number of testcases, such as function_kinds_1
- 	 and function_types_2 fail without it, by ICEing at
- 	 fold_const: 2710 (fold_convert_loc).  */
-       if (ts.type == BT_DERIVED
- 	    && gfc_option.flag_whole_file
- 	    && (TYPE_MAIN_VARIANT (TREE_TYPE (rse->expr))
- 		!= TYPE_MAIN_VARIANT (TREE_TYPE (lse->expr))))
- 	{
- 	  tmp = gfc_evaluate_now (rse->expr, &block);
- 	  TYPE_MAIN_VARIANT (TREE_TYPE (tmp))
- 		= TYPE_MAIN_VARIANT (TREE_TYPE (lse->expr));
- 	}
-       else
- 	tmp = rse->expr;
-       
        gfc_add_modify (&block, lse->expr,
! 			   fold_convert (TREE_TYPE (lse->expr), tmp));
      }
  
    gfc_add_block_to_block (&block, &lse->post);
--- 4432,4452 ----
  	  gfc_add_expr_to_block (&block, tmp);
  	}
      }
+   else if (ts.type == BT_DERIVED)
+     {
+       gfc_add_block_to_block (&block, &lse->pre);
+       gfc_add_block_to_block (&block, &rse->pre);
+       tmp = gfc_evaluate_now (rse->expr, &block);
+       tmp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lse->expr), rse->expr);
+       gfc_add_modify (&block, lse->expr, tmp);
+     }
    else
      {
        gfc_add_block_to_block (&block, &lse->pre);
        gfc_add_block_to_block (&block, &rse->pre);
  
        gfc_add_modify (&block, lse->expr,
! 		      fold_convert (TREE_TYPE (lse->expr), rse->expr));
      }
  
    gfc_add_block_to_block (&block, &lse->post);
Index: gcc/lto-streamer.c
===================================================================
*** gcc/lto-streamer.c.orig	2009-08-17 13:00:06.000000000 +0200
--- gcc/lto-streamer.c	2009-08-17 16:20:06.000000000 +0200
*************** lto_streamer_cache_insert_1 (struct lto_
*** 500,511 ****
  
    gcc_assert (t);
  
-   /* If -funsigned-char is given, replace references to 'char' with
-      'unsigned char'.  FIXME lto, this should be done in
-      free_lang_data.  */
-   if (flag_signed_char == 0 && TYPE_P (t) && t == char_type_node)
-     t = unsigned_char_type_node;
- 
    d_entry.base.from = t;
    slot = htab_find_slot (cache->node_map, &d_entry, INSERT);
    if (*slot == NULL)
--- 500,505 ----
*************** lto_streamer_cache_insert_1 (struct lto_
*** 556,561 ****
--- 550,558 ----
  	     stream is not necessary as we will not need to read
  	     forward in the stream.  */
  	  lto_streamer_cache_add_to_node_array (cache, ix, t, -1);
+ 
+ 	  if (getenv ("STREAMER_DEBUG"))
+ 	    fprintf (stderr, "duplicate ");
  	}
  
        /* Indicate that T was already in the cache.  */
*************** lto_streamer_cache_insert_1 (struct lto_
*** 568,573 ****
--- 565,576 ----
    if (offset_p)
      *offset_p = offset; 
  
+   if (getenv ("STREAMER_DEBUG"))
+     {
+       fprintf (stderr, "inserting at %i[%u]%s ", ix, offset,
+ 	       existed_p ? " (present)" : "");
+       print_generic_stmt (stderr, t, 0);
+     }
  
    return existed_p;
  }
*************** lto_streamer_cache_get (struct lto_strea
*** 662,673 ****
     SEEN_NODES.  */
  
  static void
! lto_record_common_node (tree node, VEC(tree, heap) **common_nodes,
  			struct pointer_set_t *seen_nodes)
  {
    if (node == NULL_TREE)
      return;
  
    /* Return if node is already seen.  */
    if (pointer_set_insert (seen_nodes, node))
      return;
--- 665,681 ----
     SEEN_NODES.  */
  
  static void
! lto_record_common_node (tree *nodep, VEC(tree, heap) **common_nodes,
  			struct pointer_set_t *seen_nodes)
  {
+   tree node = *nodep;
+ 
    if (node == NULL_TREE)
      return;
  
+   if (TYPE_P (node))
+     *nodep = node = gimple_register_type (node);
+ 
    /* Return if node is already seen.  */
    if (pointer_set_insert (seen_nodes, node))
      return;
*************** lto_record_common_node (tree node, VEC(t
*** 676,693 ****
  
    if (tree_node_can_be_shared (node))
      {
!       if (TYPE_P (node))
! 	lto_record_common_node (TYPE_MAIN_VARIANT (node), common_nodes,
! 				seen_nodes);
! 
!       if (TREE_CODE (node) == ARRAY_TYPE)
! 	lto_record_common_node (TREE_TYPE (node), common_nodes, seen_nodes);
      }
  }
  
  
! /* Generate a vector of common nodes and register them in the gimple
!    type table as merge targets. */
  
  static VEC(tree,heap) *
  lto_get_common_nodes (void)
--- 684,699 ----
  
    if (tree_node_can_be_shared (node))
      {
!       if (POINTER_TYPE_P (node)
! 	  || TREE_CODE (node) == COMPLEX_TYPE
! 	  || TREE_CODE (node) == ARRAY_TYPE)
! 	lto_record_common_node (&TREE_TYPE (node), common_nodes, seen_nodes);
      }
  }
  
  
! /* Generate a vector of common nodes and make sure they are merged
!    properly according to the the gimple type table.  */
  
  static VEC(tree,heap) *
  lto_get_common_nodes (void)
*************** lto_get_common_nodes (void)
*** 720,753 ****
    
    seen_nodes = pointer_set_create ();
  
-   /* char_type_node is special, we have to prefer merging the other
-      char variants into it because the middle-end has pointer comparisons
-      with it.  */
-   gimple_register_type (char_type_node);
- 
-   for (i = 0; i < TI_MAX; i++)
-     {
-       tree t = global_trees[i];
-       if (t && TYPE_P (t))
- 	gimple_register_type (t);
-       lto_record_common_node (global_trees[i], &common_nodes, seen_nodes);
-     }
- 
    for (i = 0; i < itk_none; i++)
!     {
!       tree t = integer_types[i];
!       if (t && TYPE_P (t))
! 	gimple_register_type (t);
!       lto_record_common_node (integer_types[i], &common_nodes, seen_nodes);
!     }
  
    for (i = 0; i < TYPE_KIND_LAST; i++)
!     {
!       tree t = sizetype_tab[i];
!       if (t && TYPE_P (t))
! 	gimple_register_type (t);
!       lto_record_common_node (sizetype_tab[i], &common_nodes, seen_nodes);
!     }
  
    pointer_set_destroy (seen_nodes);
  
--- 726,739 ----
    
    seen_nodes = pointer_set_create ();
  
    for (i = 0; i < itk_none; i++)
!     lto_record_common_node (&integer_types[i], &common_nodes, seen_nodes);
  
    for (i = 0; i < TYPE_KIND_LAST; i++)
!     lto_record_common_node (&sizetype_tab[i], &common_nodes, seen_nodes);
! 
!   for (i = 0; i < TI_MAX; i++)
!     lto_record_common_node (&global_trees[i], &common_nodes, seen_nodes);
  
    pointer_set_destroy (seen_nodes);
  

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH][LTO] Clean up type variant handling, allow bootstrap
  2009-08-17 15:46 [PATCH][LTO] Clean up type variant handling, allow bootstrap Richard Guenther
@ 2009-08-17 16:53 ` Diego Novillo
  2009-08-18 12:11   ` Richard Guenther
  0 siblings, 1 reply; 3+ messages in thread
From: Diego Novillo @ 2009-08-17 16:53 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On Mon, Aug 17, 2009 at 10:33, Richard Guenther<rguenther@suse.de> wrote:

> The free_lang_data_in_block change is also odd - I am hitting
> CONST_DECLs with a FUNCTION_DECL context during streaming out
> of the abstract origin of a function.  But we assert that the
> decl-context of all CONST_DECLs is NULL - for some reason.
> The hack will pessimize debug info some more.  Why again do we
> not want to stream DECL_CONTEXT properly?

Initially, we were pulling in C++-specific trees this way.  If it's no
longer needed, then that's fine.

> Any comments?

All that fixup code for WPA is a bit odd, but that is something we can
leave for later.


Diego.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH][LTO] Clean up type variant handling, allow bootstrap
  2009-08-17 16:53 ` Diego Novillo
@ 2009-08-18 12:11   ` Richard Guenther
  0 siblings, 0 replies; 3+ messages in thread
From: Richard Guenther @ 2009-08-18 12:11 UTC (permalink / raw)
  To: Diego Novillo; +Cc: gcc-patches

[-- Attachment #1: Type: TEXT/PLAIN, Size: 13663 bytes --]

On Mon, 17 Aug 2009, Diego Novillo wrote:

> On Mon, Aug 17, 2009 at 10:33, Richard Guenther<rguenther@suse.de> wrote:
> 
> > The free_lang_data_in_block change is also odd - I am hitting
> > CONST_DECLs with a FUNCTION_DECL context during streaming out
> > of the abstract origin of a function.  But we assert that the
> > decl-context of all CONST_DECLs is NULL - for some reason.
> > The hack will pessimize debug info some more.  Why again do we
> > not want to stream DECL_CONTEXT properly?
> 
> Initially, we were pulling in C++-specific trees this way.  If it's no
> longer needed, then that's fine.
> 
> > Any comments?
> 
> All that fixup code for WPA is a bit odd, but that is something we can
> leave for later.

Well, currently we do not fixup types TYPE_MAIN_VARIANT at all
(thus, it stays the non-merged variants).  This sounds wrong.
And just fixing that runs into issues with WPA.

We may not need to keep the variant chains, and the other lto_fixup_*
changes are to fix the asserts I placed (mainly the assert that for
WPA we only stream the canonical merged type variants).

I will test the following less invasive change (we can resort to
the variant chain rebuilding variant later if it works out).
It will break g++.dg/lto/pr40818 due to the CONST_DECL issue at least
(I don't like my BLOCK_ABSTRACT_ORIGIN hack there).

Probably the other lto_fixup_* changes are useful for memory usage
reasons (otherwise we'll keep references to that unused types).

So, if the following bootstraps and tests on and it fixes the bootstrap
with -flto issue as well then I'm going to apply that despite the
two regressions I know it will cause.

Richard.

2009-08-17  Richard Guenther  <rguenther@suse.de>

	PR lto/41071
	* gimple.c (compare_type_names_p): Do not look at the
	types main variant.
	(gimple_get_alias_set): Pointers to CV qualified variants
	have the same alias-set as unqualified variants.
	* lto-streamer-out.c (lto_output_ts_type_tree_pointers): Do
	not output TYPE_NEXT_VARIANT.
	(output_type_ref): Remove hack for char_type_node.
	* lto-streamer-in.c (lto_input_ts_type_tree_pointers): Do not
	input TYPE_NEXT_VARIANT.
	* lto-streamer.c (lto_streamer_cache_insert_1): Add debugging code.
	Remove hack for char_type_node.
	(lto_record_common_node): Canonicalize types of nodes we record.
	(lto_get_common_nodes): Record integer and size types first.
	Defer to lto_record_common_node for registering and canonicalizing
	types.

	lto/
	* lto.c (lto_fixup_type): Fixup the types main-variant.  Zero
	the types next-variant.

Index: gcc/gimple.c
===================================================================
*** gcc/gimple.c.orig	2009-08-18 12:37:36.000000000 +0200
--- gcc/gimple.c	2009-08-18 12:37:53.000000000 +0200
*************** lookup_type_pair (tree t1, tree t2, htab
*** 3185,3192 ****
  static bool
  compare_type_names_p (tree t1, tree t2)
  {
-   tree variant1 = TYPE_MAIN_VARIANT (t1);
-   tree variant2 = TYPE_MAIN_VARIANT (t2);
    tree name1 = TYPE_NAME (t1);
    tree name2 = TYPE_NAME (t2);
  
--- 3185,3190 ----
*************** compare_type_names_p (tree t1, tree t2)
*** 3215,3228 ****
    if (name1 == name2)
      return true;
  
-   /* If either type has a variant type, compare that.  This finds
-      the case where a struct is typedef'ed in one module but referred
-      to as 'struct foo' in the other; here, the main type for one is
-      'foo', and for the other 'foo_t', but the variants have the same
-      name 'foo'.  */
-   if (variant1 != t1 || variant2 != t2)
-     return compare_type_names_p (variant1, variant2);
- 
    return false;
  }
  
--- 3213,3218 ----
*************** gimple_get_alias_set (tree t)
*** 4183,4188 ****
--- 4173,4208 ----
        if (t1 != t)
  	return get_alias_set (t1);
      }
+   else if (POINTER_TYPE_P (t))
+     {
+       tree t1;
+ 
+       /* Unfortunately, there is no canonical form of a pointer type.
+ 	 In particular, if we have `typedef int I', then `int *', and
+ 	 `I *' are different types.  So, we have to pick a canonical
+ 	 representative.  We do this below.
+ 
+ 	 Technically, this approach is actually more conservative that
+ 	 it needs to be.  In particular, `const int *' and `int *'
+ 	 should be in different alias sets, according to the C and C++
+ 	 standard, since their types are not the same, and so,
+ 	 technically, an `int **' and `const int **' cannot point at
+ 	 the same thing.
+ 
+ 	 But, the standard is wrong.  In particular, this code is
+ 	 legal C++:
+ 
+ 	 int *ip;
+ 	 int **ipp = &ip;
+ 	 const int* const* cipp = ipp;
+ 	 And, it doesn't make sense for that to be legal unless you
+ 	 can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
+ 	 the pointed-to types.  This issue has been reported to the
+ 	 C++ committee.  */
+       t1 = build_type_no_quals (t);
+       if (t1 != t)
+ 	return get_alias_set (t1);
+     }
  
    return -1;
  }
Index: gcc/lto-streamer-out.c
===================================================================
*** gcc/lto-streamer-out.c.orig	2009-08-18 12:37:36.000000000 +0200
--- gcc/lto-streamer-out.c	2009-08-18 12:37:53.000000000 +0200
*************** output_record_start (struct output_block
*** 367,378 ****
  static void
  output_type_ref (struct output_block *ob, tree node)
  {
-   /* FIXME lto.  This is a hack, the use of -funsigned-char should be
-      reflected in the IL by changing every reference to char_type_node
-      into unsigned_char_type_node in pass_ipa_free_lang_data.  */
-   if (flag_signed_char == 0 && node == char_type_node)
-     node = unsigned_char_type_node;
- 
    output_record_start (ob, LTO_type_ref);
    lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
  }
--- 367,372 ----
*************** lto_output_ts_type_tree_pointers (struct
*** 1072,1079 ****
    lto_output_tree_or_ref (ob, TYPE_NAME (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MINVAL (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MAXVAL (expr), ref_p);
-   lto_output_tree_or_ref (ob, TYPE_NEXT_VARIANT (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MAIN_VARIANT (expr), ref_p);
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
--- 1066,1073 ----
    lto_output_tree_or_ref (ob, TYPE_NAME (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MINVAL (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MAXVAL (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_MAIN_VARIANT (expr), ref_p);
+   /* Do not stream out TYPE_NEXT_VARIANT.  */
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
    lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
Index: gcc/lto-streamer.c
===================================================================
*** gcc/lto-streamer.c.orig	2009-08-18 12:37:36.000000000 +0200
--- gcc/lto-streamer.c	2009-08-18 12:37:53.000000000 +0200
*************** lto_streamer_cache_insert_1 (struct lto_
*** 500,511 ****
  
    gcc_assert (t);
  
-   /* If -funsigned-char is given, replace references to 'char' with
-      'unsigned char'.  FIXME lto, this should be done in
-      free_lang_data.  */
-   if (flag_signed_char == 0 && TYPE_P (t) && t == char_type_node)
-     t = unsigned_char_type_node;
- 
    d_entry.base.from = t;
    slot = htab_find_slot (cache->node_map, &d_entry, INSERT);
    if (*slot == NULL)
--- 500,505 ----
*************** lto_streamer_cache_insert_1 (struct lto_
*** 556,561 ****
--- 550,558 ----
  	     stream is not necessary as we will not need to read
  	     forward in the stream.  */
  	  lto_streamer_cache_add_to_node_array (cache, ix, t, -1);
+ 
+ 	  if (getenv ("STREAMER_DEBUG"))
+ 	    fprintf (stderr, "duplicate ");
  	}
  
        /* Indicate that T was already in the cache.  */
*************** lto_streamer_cache_insert_1 (struct lto_
*** 568,573 ****
--- 565,576 ----
    if (offset_p)
      *offset_p = offset; 
  
+   if (getenv ("STREAMER_DEBUG"))
+     {
+       fprintf (stderr, "inserting at %i[%u]%s ", ix, offset,
+ 	       existed_p ? " (present)" : "");
+       print_generic_stmt (stderr, t, 0);
+     }
  
    return existed_p;
  }
*************** lto_streamer_cache_get (struct lto_strea
*** 662,673 ****
     SEEN_NODES.  */
  
  static void
! lto_record_common_node (tree node, VEC(tree, heap) **common_nodes,
  			struct pointer_set_t *seen_nodes)
  {
    if (node == NULL_TREE)
      return;
  
    /* Return if node is already seen.  */
    if (pointer_set_insert (seen_nodes, node))
      return;
--- 665,681 ----
     SEEN_NODES.  */
  
  static void
! lto_record_common_node (tree *nodep, VEC(tree, heap) **common_nodes,
  			struct pointer_set_t *seen_nodes)
  {
+   tree node = *nodep;
+ 
    if (node == NULL_TREE)
      return;
  
+   if (TYPE_P (node))
+     *nodep = node = gimple_register_type (node);
+ 
    /* Return if node is already seen.  */
    if (pointer_set_insert (seen_nodes, node))
      return;
*************** lto_record_common_node (tree node, VEC(t
*** 676,693 ****
  
    if (tree_node_can_be_shared (node))
      {
!       if (TYPE_P (node))
! 	lto_record_common_node (TYPE_MAIN_VARIANT (node), common_nodes,
! 				seen_nodes);
! 
!       if (TREE_CODE (node) == ARRAY_TYPE)
! 	lto_record_common_node (TREE_TYPE (node), common_nodes, seen_nodes);
      }
  }
  
  
! /* Generate a vector of common nodes and register them in the gimple
!    type table as merge targets. */
  
  static VEC(tree,heap) *
  lto_get_common_nodes (void)
--- 684,699 ----
  
    if (tree_node_can_be_shared (node))
      {
!       if (POINTER_TYPE_P (node)
! 	  || TREE_CODE (node) == COMPLEX_TYPE
! 	  || TREE_CODE (node) == ARRAY_TYPE)
! 	lto_record_common_node (&TREE_TYPE (node), common_nodes, seen_nodes);
      }
  }
  
  
! /* Generate a vector of common nodes and make sure they are merged
!    properly according to the the gimple type table.  */
  
  static VEC(tree,heap) *
  lto_get_common_nodes (void)
*************** lto_get_common_nodes (void)
*** 720,753 ****
    
    seen_nodes = pointer_set_create ();
  
-   /* char_type_node is special, we have to prefer merging the other
-      char variants into it because the middle-end has pointer comparisons
-      with it.  */
-   gimple_register_type (char_type_node);
- 
-   for (i = 0; i < TI_MAX; i++)
-     {
-       tree t = global_trees[i];
-       if (t && TYPE_P (t))
- 	gimple_register_type (t);
-       lto_record_common_node (global_trees[i], &common_nodes, seen_nodes);
-     }
- 
    for (i = 0; i < itk_none; i++)
!     {
!       tree t = integer_types[i];
!       if (t && TYPE_P (t))
! 	gimple_register_type (t);
!       lto_record_common_node (integer_types[i], &common_nodes, seen_nodes);
!     }
  
    for (i = 0; i < TYPE_KIND_LAST; i++)
!     {
!       tree t = sizetype_tab[i];
!       if (t && TYPE_P (t))
! 	gimple_register_type (t);
!       lto_record_common_node (sizetype_tab[i], &common_nodes, seen_nodes);
!     }
  
    pointer_set_destroy (seen_nodes);
  
--- 726,739 ----
    
    seen_nodes = pointer_set_create ();
  
    for (i = 0; i < itk_none; i++)
!     lto_record_common_node (&integer_types[i], &common_nodes, seen_nodes);
  
    for (i = 0; i < TYPE_KIND_LAST; i++)
!     lto_record_common_node (&sizetype_tab[i], &common_nodes, seen_nodes);
! 
!   for (i = 0; i < TI_MAX; i++)
!     lto_record_common_node (&global_trees[i], &common_nodes, seen_nodes);
  
    pointer_set_destroy (seen_nodes);
  
Index: gcc/lto-streamer-in.c
===================================================================
*** gcc/lto-streamer-in.c.orig	2009-08-18 12:37:34.000000000 +0200
--- gcc/lto-streamer-in.c	2009-08-18 12:37:53.000000000 +0200
*************** lto_input_ts_type_tree_pointers (struct
*** 1990,1997 ****
    TYPE_NAME (expr) = lto_input_tree (ib, data_in);
    TYPE_MINVAL (expr) = lto_input_tree (ib, data_in);
    TYPE_MAXVAL (expr) = lto_input_tree (ib, data_in);
-   TYPE_NEXT_VARIANT (expr) = lto_input_tree (ib, data_in);
    TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
    TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
--- 1990,1997 ----
    TYPE_NAME (expr) = lto_input_tree (ib, data_in);
    TYPE_MINVAL (expr) = lto_input_tree (ib, data_in);
    TYPE_MAXVAL (expr) = lto_input_tree (ib, data_in);
    TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
+   /* We do not care about TYPE_NEXT_VARIANT.  */
    if (TREE_CODE (expr) == RECORD_TYPE || TREE_CODE (expr) == UNION_TYPE)
      TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
    TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c.orig	2009-08-18 12:37:34.000000000 +0200
--- gcc/lto/lto.c	2009-08-18 12:37:53.000000000 +0200
*************** lto_fixup_type (tree t, void *data)
*** 1215,1222 ****
    LTO_FIXUP_SUBTREE (t->type.minval);
    LTO_FIXUP_SUBTREE (t->type.maxval);
  
!   LTO_FIXUP_SUBTREE (TYPE_NEXT_VARIANT (t));
!   LTO_FIXUP_SUBTREE (TYPE_MAIN_VARIANT (t));
  
    /* Accessor is for derived node types only. */
    LTO_FIXUP_SUBTREE (t->type.binfo);
--- 1215,1222 ----
    LTO_FIXUP_SUBTREE (t->type.minval);
    LTO_FIXUP_SUBTREE (t->type.maxval);
  
!   LTO_REGISTER_TYPE_AND_FIXUP_SUBTREE (TYPE_MAIN_VARIANT (t));
!   TYPE_NEXT_VARIANT (t) = NULL_TREE;
  
    /* Accessor is for derived node types only. */
    LTO_FIXUP_SUBTREE (t->type.binfo);

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-08-18 10:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-17 15:46 [PATCH][LTO] Clean up type variant handling, allow bootstrap Richard Guenther
2009-08-17 16:53 ` Diego Novillo
2009-08-18 12:11   ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).