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: Optimize type streaming


> Minor comments below, ok with those changes.
Thanks!
This is version of patch I commited after additional testing on building of
some bigger apps with LTO.  The main change (in addition to those requested) is
that I moved the fixups into lto_copy_fields_not_streamed and added loop before
SCC unification. I plan to do more of the copying and it would be getting hard
to walk all the copies in compare_tree_sccs_1.

Second change is that I moved back streaming of DECL_FIELDS. THere are two cases
where we produce variant with different fields - a member pointer with different
qualifiers and gfc_nonrestricted_type that recursively drops restrict qualifiers
from the types.  These seems valid reasons.

I also removed use of TYPE_MAXVAL and TYPE_MINVAL and expanded individual uses.
MAXVAL/MINVAL is kind of hack and even the updated conditions wasn't quite correct
on when these are used and when these needs to be copied.  There are quite few
types that do not use this field at all and there is no need to stream it.

Bootstrapped/regtested x86_64-linux and comitted.

Honza

	* tree-streamer-out.c (pack_ts_type_common_value_fields): Stream if type
	is complete.
	(write_ts_type_common_tree_pointers): Do not stream fields not set for incomplete
	types; do not stream duplicated fields for variants; sanity check that variant
	and type match.
	(write_ts_type_non_common_tree_pointers): Likewise.
	* tree-streamer-in.c (unpack_ts_type_common_value_fields): Mark in TYPE_SIZE whether
	type is complete.
	(lto_input_ts_type_common_tree_pointers): Do same changes as in
	write_ts_type_common_tree_pointers
	(lto_input_ts_type_non_common_tree_pointers): Likewise.

	* lto.c (lto_copy_fields_not_streamed): New function.
	(compare_tree_sccs_1): Do not compare fields shared in between type
	and variant.
	(lto_read_decls): Fixup types first before inserting into hash.
Index: tree-streamer-in.c
===================================================================
--- tree-streamer-in.c	(revision 212098)
+++ tree-streamer-in.c	(working copy)
@@ -357,6 +357,13 @@ unpack_ts_type_common_value_fields (stru
   TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
+  /* This bit represent if type is complete, or if the TYPE_SIZE
+     is non-NULL.  Mark this fact into TYPE_SIZE. The actual values
+     will be filled in later.  */
+  if ((unsigned) bp_unpack_value (bp, 1))
+    TYPE_SIZE (expr) = error_mark_node;
+  else
+    TYPE_SIZE (expr) = NULL_TREE;
   TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp);
   TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp);
   TYPE_ALIAS_SET (expr) = bp_unpack_var_len_int (bp);
