]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-streamer-out.c (pack_ts_type_common_value_fields): Stream if type is complete.
authorJan Hubicka <hubicka@ucw.cz>
Sat, 28 Jun 2014 23:40:46 +0000 (01:40 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 28 Jun 2014 23:40:46 +0000 (23:40 +0000)
* 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.

From-SVN: r212114

gcc/ChangeLog
gcc/lto/ChangeLog
gcc/lto/lto.c
gcc/tree-streamer-in.c
gcc/tree-streamer-out.c

index 17a510dbd49b47947ce7930294ea440e8e71410e..34e7c931333b0de9b7e1304504932fc8b97b8ef7 100644 (file)
@@ -1,3 +1,17 @@
+2014-06-28  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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.
+
 2014-06-28  Jan Hubicka  <hubicka@ucw.cz>
 
        * cgraph.c (dump_cgraph_node): Dump init&fini priorities.
index 7d2a0a65ecbc27260f6b16b9ab23c5a84f56c829..63ebdebc877fb206564234e911201762176acba4 100644 (file)
@@ -1,3 +1,10 @@
+2014-06-28  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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.
+
 2014-06-25  Martin Liska  <mliska@suse.cz>
 
        * lto/lto-partition.c (add_references_to_partition): New IPA REF function
index f5ed5c31a8c2fcca44cc145b954a30fd4b264f8e..701447c680272a5f688a00bb10bd4df08aff0c13 100644 (file)
@@ -1050,6 +1050,57 @@ lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl,
                         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 +1597,28 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
 
   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 +1633,31 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
 
   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,13 +1958,19 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
                  || 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;
 
-         /* Do remaining fixup tasks for prevailing nodes.  */
+         /* /* Do remaining fixup tasks for prevailing nodes.  */
          bool seen_type = false;
          for (unsigned i = 0; i < len; ++i)
            {
index ee1c955f159bf901425bfa5050d9590015158aed..93d30605ea79e95a43a4604f4423d8aa9b9be3d6 100644 (file)
@@ -357,6 +357,13 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
   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_pointers (struct lto_input_block *ib,
                                            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 52e714ef29ebec81aea578f993061f13af88e658..287deb75c19af7aa9203a7eb18b498d7c84c4b23 100644 (file)
@@ -313,6 +313,7 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
   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,37 @@ 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);
+
+      gcc_checking_assert (TYPE_MAIN_VARIANT (mv) == mv);
+      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 +740,85 @@ 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);
+
+      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);
 }