@@ -794,19 +801,29 @@ static void
 lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib,
 					struct data_in *data_in, tree expr)
 {
-  TYPE_SIZE (expr) = stream_read_tree (ib, data_in);
-  TYPE_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
-  TYPE_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
+  TYPE_MAIN_VARIANT (expr) = stream_read_tree (ib, data_in);
+
+  /* Variants share most the properties with the main variant.  */
+  if (TYPE_MAIN_VARIANT (expr) == expr)
+    {
+      if (COMPLETE_TYPE_P (expr))
+	{
+	  TYPE_SIZE (expr) = stream_read_tree (ib, data_in);
+	  TYPE_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
+	}
+      TYPE_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
+    }
+  /* The fileds not streamed will be copied by
+     lto_copy_fields_not_streamed.  */
   TYPE_NAME (expr) = stream_read_tree (ib, data_in);
+  TYPE_CONTEXT (expr) = stream_read_tree (ib, data_in);
+  TYPE_STUB_DECL (expr) = stream_read_tree (ib, data_in);
   /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
      reconstructed during fixup.  */
   /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
      during fixup.  */
-  TYPE_MAIN_VARIANT (expr) = stream_read_tree (ib, data_in);
-  TYPE_CONTEXT (expr) = stream_read_tree (ib, data_in);
   /* TYPE_CANONICAL gets re-computed during type merging.  */
   TYPE_CANONICAL (expr) = NULL_TREE;
-  TYPE_STUB_DECL (expr) = stream_read_tree (ib, data_in);
 }
 
 /* Read all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
@@ -818,21 +835,48 @@ lto_input_ts_type_non_common_tree_pointe
 					    struct data_in *data_in,
 					    tree expr)
 {
-  if (TREE_CODE (expr) == ENUMERAL_TYPE)
-    TYPE_VALUES (expr) = stream_read_tree (ib, data_in);
-  else if (TREE_CODE (expr) == ARRAY_TYPE)
-    TYPE_DOMAIN (expr) = stream_read_tree (ib, data_in);
-  else if (RECORD_OR_UNION_TYPE_P (expr))
+  if (TYPE_MAIN_VARIANT (expr) == expr)
+    {
+      if (TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	TYPE_VALUES (expr) = stream_read_tree (ib, data_in);
+      else if (TREE_CODE (expr) == ARRAY_TYPE)
+	TYPE_DOMAIN (expr) = stream_read_tree (ib, data_in);
+
+      /* TYPE_NEXT_PTR_TO and TYPE_NEXT_REF_TO is recomputed.  */
+      if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+	TYPE_VFIELD (expr) = stream_read_tree (ib, data_in);
+      else if ((TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	       || TREE_CODE (expr) == INTEGER_TYPE
+	       || TREE_CODE (expr) == BOOLEAN_TYPE
+	       || TREE_CODE (expr) == REAL_TYPE
+	       || TREE_CODE (expr) == FIXED_POINT_TYPE)
+	TYPE_MIN_VALUE (expr) = stream_read_tree (ib, data_in);
+
+      if (TREE_CODE (expr) == METHOD_TYPE)
+	TYPE_METHOD_BASETYPE (expr) = stream_read_tree (ib, data_in);
+      else if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+	TYPE_METHODS (expr) = stream_read_tree (ib, data_in);
+      else if (TREE_CODE (expr) == OFFSET_TYPE)
+	TYPE_OFFSET_BASETYPE (expr) = stream_read_tree (ib, data_in);
+      else if (TREE_CODE (expr) == ARRAY_TYPE)
+	TYPE_ARRAY_MAX_SIZE (expr) = stream_read_tree (ib, data_in);
+      else if ((TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	       || TREE_CODE (expr) == INTEGER_TYPE
+	       || TREE_CODE (expr) == BOOLEAN_TYPE
+	       || TREE_CODE (expr) == REAL_TYPE
+	       || TREE_CODE (expr) == FIXED_POINT_TYPE)
+	TYPE_MAX_VALUE (expr) = stream_read_tree (ib, data_in);
+
+      if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+	TYPE_BINFO (expr) = stream_read_tree (ib, data_in);
+    }
+  /* The fileds not streamed will be copied by
+     lto_copy_fields_not_streamed.  */
+  if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
     TYPE_FIELDS (expr) = streamer_read_chain (ib, data_in);
   else if (TREE_CODE (expr) == FUNCTION_TYPE
-	   || TREE_CODE (expr) == METHOD_TYPE)
+           || TREE_CODE (expr) == METHOD_TYPE)
     TYPE_ARG_TYPES (expr) = stream_read_tree (ib, data_in);
-
-  if (!POINTER_TYPE_P (expr))
-    TYPE_MINVAL (expr) = stream_read_tree (ib, data_in);
-  TYPE_MAXVAL (expr) = stream_read_tree (ib, data_in);
-  if (RECORD_OR_UNION_TYPE_P (expr))
-    TYPE_BINFO (expr) = stream_read_tree (ib, data_in);
 }
 
 
Index: lto/lto.c
===================================================================
--- lto/lto.c	(revision 212098)
+++ lto/lto.c	(working copy)
@@ -1050,6 +1050,58 @@ lto_register_function_decl_in_symtab (st
 			 decl, get_resolution (data_in, ix));
 }
 
+/* Copy fields that are not streamed but copied from other nodes.  */
+static void
+lto_copy_fields_not_streamed (tree t)
+{
+  if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) != t)
+    {
+      tree mv = TYPE_MAIN_VARIANT (t);
+
+      if (COMPLETE_TYPE_P (t))
+	{
+	  TYPE_SIZE (t) = TYPE_SIZE (mv);
+	  TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (mv);
+	}
+      TYPE_ATTRIBUTES (t) = TYPE_ATTRIBUTES (mv);
+
+      if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_NON_COMMON))
+	{
+	  if (TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t))
+	    TYPE_VALUES (t) = TYPE_VALUES (mv);
+	  else if (TREE_CODE (t) == ARRAY_TYPE)
+	    TYPE_DOMAIN (t) = TYPE_DOMAIN (mv);
+
+          if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t))
+	    TYPE_VFIELD (t) = TYPE_VFIELD (mv);
+	  else if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t))
+		   || TREE_CODE (t) == INTEGER_TYPE
+		   || TREE_CODE (t) == BOOLEAN_TYPE
+		   || TREE_CODE (t) == REAL_TYPE
+		   || TREE_CODE (t) == FIXED_POINT_TYPE)
+	    TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (mv);
+
+	  if (TREE_CODE (t) == METHOD_TYPE)
+	    TYPE_METHOD_BASETYPE (t) = TYPE_METHOD_BASETYPE (mv);
+	  else if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t))
+	    TYPE_METHODS (t) = TYPE_METHODS (mv);
+	  else if (TREE_CODE (t) == OFFSET_TYPE)
+	    TYPE_OFFSET_BASETYPE (t) = TYPE_OFFSET_BASETYPE (mv);
+	  else if (TREE_CODE (t) == ARRAY_TYPE)
+	    TYPE_ARRAY_MAX_SIZE (t) = TYPE_ARRAY_MAX_SIZE (mv);
+	  else if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t))
+		   || TREE_CODE (t) == INTEGER_TYPE
+		   || TREE_CODE (t) == BOOLEAN_TYPE
+		   || TREE_CODE (t) == REAL_TYPE
+		   || TREE_CODE (t) == FIXED_POINT_TYPE)
+	    TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (mv);
+
+	  if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t))
+	    TYPE_BINFO (t) = TYPE_BINFO (mv);
+	}
+    }
+}
 
 /* For the type T re-materialize it in the type variant list and
    the pointer/reference-to chains.  */
@@ -1546,15 +1598,28 @@ compare_tree_sccs_1 (tree t1, tree t2, t
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
     {
-      compare_tree_edges (TYPE_SIZE (t1), TYPE_SIZE (t2));
-      compare_tree_edges (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2));
-      compare_tree_edges (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2));
-      compare_tree_edges (TYPE_NAME (t1), TYPE_NAME (t2));
+      /* See if type is the main variant.  */
+      if (TYPE_MAIN_VARIANT (t1) == t1)
+	{
+	  /* Main variant can match only another main variant.  */
+	  if (TYPE_MAIN_VARIANT (t2) != t2)
+	    return false;
+
+	  compare_tree_edges (TYPE_SIZE (t1), TYPE_SIZE (t2));
+	  compare_tree_edges (TYPE_SIZE_UNIT (t1), TYPE_SIZE_UNIT (t2));
+	  compare_tree_edges (TYPE_ATTRIBUTES (t1), TYPE_ATTRIBUTES (t2));
+	}
+      else
+	/* Compare main variant pointers, but do not compare fields that are
+	   shared in between type and the main variant since those are not
+	   streamed and not copied yet.  */
+        compare_tree_edges (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2));
+
       /* Do not compare TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
 	 reconstructed during fixup.  */
       /* Do not compare TYPE_NEXT_VARIANT, we reconstruct the variant lists
 	 during fixup.  */
-      compare_tree_edges (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2));
+      compare_tree_edges (TYPE_NAME (t1), TYPE_NAME (t2));
       /* ???  Global types from different TUs have non-matching
 	 TRANSLATION_UNIT_DECLs.  Still merge them if they are otherwise
 	 equal.  */
@@ -1569,25 +1634,31 @@ compare_tree_sccs_1 (tree t1, tree t2, t
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
     {
-      if (code == ENUMERAL_TYPE)
-	compare_tree_edges (TYPE_VALUES (t1), TYPE_VALUES (t2));
-      else if (code == ARRAY_TYPE)
-	compare_tree_edges (TYPE_DOMAIN (t1), TYPE_DOMAIN (t2));
-      else if (RECORD_OR_UNION_TYPE_P (t1))
+      if (TYPE_MAIN_VARIANT (t1) == t1)
+	{
+	  if (code == ENUMERAL_TYPE)
+	    compare_tree_edges (TYPE_VALUES (t1), TYPE_VALUES (t2));
+	  else if (code == ARRAY_TYPE)
+	    compare_tree_edges (TYPE_DOMAIN (t1), TYPE_DOMAIN (t2));
+	  else if (RECORD_OR_UNION_TYPE_P (t1))
+	    compare_tree_edges (TYPE_BINFO (t1), TYPE_BINFO (t2));
+	  if (!POINTER_TYPE_P (t1))
+	    compare_tree_edges (TYPE_MINVAL (t1), TYPE_MINVAL (t2));
+	  compare_tree_edges (TYPE_MAXVAL (t1), TYPE_MAXVAL (t2));
+	}
+      if (RECORD_OR_UNION_TYPE_P (t1)
+	  && TYPE_FIELDS (t1) != TYPE_FIELDS (t2))
 	{
 	  tree f1, f2;
+
 	  for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
 	       f1 || f2;
 	       f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
 	    compare_tree_edges (f1, f2);
-	  compare_tree_edges (TYPE_BINFO (t1), TYPE_BINFO (t2));
 	}
-      else if (code == FUNCTION_TYPE
-	       || code == METHOD_TYPE)
+      if (code == FUNCTION_TYPE
+	  || code == METHOD_TYPE)
 	compare_tree_edges (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2));
-      if (!POINTER_TYPE_P (t1))
-	compare_tree_edges (TYPE_MINVAL (t1), TYPE_MINVAL (t2));
-      compare_tree_edges (TYPE_MAXVAL (t1), TYPE_MAXVAL (t2));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_LIST))
@@ -1888,14 +1959,20 @@ lto_read_decls (struct lto_file_decl_dat
 		  || streamer_handle_as_builtin_p (first)))
 	    continue;
 
+	  /* Copy fileds we do not stream before unification so we can compare them
+	     without being worried if they are already initialized.  */
+	  for (unsigned i = 0; i < len; ++i)
+	    lto_copy_fields_not_streamed
+	       (streamer_tree_cache_get_tree (data_in->reader_cache, from + i));
+
 	  /* Try to unify the SCC with already existing ones.  */
 	  if (!flag_ltrans
 	      && unify_scc (data_in->reader_cache, from,
 			    len, scc_entry_len, scc_hash))
 	    continue;
Index: tree-streamer-out.c
===================================================================
--- tree-streamer-out.c	(revision 212098)
+++ tree-streamer-out.c	(working copy)
@@ -313,6 +313,7 @@ pack_ts_type_common_value_fields (struct
   bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
   bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
   bp_pack_value (bp, TYPE_READONLY (expr), 1);
+  bp_pack_value (bp, COMPLETE_TYPE_P (expr), 1);
   bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr));
   bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr));
   /* Make sure to preserve the fact whether the frontend would assign
@@ -698,19 +699,36 @@ static void
 write_ts_type_common_tree_pointers (struct output_block *ob, tree expr,
 				    bool ref_p)
 {
-  stream_write_tree (ob, TYPE_SIZE (expr), ref_p);
-  stream_write_tree (ob, TYPE_SIZE_UNIT (expr), ref_p);
-  stream_write_tree (ob, TYPE_ATTRIBUTES (expr), ref_p);
-  stream_write_tree (ob, TYPE_NAME (expr), ref_p);
-  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
-     reconstructed during fixup.  */
   /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
      during fixup.  */
   stream_write_tree (ob, TYPE_MAIN_VARIANT (expr), ref_p);
+  if (TYPE_MAIN_VARIANT (expr) == expr)
+    {
+      if (COMPLETE_TYPE_P (expr))
+	{
+	  stream_write_tree (ob, TYPE_SIZE (expr), ref_p);
+	  stream_write_tree (ob, TYPE_SIZE_UNIT (expr), ref_p);
+	}
+      stream_write_tree (ob, TYPE_ATTRIBUTES (expr), ref_p);
+    }
+  else
+    {
+      tree mv = TYPE_MAIN_VARIANT (expr);
+
+      if (COMPLETE_TYPE_P (expr))
+	{
+	  gcc_checking_assert (TYPE_SIZE (expr) == TYPE_SIZE (mv));
+	  gcc_checking_assert (TYPE_SIZE_UNIT (expr) == TYPE_SIZE_UNIT (mv));
+	}
+      gcc_checking_assert (TYPE_ATTRIBUTES (expr) == TYPE_ATTRIBUTES (mv));
+    }
+  stream_write_tree (ob, TYPE_NAME (expr), ref_p);
   stream_write_tree (ob, TYPE_CONTEXT (expr), ref_p);
+  stream_write_tree (ob, TYPE_STUB_DECL (expr), ref_p);
+  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
+     reconstructed during fixup.  */
   /* TYPE_CANONICAL is re-computed during type merging, so no need
      to stream it here.  */
-  stream_write_tree (ob, TYPE_STUB_DECL (expr), ref_p);
 }
 
 /* Write all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
@@ -721,21 +739,86 @@ static void
 write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr,
 					bool ref_p)
 {
-  if (TREE_CODE (expr) == ENUMERAL_TYPE)
-    stream_write_tree (ob, TYPE_VALUES (expr), ref_p);
-  else if (TREE_CODE (expr) == ARRAY_TYPE)
-    stream_write_tree (ob, TYPE_DOMAIN (expr), ref_p);
-  else if (RECORD_OR_UNION_TYPE_P (expr))
-    streamer_write_chain (ob, TYPE_FIELDS (expr), ref_p);
-  else if (TREE_CODE (expr) == FUNCTION_TYPE
-	   || TREE_CODE (expr) == METHOD_TYPE)
-    stream_write_tree (ob, TYPE_ARG_TYPES (expr), ref_p);
-
-  if (!POINTER_TYPE_P (expr))
-    stream_write_tree (ob, TYPE_MINVAL (expr), ref_p);
-  stream_write_tree (ob, TYPE_MAXVAL (expr), ref_p);
-  if (RECORD_OR_UNION_TYPE_P (expr))
-    stream_write_tree (ob, TYPE_BINFO (expr), ref_p);
+  if (TYPE_MAIN_VARIANT (expr) == expr)
+    {
+      if (TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	stream_write_tree (ob, TYPE_VALUES (expr), ref_p);
+      else if (TREE_CODE (expr) == ARRAY_TYPE)
+	stream_write_tree (ob, TYPE_DOMAIN (expr), ref_p);
+
+      /* TYPE_NEXT_PTR_TO and TYPE_NEXT_REF_TO is recomputed.  */
+      if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+	stream_write_tree (ob, TYPE_VFIELD (expr), ref_p);
+      else if ((TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	       || TREE_CODE (expr) == INTEGER_TYPE
+	       || TREE_CODE (expr) == BOOLEAN_TYPE
+	       || TREE_CODE (expr) == REAL_TYPE
+	       || TREE_CODE (expr) == FIXED_POINT_TYPE)
+	stream_write_tree (ob, TYPE_MIN_VALUE (expr), ref_p);
+
+      if (TREE_CODE (expr) == METHOD_TYPE)
+	stream_write_tree (ob, TYPE_METHOD_BASETYPE (expr), ref_p);
+      else if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+	stream_write_tree (ob, TYPE_METHODS (expr), ref_p);
+      else if (TREE_CODE (expr) == OFFSET_TYPE)
+	stream_write_tree (ob, TYPE_OFFSET_BASETYPE (expr), ref_p);
+      else if (TREE_CODE (expr) == ARRAY_TYPE)
+	stream_write_tree (ob, TYPE_ARRAY_MAX_SIZE (expr), ref_p);
+      else if ((TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	       || TREE_CODE (expr) == INTEGER_TYPE
+	       || TREE_CODE (expr) == BOOLEAN_TYPE
+	       || TREE_CODE (expr) == REAL_TYPE
+	       || TREE_CODE (expr) == FIXED_POINT_TYPE)
+	stream_write_tree (ob, TYPE_MAX_VALUE (expr), ref_p);
+
+      if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+	stream_write_tree (ob, TYPE_BINFO (expr), ref_p);
+    }
+  else
+    {
+      tree mv = TYPE_MAIN_VARIANT (expr);
+
+      gcc_checking_assert (TYPE_MAIN_VARIANT (mv) == mv);
+      if (TREE_CODE (expr) == ENUMERAL_TYPE)
+        gcc_checking_assert (TYPE_VALUES (expr) == TYPE_VALUES (mv));
+      else if (TREE_CODE (expr) == ARRAY_TYPE)
+        gcc_checking_assert (TYPE_DOMAIN (expr) == TYPE_DOMAIN (mv));
+
+      if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+        gcc_checking_assert (TYPE_VFIELD (expr) == TYPE_VFIELD (mv));
+      else if ((TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	       || TREE_CODE (expr) == INTEGER_TYPE
+	       || TREE_CODE (expr) == BOOLEAN_TYPE
+	       || TREE_CODE (expr) == REAL_TYPE
+	       || TREE_CODE (expr) == FIXED_POINT_TYPE)
+        gcc_checking_assert (TYPE_MINVAL (expr) == TYPE_MINVAL (mv));
+
+      if (TREE_CODE (expr) == METHOD_TYPE)
+        gcc_checking_assert (TYPE_METHOD_BASETYPE (expr) == TYPE_METHOD_BASETYPE (mv));
+      else if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+        gcc_checking_assert (TYPE_METHODS (expr) == TYPE_METHODS (mv));
+      else if (TREE_CODE (expr) == OFFSET_TYPE)
+        gcc_checking_assert (TYPE_OFFSET_BASETYPE (expr) == TYPE_OFFSET_BASETYPE (mv));
+      else if (TREE_CODE (expr) == ARRAY_TYPE)
+        gcc_checking_assert (TYPE_ARRAY_MAX_SIZE (expr) == TYPE_ARRAY_MAX_SIZE (mv));
+      else if ((TREE_CODE (expr) == ENUMERAL_TYPE && COMPLETE_TYPE_P (expr))
+	       || TREE_CODE (expr) == INTEGER_TYPE
+	       || TREE_CODE (expr) == BOOLEAN_TYPE
+	       || TREE_CODE (expr) == REAL_TYPE
+	       || TREE_CODE (expr) == FIXED_POINT_TYPE)
+        gcc_checking_assert (TYPE_MAX_VALUE (expr) == TYPE_MAX_VALUE (mv));
+
+      if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+        gcc_checking_assert (TYPE_BINFO (expr) == TYPE_BINFO (mv));
+    }
+   /* Fortran's gfc_nonrestricted_type may build variant that has different fields.  */
+   if (RECORD_OR_UNION_TYPE_P (expr) && COMPLETE_TYPE_P (expr))
+      streamer_write_chain (ob, TYPE_FIELDS (expr), ref_p);
+   /* Parameters of variant may by modified in case ipa-prop decides to remove
+      some.  */
+   else if (TREE_CODE (expr) == FUNCTION_TYPE
+       || TREE_CODE (expr) == METHOD_TYPE)
+     stream_write_tree (ob, TYPE_ARG_TYPES (expr), ref_p);
 }
 
 


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