Patchwork split tree_type, a.k.a. "tuplifying types"

login
register
mail settings
Submitter Nathan Froyd
Date May 10, 2011, 4:15 p.m.
Message ID <20110510161543.GW23480@codesourcery.com>
Download mbox | patch
Permalink /patch/95138/
State New
Headers show

Comments

Nathan Froyd - May 10, 2011, 4:15 p.m.
tree_type is a fairly big structure, and several of its fields are
overloaded.  This means we waste some space, depending on the type, and
it's also somewhat confusing as to who uses what.

The patch below implements the first step towards "tuplifying types":
those pieces which all types use have been split out into a
tree_type_common structure and those pieces which are overloaded live in
a tree_type_non_common structure.  I choose to implement the
lang-specific bit as a separate substructure, on the off-chance that
some types are fortunate enough to not have langage-specific data
attached to them by the FEs--I have not gone through and made a detailed
check of this, but a skimming shows that nearly every interesting type
that we'd care about shrinking has TYPE_LANG_SPECIFIC set on it by some
FE.

There are several miscellaneous places that need to be fixed up after
the removal of tree_type.  The changes to the Ada, Java, ObjC/C++, and
C++ FEs mainly have to do with direct access to the fields of tree_type,
rather than going through accessor macros.  ggc-page.c creates a bucket
size for sizeof (struct tree_type); I changed it to use 'struct
tree_type_non_common' instead.  There are a couple of places in the
compiler where fields are accessed directly--stor-layout.c and
lto/lto.c--I chose to leave those alone.

After this reorganization, the most that we can shrink most types will
be 2-3 words (possibly more, if we moved TYPE_SIZE around so not all
types needed it).  According to PR 45375, the types on which we should
focus are:

- RECORD_TYPE
- FUNCTION_TYPE
- METHOD_TYPE
- POINTER_TYPE
- INTEGER_TYPE
- REFERENCE_TYPE

RECORD_TYPE is not straightforwardly shrinkable.  FUNCTION_TYPE and
METHOD_TYPE could probably be shrunk by a word or two; likewise for
POINTER_TYPE and REFERENCE_TYPE.  (POINTER_TYPE and REFERENCE_TYPE could
also be made smaller by not allocating an entire TREE_VEC for the one
cached value they put in TYPE_CACHED_VALUES...)  INTEGER_TYPE's binfo
field is used by Ada; INTEGER_TYPE could be shrunk by one word were it
not for this overloading.

Other types can of course be shrunk, but the memory savings from doing
so will be negligible

This patch also opens up the possibility of using language-specific
trees for types as well as decls; the C++ FE's tree_size langhook makes
an attempt to do this, but we never call the tree_size langhook for
types.

I haven't included the refactoring of types yet; I'll let this patch sit
on trunk for a couple of days before trying that.

Testing with all languages in progress on x86_64-unknown-linux-gnu;
ObjC/Go/Ada tests have completed with no regressions; C/C++/Fortran are
looking good as well.  OK to commit?

-Nathan

gcc/ada/
	* gcc-interface/ada-tree.h (TYPE_OBJECT_RECORD_TYPE): Use TYPE_MINVAL.
	(TYPE_GCC_MIN_VALUE): Use TYPE_MINVAL.
	(TYPE_GCC_MAX_VALUE): Use TYPE_MAXVAL.

gcc/cp/
	* cp-tree.h (TYPENAME_TYPE_FULLNAME, TYPEOF_TYPE_EXPR): Use
	TYPE_VALUES_RAW.
	(UNDERLYING_TYPE_TYPE, DECLTYPE_TYPE_EXPR): Likewise.
	(DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P): Likewise.
	(TEMPLATE_TYPE_PARM_INDEX): Likewise.

gcc/
	* ggc-page.c (extra_order_size_table): Use struct
	tree_type_non_common.
	* lto-streamer-in.c (unpack_ts_type_value_fields): Rename to...
	(unpack_ts_type_common_value_fields): ...this.  Update comment.
	(unpack_value_fields): Adjust for renaming.
	(lto_input_ts_type_tree_pointers): Split into...
	(lto_input_ts_type_common_tree_pointer): ...this and...
	(lto_input_ts_type_non_common_tree_pointers): ...this.
	(lto_input_tree_pointers): Adjust for above split.
	* lto-streamer-out.c (pack_ts_type_value_fields): Rename to...
	(pack_ts_type_common_value_fields): ...this.  Update comment.
	(lto_output_ts_type_tree_pointers): Split into...
	(lto_output_ts_type_common_tree_pointers): ...this and...
	(lto_output_ts_type_non_common_tree_pointers): ...this.
	(lto_output_tree_pointers): Adjust for above split.
	* lto-streamer.c (check_handled_ts_structures): Mark TS_TYPE_COMMON,
	TS_TYPE_WITH_LANG_SPECIFIC, and TS_TYPE_NON_COMMON as handled.
	* stor-layout.c (vector_type_mode): Adjust location of mode field.
	* tree.h (MARK_TS_TYPE_COMMON, MARK_TS_TYPE_WITH_LANG_SPECIFIC):
	Define.
	(struct tree_type): Split into...
	(struct tree_type_common: ...this and...
	(struct tree_type_with_lang_specific): ...this and...
	(struct tree_type_non_common): ...this.  Adjust accessor macros
	accordingly.
	(TYPE_VALUES_RAW): Define.
	(union tree_node): Update for above changes.
	* tree.c (tree_node_structure_for_code) [tcc_type]: Return
	TS_TYPE_NON_COMMON.
	(initialize_tree_contains_struct) [TS_TYPE]: Use TS_TYPE_COMMON.
	Add TS_TYPE_WITH_LANG_SPECIFIC and TS_TYPE_NON_COMMON.
	(tree_code_size) [tcc_type]: Use struct tree_type_non_common.
	* treestructu.def (TS_TYPE): Remove.
	(TS_TYPE_COMMON, TS_TYPE_WITH_LANG_SPECIFIC, TS_TYPE_NON_COMMON):
	Define.

gcc/java/
	* java-tree.h (TYPE_ARGUMENT_SIGNATURE): Use TYPE_MINVAL.

gcc/lto/
	* lto.c (lto_ft_type): Use TYPE_MINVAL and TYPE_MAXVAL.  Adjust
	location of binfo field.
	(lto_fixup_prevailing_decls): Likewise.

gcc/objc/
	* objc-act.h (CLASS_NAME, CLASS_SUPER_NAME): Use proper accessors.
	(CLASS_NST_METHODS, CLASS_CLS_METHODS): Likewise.
	(PROTOCOL_NAME, PROTOCOL_NST_METHODS, PROTOCOL_CLS_METHODS): Likewise.
Mike Stump - May 10, 2011, 4:53 p.m.
On May 10, 2011, at 9:15 AM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> The patch below implements the first step towards "tuplifying types":

> OK to commit?

Ok for Objective parts...
>
Nathan Froyd - May 10, 2011, 5:50 p.m.
On Tue, May 10, 2011 at 02:28:06PM -0300, Diego Novillo wrote:
> On Tue, May 10, 2011 at 13:15, Nathan Froyd <froydnj@codesourcery.com> wrote:
> > Other types can of course be shrunk, but the memory savings from doing
> > so will be negligible
> 
> Have you done any measurements on the potential savings?

Only back-of-the-envelope.  I will try to get some numbers after we
start saving memory. :)

> > +static void
> > +lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib,
> > +                                       struct data_in *data_in, tree expr)
> > +{
> > +  TYPE_SIZE (expr) = lto_input_tree (ib, data_in);
> > +  TYPE_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
> > +  TYPE_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
> > +  TYPE_NAME (expr) = lto_input_tree (ib, data_in);
> > +  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  */
> 
> Add some wording as to why not?  This was copied from existing
> comments, but I do not remember why we were doing this.  Not too
> critical, anyway.

I'm not entirely sure; I'm not intimately familiar with how LTO
streaming works. lto.c's lto_ft_type and lto_ft_common purport to
recreate TYPE_{POINTER,REFERENCE}_TO, but I don't immediately see how
that's supposed to work.  I can imagine that we ought to be able to
recreate those fields after reading everything in, and that's why don't
stream them; I just don't know where that's done.

-Nathan
Michael Matz - May 10, 2011, 9:13 p.m.
Hi,

On Tue, 10 May 2011, Nathan Froyd wrote:

> > > +  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  */
> > 
> > Add some wording as to why not?  This was copied from existing
> > comments, but I do not remember why we were doing this.  Not too
> > critical, anyway.
> 
> I'm not entirely sure; I'm not intimately familiar with how LTO
> streaming works. lto.c's lto_ft_type and lto_ft_common purport to
> recreate TYPE_{POINTER,REFERENCE}_TO, but I don't immediately see how
> that's supposed to work.  I can imagine that we ought to be able to
> recreate those fields after reading everything in, and that's why don't
> stream them; I just don't know where that's done.

That is correct.  As soon as we read in a POINTER_TYPE or REFERENCE_TYPE 
we'll reconstruct the target type's TYPE_{POINTER,REFERENCE}_TO fields as 
being the trees we just process.  Type merging would have to overwrite 
them anyway, so it actually saves time and space to not stream or 
reconstruct them, just to have them overwritten during type merging.


Ciao,
Michael.
Richard Guenther - May 11, 2011, 9:02 a.m.
On Tue, May 10, 2011 at 7:50 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Tue, May 10, 2011 at 02:28:06PM -0300, Diego Novillo wrote:
>> On Tue, May 10, 2011 at 13:15, Nathan Froyd <froydnj@codesourcery.com> wrote:
>> > Other types can of course be shrunk, but the memory savings from doing
>> > so will be negligible
>>
>> Have you done any measurements on the potential savings?
>
> Only back-of-the-envelope.  I will try to get some numbers after we
> start saving memory. :)
>
>> > +static void
>> > +lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib,
>> > +                                       struct data_in *data_in, tree expr)
>> > +{
>> > +  TYPE_SIZE (expr) = lto_input_tree (ib, data_in);
>> > +  TYPE_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
>> > +  TYPE_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
>> > +  TYPE_NAME (expr) = lto_input_tree (ib, data_in);
>> > +  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  */
>>
>> Add some wording as to why not?  This was copied from existing
>> comments, but I do not remember why we were doing this.  Not too
>> critical, anyway.
>
> I'm not entirely sure; I'm not intimately familiar with how LTO
> streaming works. lto.c's lto_ft_type and lto_ft_common purport to
> recreate TYPE_{POINTER,REFERENCE}_TO, but I don't immediately see how
> that's supposed to work.  I can imagine that we ought to be able to
> recreate those fields after reading everything in, and that's why don't
> stream them; I just don't know where that's done.

Yes, we're re-creating them to avoid streaming all pointer types that might
be unused before streaming.

One nit:

+struct GTY(()) tree_type_non_common {
+  struct tree_type_with_lang_specific common;

shouldn't that field be named w_lang_specific or something like that,
instead of re-using common?

Richard.

> -Nathan
>
Tom de Vries - May 22, 2011, 6:24 p.m.
Hi,

Now that struct tree_type does not exist anymore, 'sizeof (struct tree_type)'
generates an error in the following assert in fold_checksum_tree:
...
  gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
	       <= sizeof (struct tree_function_decl))
	      && sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
...

This error is triggered with -enable-checking=fold.

Thanks,
- Tom
Nathan Froyd - May 23, 2011, 3:04 p.m.
On 05/22/2011 02:24 PM, Tom de Vries wrote:
> Now that struct tree_type does not exist anymore, 'sizeof (struct tree_type)'
> generates an error in the following assert in fold_checksum_tree:
> ...
>   gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
> 	       <= sizeof (struct tree_function_decl))
> 	      && sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
> ...
> 
> This error is triggered with -enable-checking=fold.

Doh.  Thanks for the report.

The easy fix is s/tree_type/tree_type_non_common/.  But I don't see why the
assert has to even care about tree_type; doesn't:

  gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
              <= sizeof (union tree_node));

accomplish the same thing?

-Nathan

Patch

diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index 2b14b95..588c852 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -174,21 +174,21 @@  do {							 \
    this is a conflict on the minval field, but there doesn't seem to be
    simple fix, so we'll live with this kludge for now.  */
 #define TYPE_OBJECT_RECORD_TYPE(NODE) \
-  (TREE_CHECK2 ((NODE), UNCONSTRAINED_ARRAY_TYPE, ENUMERAL_TYPE)->type.minval)
+  (TYPE_MINVAL (TREE_CHECK2 ((NODE), UNCONSTRAINED_ARRAY_TYPE, ENUMERAL_TYPE)))
 
 /* For numerical types, this is the GCC lower bound of the type.  The GCC
    type system is based on the invariant that an object X of a given type
    cannot hold at run time a value smaller than its lower bound; otherwise
    the behavior is undefined.  The optimizer takes advantage of this and
    considers that the assertion X >= LB is always true.  */
-#define TYPE_GCC_MIN_VALUE(NODE) (NUMERICAL_TYPE_CHECK (NODE)->type.minval)
+#define TYPE_GCC_MIN_VALUE(NODE) (TYPE_MINVAL (NUMERICAL_TYPE_CHECK (NODE)))
 
 /* For numerical types, this is the GCC upper bound of the type.  The GCC
    type system is based on the invariant that an object X of a given type
    cannot hold at run time a value larger than its upper bound; otherwise
    the behavior is undefined.  The optimizer takes advantage of this and
    considers that the assertion X <= UB is always true.  */
-#define TYPE_GCC_MAX_VALUE(NODE) (NUMERICAL_TYPE_CHECK (NODE)->type.maxval)
+#define TYPE_GCC_MAX_VALUE(NODE) (TYPE_MAXVAL (NUMERICAL_TYPE_CHECK (NODE)))
 
 /* For a FUNCTION_TYPE, if the subprogram has parameters passed by copy in/
    copy out, this is the list of nodes used to specify the return values of
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 53092ff..5548e94 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2933,7 +2933,8 @@  more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
    this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
    corresponding TYPE_DECL.  However, this may also be a
    TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'.  */
-#define TYPENAME_TYPE_FULLNAME(NODE) (TYPENAME_TYPE_CHECK (NODE))->type.values
+#define TYPENAME_TYPE_FULLNAME(NODE) \
+  (TYPE_VALUES_RAW (TYPENAME_TYPE_CHECK (NODE)))
 
 /* True if a TYPENAME_TYPE was declared as an "enum".  */
 #define TYPENAME_IS_ENUM_P(NODE) \
@@ -3371,20 +3372,20 @@  more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member)
 
 /* The expression in question for a TYPEOF_TYPE.  */
-#define TYPEOF_TYPE_EXPR(NODE) (TYPEOF_TYPE_CHECK (NODE))->type.values
+#define TYPEOF_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (TYPEOF_TYPE_CHECK (NODE)))
 
 /* The type in question for an UNDERLYING_TYPE.  */
 #define UNDERLYING_TYPE_TYPE(NODE) \
-  (UNDERLYING_TYPE_CHECK (NODE))->type.values
+  (TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))
 
 /* The expression in question for a DECLTYPE_TYPE.  */
-#define DECLTYPE_TYPE_EXPR(NODE) (DECLTYPE_TYPE_CHECK (NODE))->type.values
+#define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))
 
 /* Whether the DECLTYPE_TYPE_EXPR of NODE was originally parsed as an
    id-expression or a member-access expression. When false, it was
    parsed as a full expression.  */
 #define DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P(NODE) \
-  (DECLTYPE_TYPE_CHECK (NODE))->type.string_flag
+  (DECLTYPE_TYPE_CHECK (NODE))->type_common.string_flag
 
 /* These flags indicate that we want different semantics from normal
    decltype: lambda capture just drops references, lambda return also does
@@ -4355,9 +4356,10 @@  enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 
 /* These macros are for accessing the fields of TEMPLATE_TYPE_PARM,
    TEMPLATE_TEMPLATE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM nodes.  */
-#define TEMPLATE_TYPE_PARM_INDEX(NODE)					 \
-  (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,	\
-		BOUND_TEMPLATE_TEMPLATE_PARM))->type.values
+#define TEMPLATE_TYPE_PARM_INDEX(NODE)					\
+  (TYPE_VALUES_RAW (TREE_CHECK3 ((NODE), TEMPLATE_TYPE_PARM,		\
+				 TEMPLATE_TEMPLATE_PARM,		\
+				 BOUND_TEMPLATE_TEMPLATE_PARM)))
 #define TEMPLATE_TYPE_IDX(NODE) \
   (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 #define TEMPLATE_TYPE_LEVEL(NODE) \
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 2c14adb..624f029 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -196,7 +196,7 @@  static const size_t extra_order_size_table[] = {
   sizeof (struct tree_field_decl),
   sizeof (struct tree_parm_decl),
   sizeof (struct tree_var_decl),
-  sizeof (struct tree_type),
+  sizeof (struct tree_type_non_common),
   sizeof (struct function),
   sizeof (struct basic_block_def),
   sizeof (struct cgraph_node),
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 7743c6e..7001321 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -1331,7 +1331,7 @@  extern tree *type_map;
 
 /* If FUNCTION_TYPE or METHOD_TYPE: cache for build_java_argument_signature. */
 #define TYPE_ARGUMENT_SIGNATURE(TYPE) \
-  (TREE_CHECK2 (TYPE, FUNCTION_TYPE, METHOD_TYPE)->type.minval)
+  (TYPE_MINVAL (TREE_CHECK2 (TYPE, FUNCTION_TYPE, METHOD_TYPE)))
 
 /* Given an array type, give the type of the elements. */
 /* FIXME this use of TREE_TYPE conflicts with something or other. */
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 4070299..424dbef 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1745,11 +1745,11 @@  unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
 }
 
 
-/* Unpack all the non-pointer fields of the TS_TYPE structure
+/* Unpack all the non-pointer fields of the TS_TYPE_COMMON structure
    of expression EXPR from bitpack BP.  */
 
 static void
-unpack_ts_type_value_fields (struct bitpack_d *bp, tree expr)
+unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
 {
   enum machine_mode mode;
 
@@ -1821,8 +1821,8 @@  unpack_value_fields (struct bitpack_d *bp, tree expr)
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     unpack_ts_function_decl_value_fields (bp, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
-    unpack_ts_type_value_fields (bp, expr);
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+    unpack_ts_type_common_value_fields (bp, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
     unpack_ts_block_value_fields (bp, expr);
@@ -2099,13 +2099,36 @@  lto_input_ts_function_decl_tree_pointers (struct lto_input_block *ib,
 }
 
 
-/* Read all pointer fields in the TS_TYPE structure of EXPR from input
-   block IB.  DATA_IN contains tables and descriptors for the
+/* Read all pointer fields in the TS_TYPE_COMMON structure of EXPR from
+   input block IB.  DATA_IN contains tables and descriptors for the file
+   being read.  */
+
+static void
+lto_input_ts_type_common_tree_pointers (struct lto_input_block *ib,
+					struct data_in *data_in, tree expr)
+{
+  TYPE_SIZE (expr) = lto_input_tree (ib, data_in);
+  TYPE_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
+  TYPE_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
+  TYPE_NAME (expr) = lto_input_tree (ib, data_in);
+  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  */
+  /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
+     during fixup.  */
+  TYPE_MAIN_VARIANT (expr) = lto_input_tree (ib, data_in);
+  TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
+  /* TYPE_CANONICAL gets re-computed during type merging.  */
+  TYPE_CANONICAL (expr) = NULL_TREE;
+  TYPE_STUB_DECL (expr) = lto_input_tree (ib, data_in);
+}
+
+/* Read all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
+   from input block IB.  DATA_IN contains tables and descriptors for the
    file being read.  */
 
 static void
-lto_input_ts_type_tree_pointers (struct lto_input_block *ib,
-				 struct data_in *data_in, tree expr)
+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) = lto_input_tree (ib, data_in);
@@ -2117,24 +2140,11 @@  lto_input_ts_type_tree_pointers (struct lto_input_block *ib,
 	   || TREE_CODE (expr) == METHOD_TYPE)
     TYPE_ARG_TYPES (expr) = lto_input_tree (ib, data_in);
 
-  TYPE_SIZE (expr) = lto_input_tree (ib, data_in);
-  TYPE_SIZE_UNIT (expr) = lto_input_tree (ib, data_in);
-  TYPE_ATTRIBUTES (expr) = lto_input_tree (ib, data_in);
-  TYPE_NAME (expr) = lto_input_tree (ib, data_in);
-  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO nor
-     TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO.  */
   if (!POINTER_TYPE_P (expr))
     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);
-  /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
-     during fixup.  */
   if (RECORD_OR_UNION_TYPE_P (expr))
     TYPE_BINFO (expr) = lto_input_tree (ib, data_in);
-  TYPE_CONTEXT (expr) = lto_input_tree (ib, data_in);
-  /* TYPE_CANONICAL gets re-computed during type merging.  */
-  TYPE_CANONICAL (expr) = NULL_TREE;
-  TYPE_STUB_DECL (expr) = lto_input_tree (ib, data_in);
 }
 
 
@@ -2370,8 +2380,11 @@  lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     lto_input_ts_function_decl_tree_pointers (ib, data_in, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
-    lto_input_ts_type_tree_pointers (ib, data_in, expr);
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+    lto_input_ts_type_common_tree_pointers (ib, data_in, expr);
+
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
+    lto_input_ts_type_non_common_tree_pointers (ib, data_in, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_LIST))
     lto_input_ts_list_tree_pointers (ib, data_in, expr);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 48ab36d..16019e4 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -488,11 +488,11 @@  pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
 }
 
 
-/* Pack all the non-pointer fields of the TS_TYPE structure
+/* Pack all the non-pointer fields of the TS_TYPE_COMMON structure
    of expression EXPR into bitpack BP.  */
 
 static void
-pack_ts_type_value_fields (struct bitpack_d *bp, tree expr)
+pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
 {
   bp_pack_value (bp, TYPE_PRECISION (expr), 10);
   bp_pack_value (bp, TYPE_MODE (expr), 8);
@@ -560,8 +560,8 @@  pack_value_fields (struct bitpack_d *bp, tree expr)
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     pack_ts_function_decl_value_fields (bp, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
-    pack_ts_type_value_fields (bp, expr);
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+    pack_ts_type_common_value_fields (bp, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
     pack_ts_block_value_fields (bp, expr);
@@ -949,13 +949,35 @@  lto_output_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
 }
 
 
-/* Write all pointer fields in the TS_TYPE structure of EXPR to output
-   block OB.  If REF_P is true, write a reference to EXPR's pointer
-   fields.  */
+/* Write all pointer fields in the TS_TYPE_COMMON structure of EXPR to
+   output block OB.  If REF_P is true, write a reference to EXPR's
+   pointer fields.  */
 
 static void
-lto_output_ts_type_tree_pointers (struct output_block *ob, tree expr,
-				  bool ref_p)
+lto_output_ts_type_common_tree_pointers (struct output_block *ob, tree expr,
+					 bool ref_p)
+{
+  lto_output_tree_or_ref (ob, TYPE_SIZE (expr), ref_p);
+  lto_output_tree_or_ref (ob, TYPE_SIZE_UNIT (expr), ref_p);
+  lto_output_tree_or_ref (ob, TYPE_ATTRIBUTES (expr), ref_p);
+  lto_output_tree_or_ref (ob, TYPE_NAME (expr), ref_p);
+  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  */
+  /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
+     during fixup.  */
+  lto_output_tree_or_ref (ob, TYPE_MAIN_VARIANT (expr), ref_p);
+  lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
+  /* TYPE_CANONICAL is re-computed during type merging, so no need
+     to stream it here.  */
+  lto_output_tree_or_ref (ob, TYPE_STUB_DECL (expr), ref_p);
+}
+
+/* Write all pointer fields in the TS_TYPE_NON_COMMON structure of EXPR
+   to output block OB.  If REF_P is true, write a reference to EXPR's
+   pointer fields.  */
+
+static void
+lto_output_ts_type_non_common_tree_pointers (struct output_block *ob,
+					     tree expr, bool ref_p)
 {
   if (TREE_CODE (expr) == ENUMERAL_TYPE)
     lto_output_tree_or_ref (ob, TYPE_VALUES (expr), ref_p);
@@ -967,24 +989,11 @@  lto_output_ts_type_tree_pointers (struct output_block *ob, tree expr,
 	   || TREE_CODE (expr) == METHOD_TYPE)
     lto_output_tree_or_ref (ob, TYPE_ARG_TYPES (expr), ref_p);
 
-  lto_output_tree_or_ref (ob, TYPE_SIZE (expr), ref_p);
-  lto_output_tree_or_ref (ob, TYPE_SIZE_UNIT (expr), ref_p);
-  lto_output_tree_or_ref (ob, TYPE_ATTRIBUTES (expr), ref_p);
-  lto_output_tree_or_ref (ob, TYPE_NAME (expr), ref_p);
-  /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO nor
-     TYPE_NEXT_PTR_TO or TYPE_NEXT_REF_TO.  */
   if (!POINTER_TYPE_P (expr))
     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 TYPE_NEXT_VARIANT, we reconstruct the variant lists
-     during fixup.  */
   if (RECORD_OR_UNION_TYPE_P (expr))
     lto_output_tree_or_ref (ob, TYPE_BINFO (expr), ref_p);
-  lto_output_tree_or_ref (ob, TYPE_CONTEXT (expr), ref_p);
-  /* TYPE_CANONICAL is re-computed during type merging, so no need
-     to stream it here.  */
-  lto_output_tree_or_ref (ob, TYPE_STUB_DECL (expr), ref_p);
 }
 
 
@@ -1183,8 +1192,11 @@  lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     lto_output_ts_function_decl_tree_pointers (ob, expr, ref_p);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_TYPE))
-    lto_output_ts_type_tree_pointers (ob, expr, ref_p);
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
+    lto_output_ts_type_common_tree_pointers (ob, expr, ref_p);
+
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
+    lto_output_ts_type_non_common_tree_pointers (ob, expr, ref_p);
 
   if (CODE_CONTAINS_STRUCT (code, TS_LIST))
     lto_output_ts_list_tree_pointers (ob, expr, ref_p);
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index be54305..bca654b 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -292,7 +292,9 @@  check_handled_ts_structures (void)
   handled_p[TS_CONST_DECL] = true;
   handled_p[TS_TYPE_DECL] = true;
   handled_p[TS_FUNCTION_DECL] = true;
-  handled_p[TS_TYPE] = true;
+  handled_p[TS_TYPE_COMMON] = true;
+  handled_p[TS_TYPE_WITH_LANG_SPECIFIC] = true;
+  handled_p[TS_TYPE_NON_COMMON] = true;
   handled_p[TS_LIST] = true;
   handled_p[TS_VEC] = true;
   handled_p[TS_EXP] = true;
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 8344022..a5c7474 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -385,11 +385,11 @@  lto_ft_type (tree 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);
+    LTO_FIXUP_TREE (TYPE_MINVAL (t));
+  LTO_FIXUP_TREE (TYPE_MAXVAL (t));
 
   /* Accessor is for derived node types only. */
-  LTO_FIXUP_TREE (t->type.binfo);
+  LTO_FIXUP_TREE (t->type_non_common.binfo);
 
   LTO_FIXUP_TREE (TYPE_CONTEXT (t));
 
@@ -2079,9 +2079,9 @@  lto_fixup_prevailing_decls (tree 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_MINVAL (t));
+      LTO_SET_PREVAIL (TYPE_MAXVAL (t));
+      LTO_SET_PREVAIL (t->type_non_common.binfo);
 
       LTO_SET_PREVAIL (TYPE_CONTEXT (t));
 
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index d31bb7d..99551a8 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -152,24 +152,24 @@  typedef enum objc_property_assign_semantics {
    CATEGORY_INTERFACE_TYPE, CATEGORY_IMPLEMENTATION_TYPE,
    PROTOCOL_INTERFACE_TYPE */
 /* CLASS_NAME is the name of the class.  */
-#define CLASS_NAME(CLASS) ((CLASS)->type.name)
+#define CLASS_NAME(CLASS) (TYPE_NAME (CLASS))
 /* CLASS_SUPER_NAME is the name of the superclass, or, in the case of
    categories, it is the name of the category itself.  */
-#define CLASS_SUPER_NAME(CLASS) (TYPE_CHECK (CLASS)->type.context)
+#define CLASS_SUPER_NAME(CLASS) (TYPE_CONTEXT (CLASS))
 #define CLASS_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0)
 #define CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 1)
-#define CLASS_NST_METHODS(CLASS) ((CLASS)->type.minval)
-#define CLASS_CLS_METHODS(CLASS) ((CLASS)->type.maxval)
+#define CLASS_NST_METHODS(CLASS) (TYPE_MINVAL (CLASS))
+#define CLASS_CLS_METHODS(CLASS) (TYPE_MAXVAL (CLASS))
 #define CLASS_STATIC_TEMPLATE(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2)
 #define CLASS_CATEGORY_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 3)
 #define CLASS_PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 4)
 #define TOTAL_CLASS_RAW_IVARS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 5)
 #define CLASS_HAS_EXCEPTION_ATTR(CLASS) (TYPE_LANG_FLAG_0 (CLASS))
 
-#define PROTOCOL_NAME(CLASS) ((CLASS)->type.name)
+#define PROTOCOL_NAME(CLASS) (TYPE_NAME (CLASS))
 #define PROTOCOL_LIST(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 0)
-#define PROTOCOL_NST_METHODS(CLASS) ((CLASS)->type.minval)
-#define PROTOCOL_CLS_METHODS(CLASS) ((CLASS)->type.maxval)
+#define PROTOCOL_NST_METHODS(CLASS) (TYPE_MINVAL (CLASS))
+#define PROTOCOL_CLS_METHODS(CLASS) (TYPE_MAXVAL (CLASS))
 #define PROTOCOL_FORWARD_DECL(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 1)
 #define PROTOCOL_DEFINED(CLASS) TREE_USED (CLASS)
 #define PROTOCOL_OPTIONAL_CLS_METHODS(CLASS) TREE_VEC_ELT (TYPE_LANG_SLOT_1 (CLASS), 2)
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 12ccd80..55c1e30 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -2088,12 +2088,12 @@  vector_type_mode (const_tree t)
 
   gcc_assert (TREE_CODE (t) == VECTOR_TYPE);
 
-  mode = t->type.mode;
+  mode = t->type_common.mode;
   if (VECTOR_MODE_P (mode)
       && (!targetm.vector_mode_supported_p (mode)
 	  || !have_regs_of_mode[mode]))
     {
-      enum machine_mode innermode = TREE_TYPE (t)->type.mode;
+      enum machine_mode innermode = TREE_TYPE (t)->type_common.mode;
 
       /* For integers, try mapping it to a same-sized scalar mode.  */
       if (GET_MODE_CLASS (innermode) == MODE_INT)
diff --git a/gcc/tree.c b/gcc/tree.c
index 7fd078d..c38d24b 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -303,7 +303,7 @@  tree_node_structure_for_code (enum tree_code code)
 	  }
       }
     case tcc_type:
-      return TS_TYPE;
+      return TS_TYPE_NON_COMMON;
     case tcc_reference:
     case tcc_comparison:
     case tcc_unary:
@@ -385,7 +385,7 @@  initialize_tree_contains_struct (void)
 
 	case TS_IDENTIFIER:
 	case TS_DECL_MINIMAL:
-	case TS_TYPE:
+	case TS_TYPE_COMMON:
 	case TS_LIST:
 	case TS_VEC:
 	case TS_EXP:
@@ -398,6 +398,14 @@  initialize_tree_contains_struct (void)
 	  MARK_TS_COMMON (code);
 	  break;
 
+	case TS_TYPE_WITH_LANG_SPECIFIC:
+	  MARK_TS_TYPE_COMMON (code);
+	  break;
+
+	case TS_TYPE_NON_COMMON:
+	  MARK_TS_TYPE_WITH_LANG_SPECIFIC (code);
+	  break;
+
 	case TS_DECL_COMMON:
 	  MARK_TS_DECL_MINIMAL (code);
 	  break;
@@ -639,7 +647,7 @@  tree_code_size (enum tree_code code)
       }
 
     case tcc_type:  /* a type node */
-      return sizeof (struct tree_type);
+      return sizeof (struct tree_type_non_common);
 
     case tcc_reference:   /* a reference */
     case tcc_expression:  /* an expression */
diff --git a/gcc/tree.h b/gcc/tree.h
index 4cf1730..84ca4a3 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -68,6 +68,18 @@  extern unsigned char tree_contains_struct[MAX_TREE_CODES][64];
     tree_contains_struct[C][TS_COMMON] = 1;		\
   } while (0)
 
+#define MARK_TS_TYPE_COMMON(C)				\
+  do {							\
+    MARK_TS_COMMON (C);					\
+    tree_contains_struct[C][TS_TYPE_COMMON] = 1;	\
+  } while (0)
+
+#define MARK_TS_TYPE_WITH_LANG_SPECIFIC(C)		\
+  do {							\
+    MARK_TS_TYPE_COMMON (C);				\
+    tree_contains_struct[C][TS_TYPE_WITH_LANG_SPECIFIC] = 1;	\
+  } while (0)
+
 #define MARK_TS_DECL_MINIMAL(C)				\
   do {							\
     MARK_TS_COMMON (C);					\
@@ -2110,39 +2122,24 @@  struct GTY(()) tree_block {
    type.  Note also that some of the front-ends also overload these fields,
    so they must be checked as well.  */
 
-#define TYPE_UID(NODE) (TYPE_CHECK (NODE)->type.uid)
-#define TYPE_SIZE(NODE) (TYPE_CHECK (NODE)->type.size)
-#define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type.size_unit)
-#define TYPE_VALUES(NODE) (ENUMERAL_TYPE_CHECK (NODE)->type.values)
-#define TYPE_DOMAIN(NODE) (ARRAY_TYPE_CHECK (NODE)->type.values)
-#define TYPE_FIELDS(NODE) (RECORD_OR_UNION_CHECK (NODE)->type.values)
-#define TYPE_CACHED_VALUES(NODE) (TYPE_CHECK(NODE)->type.values)
-#define TYPE_METHODS(NODE) (RECORD_OR_UNION_CHECK (NODE)->type.maxval)
-#define TYPE_VFIELD(NODE) (RECORD_OR_UNION_CHECK (NODE)->type.minval)
-#define TYPE_ARG_TYPES(NODE) (FUNC_OR_METHOD_CHECK (NODE)->type.values)
-#define TYPE_METHOD_BASETYPE(NODE) (FUNC_OR_METHOD_CHECK (NODE)->type.maxval)
-#define TYPE_OFFSET_BASETYPE(NODE) (OFFSET_TYPE_CHECK (NODE)->type.maxval)
-#define TYPE_POINTER_TO(NODE) (TYPE_CHECK (NODE)->type.pointer_to)
-#define TYPE_REFERENCE_TO(NODE) (TYPE_CHECK (NODE)->type.reference_to)
-#define TYPE_NEXT_PTR_TO(NODE) (POINTER_TYPE_CHECK (NODE)->type.minval)
-#define TYPE_NEXT_REF_TO(NODE) (REFERENCE_TYPE_CHECK (NODE)->type.minval)
-#define TYPE_MIN_VALUE(NODE) (NUMERICAL_TYPE_CHECK (NODE)->type.minval)
-#define TYPE_MAX_VALUE(NODE) (NUMERICAL_TYPE_CHECK (NODE)->type.maxval)
-#define TYPE_PRECISION(NODE) (TYPE_CHECK (NODE)->type.precision)
-#define TYPE_NAME(NODE) (TYPE_CHECK (NODE)->type.name)
-#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type.next_variant)
-#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant)
-#define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type.context)
-#define TYPE_MAXVAL(NODE) (TYPE_CHECK (NODE)->type.maxval)
-#define TYPE_MINVAL(NODE) (TYPE_CHECK (NODE)->type.minval)
+#define TYPE_UID(NODE) (TYPE_CHECK (NODE)->type_common.uid)
+#define TYPE_SIZE(NODE) (TYPE_CHECK (NODE)->type_common.size)
+#define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type_common.size_unit)
+#define TYPE_POINTER_TO(NODE) (TYPE_CHECK (NODE)->type_common.pointer_to)
+#define TYPE_REFERENCE_TO(NODE) (TYPE_CHECK (NODE)->type_common.reference_to)
+#define TYPE_PRECISION(NODE) (TYPE_CHECK (NODE)->type_common.precision)
+#define TYPE_NAME(NODE) (TYPE_CHECK (NODE)->type_common.name)
+#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.next_variant)
+#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.main_variant)
+#define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type_common.context)
 
 /* Vector types need to check target flags to determine type.  */
 extern enum machine_mode vector_type_mode (const_tree);
 #define TYPE_MODE(NODE) \
   (TREE_CODE (TYPE_CHECK (NODE)) == VECTOR_TYPE \
-   ? vector_type_mode (NODE) : (NODE)->type.mode)
+   ? vector_type_mode (NODE) : (NODE)->type_common.mode)
 #define SET_TYPE_MODE(NODE, MODE) \
-  (TYPE_CHECK (NODE)->type.mode = (MODE))
+  (TYPE_CHECK (NODE)->type_common.mode = (MODE))
 
 /* The "canonical" type for this type node, which is used by frontends to
    compare the type for equality with another type.  If two types are
@@ -2160,7 +2157,7 @@  extern enum machine_mode vector_type_mode (const_tree);
    to each other without a conversion.  The middle-end also makes sure
    to assign the same alias-sets to the type partition with equal
    TYPE_CANONICAL of their unqualified variants.  */
-#define TYPE_CANONICAL(NODE) (TYPE_CHECK (NODE)->type.canonical)
+#define TYPE_CANONICAL(NODE) (TYPE_CHECK (NODE)->type_common.canonical)
 /* Indicates that the type node requires structural equality
    checks.  The compiler will need to look at the composition of the
    type to determine whether it is equal to another type, rather than
@@ -2172,35 +2169,28 @@  extern enum machine_mode vector_type_mode (const_tree);
    type node requires structural equality.  */
 #define SET_TYPE_STRUCTURAL_EQUALITY(NODE) (TYPE_CANONICAL (NODE) = NULL_TREE)
 
-#define TYPE_LANG_SPECIFIC(NODE) (TYPE_CHECK (NODE)->type.lang_specific)
 #define TYPE_IBIT(NODE) (GET_MODE_IBIT (TYPE_MODE (NODE)))
 #define TYPE_FBIT(NODE) (GET_MODE_FBIT (TYPE_MODE (NODE)))
 
-/* For record and union types, information about this type, as a base type
-   for itself.  */
-#define TYPE_BINFO(NODE) (RECORD_OR_UNION_CHECK(NODE)->type.binfo)
-
-/* For non record and union types, used in a language-dependent way.  */
-#define TYPE_LANG_SLOT_1(NODE) (NOT_RECORD_OR_UNION_CHECK(NODE)->type.binfo)
-
 /* The (language-specific) typed-based alias set for this type.
    Objects whose TYPE_ALIAS_SETs are different cannot alias each
    other.  If the TYPE_ALIAS_SET is -1, no alias set has yet been
    assigned to this type.  If the TYPE_ALIAS_SET is 0, objects of this
    type can alias objects of any type.  */
-#define TYPE_ALIAS_SET(NODE) (TYPE_CHECK (NODE)->type.alias_set)
+#define TYPE_ALIAS_SET(NODE) (TYPE_CHECK (NODE)->type_common.alias_set)
 
 /* Nonzero iff the typed-based alias set for this type has been
    calculated.  */
-#define TYPE_ALIAS_SET_KNOWN_P(NODE) (TYPE_CHECK (NODE)->type.alias_set != -1)
+#define TYPE_ALIAS_SET_KNOWN_P(NODE) \
+  (TYPE_CHECK (NODE)->type_common.alias_set != -1)
 
 /* A TREE_LIST of IDENTIFIER nodes of the attributes that apply
    to this type.  */
-#define TYPE_ATTRIBUTES(NODE) (TYPE_CHECK (NODE)->type.attributes)
+#define TYPE_ATTRIBUTES(NODE) (TYPE_CHECK (NODE)->type_common.attributes)
 
 /* The alignment necessary for objects of this type.
    The value is an int, measured in bits.  */
-#define TYPE_ALIGN(NODE) (TYPE_CHECK (NODE)->type.align)
+#define TYPE_ALIGN(NODE) (TYPE_CHECK (NODE)->type_common.align)
 
 /* 1 if the alignment for this type was requested by "aligned" attribute,
    0 if it is the default for this type.  */
@@ -2221,7 +2211,8 @@  extern enum machine_mode vector_type_mode (const_tree);
 /* In a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE, it means the type
    has BLKmode only because it lacks the alignment requirement for
    its size.  */
-#define TYPE_NO_FORCE_BLK(NODE) (TYPE_CHECK (NODE)->type.no_force_blk_flag)
+#define TYPE_NO_FORCE_BLK(NODE) \
+  (TYPE_CHECK (NODE)->type_common.no_force_blk_flag)
 
 /* In an INTEGER_TYPE, it means the type represents a size.  We use
    this both for validity checking and to permit optimizations that
@@ -2232,7 +2223,7 @@  extern enum machine_mode vector_type_mode (const_tree);
    properties.  Expressions whose type have TYPE_IS_SIZETYPE set are
    always actual sizes.  */
 #define TYPE_IS_SIZETYPE(NODE) \
-  (INTEGER_TYPE_CHECK (NODE)->type.no_force_blk_flag)
+  (INTEGER_TYPE_CHECK (NODE)->type_common.no_force_blk_flag)
 
 /* Nonzero in a type considered volatile as a whole.  */
 #define TYPE_VOLATILE(NODE) (TYPE_CHECK (NODE)->base.volatile_flag)
@@ -2242,7 +2233,7 @@  extern enum machine_mode vector_type_mode (const_tree);
 
 /* If nonzero, this type is `restrict'-qualified, in the C sense of
    the term.  */
-#define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type.restrict_flag)
+#define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type_common.restrict_flag)
 
 /* If nonzero, type's name shouldn't be emitted into debug info.  */
 #define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.nameless_flag)
@@ -2287,13 +2278,13 @@  enum cv_qualifier
    | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT))
 
 /* These flags are available for each language front end to use internally.  */
-#define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type.lang_flag_0)
-#define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type.lang_flag_1)
-#define TYPE_LANG_FLAG_2(NODE) (TYPE_CHECK (NODE)->type.lang_flag_2)
-#define TYPE_LANG_FLAG_3(NODE) (TYPE_CHECK (NODE)->type.lang_flag_3)
-#define TYPE_LANG_FLAG_4(NODE) (TYPE_CHECK (NODE)->type.lang_flag_4)
-#define TYPE_LANG_FLAG_5(NODE) (TYPE_CHECK (NODE)->type.lang_flag_5)
-#define TYPE_LANG_FLAG_6(NODE) (TYPE_CHECK (NODE)->type.lang_flag_6)
+#define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_0)
+#define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_1)
+#define TYPE_LANG_FLAG_2(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_2)
+#define TYPE_LANG_FLAG_3(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_3)
+#define TYPE_LANG_FLAG_4(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_4)
+#define TYPE_LANG_FLAG_5(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_5)
+#define TYPE_LANG_FLAG_6(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_6)
 
 /* Used to keep track of visited nodes in tree traversals.  This is set to
    0 by copy_node and make_node.  */
@@ -2302,22 +2293,16 @@  enum cv_qualifier
 /* If set in an ARRAY_TYPE, indicates a string type (for languages
    that distinguish string from array of char).
    If set in a INTEGER_TYPE, indicates a character type.  */
-#define TYPE_STRING_FLAG(NODE) (TYPE_CHECK (NODE)->type.string_flag)
-
-/* If non-NULL, this is an upper bound of the size (in bytes) of an
-   object of the given ARRAY_TYPE.  This allows temporaries to be
-   allocated.  */
-#define TYPE_ARRAY_MAX_SIZE(ARRAY_TYPE) \
-  (ARRAY_TYPE_CHECK (ARRAY_TYPE)->type.maxval)
+#define TYPE_STRING_FLAG(NODE) (TYPE_CHECK (NODE)->type_common.string_flag)
 
 /* For a VECTOR_TYPE, this is the number of sub-parts of the vector.  */
 #define TYPE_VECTOR_SUBPARTS(VECTOR_TYPE) \
   (((unsigned HOST_WIDE_INT) 1) \
-   << VECTOR_TYPE_CHECK (VECTOR_TYPE)->type.precision)
+   << VECTOR_TYPE_CHECK (VECTOR_TYPE)->type_common.precision)
 
 /* Set precision to n when we have 2^n sub-parts of the vector.  */
 #define SET_TYPE_VECTOR_SUBPARTS(VECTOR_TYPE, X) \
-  (VECTOR_TYPE_CHECK (VECTOR_TYPE)->type.precision = exact_log2 (X))
+  (VECTOR_TYPE_CHECK (VECTOR_TYPE)->type_common.precision = exact_log2 (X))
 
 /* Nonzero in a VECTOR_TYPE if the frontends should not emit warnings
    about missing conversions to other vector types of the same size.  */
@@ -2327,20 +2312,20 @@  enum cv_qualifier
 /* Indicates that objects of this type must be initialized by calling a
    function when they are created.  */
 #define TYPE_NEEDS_CONSTRUCTING(NODE) \
-  (TYPE_CHECK (NODE)->type.needs_constructing_flag)
+  (TYPE_CHECK (NODE)->type_common.needs_constructing_flag)
 
 /* Indicates that a UNION_TYPE object should be passed the same way that
    the first union alternative would be passed, or that a RECORD_TYPE
    object should be passed the same way that the first (and only) member
    would be passed.  */
 #define TYPE_TRANSPARENT_AGGR(NODE) \
-  (RECORD_OR_UNION_CHECK (NODE)->type.transparent_aggr_flag)
+  (RECORD_OR_UNION_CHECK (NODE)->type_common.transparent_aggr_flag)
 
 /* For an ARRAY_TYPE, indicates that it is not permitted to take the
    address of a component of the type.  This is the counterpart of
    DECL_NONADDRESSABLE_P for arrays, see the definition of this flag.  */
 #define TYPE_NONALIASED_COMPONENT(NODE) \
-  (ARRAY_TYPE_CHECK (NODE)->type.transparent_aggr_flag)
+  (ARRAY_TYPE_CHECK (NODE)->type_common.transparent_aggr_flag)
 
 /* Indicated that objects of this type should be laid out in as
    compact a way as possible.  */
@@ -2350,7 +2335,7 @@  enum cv_qualifier
    Values are: 0 (unknown), 1 (false), 2 (true).  Never access
    this field directly.  */
 #define TYPE_CONTAINS_PLACEHOLDER_INTERNAL(NODE) \
-  (TYPE_CHECK (NODE)->type.contains_placeholder_bits)
+  (TYPE_CHECK (NODE)->type_common.contains_placeholder_bits)
 
 /* The debug output functions use the symtab union field to store
    information specific to the debugging format.  The different debug
@@ -2361,15 +2346,18 @@  enum cv_qualifier
 
 /* Symtab field as an integer.  Used by stabs generator in dbxout.c to
    hold the type's number in the generated stabs.  */
-#define TYPE_SYMTAB_ADDRESS(NODE) (TYPE_CHECK (NODE)->type.symtab.address)
+#define TYPE_SYMTAB_ADDRESS(NODE) \
+  (TYPE_CHECK (NODE)->type_common.symtab.address)
 
 /* Symtab field as a string.  Used by COFF generator in sdbout.c to
    hold struct/union type tag names.  */
-#define TYPE_SYMTAB_POINTER(NODE) (TYPE_CHECK (NODE)->type.symtab.pointer)
+#define TYPE_SYMTAB_POINTER(NODE) \
+  (TYPE_CHECK (NODE)->type_common.symtab.pointer)
 
 /* Symtab field as a pointer to a DWARF DIE.  Used by DWARF generator
    in dwarf2out.c to point to the DIE generated for the type.  */
-#define TYPE_SYMTAB_DIE(NODE) (TYPE_CHECK (NODE)->type.symtab.die)
+#define TYPE_SYMTAB_DIE(NODE) \
+  (TYPE_CHECK (NODE)->type_common.symtab.die)
 
 /* The garbage collector needs to know the interpretation of the
    symtab field.  These constants represent the different types in the
@@ -2381,9 +2369,8 @@  enum cv_qualifier
 
 struct die_struct;
 
-struct GTY(()) tree_type {
+struct GTY(()) tree_type_common {
   struct tree_common common;
-  tree values;
   tree size;
   tree size_unit;
   tree attributes;
@@ -2417,16 +2404,70 @@  struct GTY(()) tree_type {
     struct die_struct * GTY ((tag ("TYPE_SYMTAB_IS_DIE"))) die;
   } GTY ((desc ("debug_hooks->tree_type_symtab_field"))) symtab;
   tree name;
-  tree minval;
-  tree maxval;
   tree next_variant;
   tree main_variant;
-  tree binfo;
   tree context;
   tree canonical;
+};
+
+#define TYPE_LANG_SPECIFIC(NODE) \
+  (TYPE_CHECK (NODE)->type_with_lang_specific.lang_specific)
+
+struct GTY(()) tree_type_with_lang_specific {
+  struct tree_type_common common;
   /* Points to a structure whose details depend on the language in use.  */
   struct lang_type *lang_specific;
 };
+
+#define TYPE_VALUES(NODE) (ENUMERAL_TYPE_CHECK (NODE)->type_non_common.values)
+#define TYPE_DOMAIN(NODE) (ARRAY_TYPE_CHECK (NODE)->type_non_common.values)
+#define TYPE_FIELDS(NODE) \
+  (RECORD_OR_UNION_CHECK (NODE)->type_non_common.values)
+#define TYPE_CACHED_VALUES(NODE) (TYPE_CHECK(NODE)->type_non_common.values)
+#define TYPE_ARG_TYPES(NODE) \
+  (FUNC_OR_METHOD_CHECK (NODE)->type_non_common.values)
+#define TYPE_VALUES_RAW(NODE) (TYPE_CHECK(NODE)->type_non_common.values)
+
+#define TYPE_METHODS(NODE) \
+  (RECORD_OR_UNION_CHECK (NODE)->type_non_common.maxval)
+#define TYPE_VFIELD(NODE) \
+  (RECORD_OR_UNION_CHECK (NODE)->type_non_common.minval)
+#define TYPE_METHOD_BASETYPE(NODE) \
+  (FUNC_OR_METHOD_CHECK (NODE)->type_non_common.maxval)
+#define TYPE_OFFSET_BASETYPE(NODE) \
+  (OFFSET_TYPE_CHECK (NODE)->type_non_common.maxval)
+#define TYPE_MAXVAL(NODE) (TYPE_CHECK (NODE)->type_non_common.maxval)
+#define TYPE_MINVAL(NODE) (TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_NEXT_PTR_TO(NODE) \
+  (POINTER_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_NEXT_REF_TO(NODE) \
+  (REFERENCE_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_MIN_VALUE(NODE) \
+  (NUMERICAL_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_MAX_VALUE(NODE) \
+  (NUMERICAL_TYPE_CHECK (NODE)->type_non_common.maxval)
+
+/* If non-NULL, this is an upper bound of the size (in bytes) of an
+   object of the given ARRAY_TYPE_NON_COMMON.  This allows temporaries to be
+   allocated.  */
+#define TYPE_ARRAY_MAX_SIZE(ARRAY_TYPE) \
+  (ARRAY_TYPE_CHECK (ARRAY_TYPE)->type_non_common.maxval)
+
+/* For record and union types, information about this type, as a base type
+   for itself.  */
+#define TYPE_BINFO(NODE) (RECORD_OR_UNION_CHECK(NODE)->type_non_common.binfo)
+
+/* For non record and union types, used in a language-dependent way.  */
+#define TYPE_LANG_SLOT_1(NODE) \
+  (NOT_RECORD_OR_UNION_CHECK(NODE)->type_non_common.binfo)
+
+struct GTY(()) tree_type_non_common {
+  struct tree_type_with_lang_specific common;
+  tree values;
+  tree minval;
+  tree maxval;
+  tree binfo;
+};
 
 /* Define accessor macros for information about type inheritance
    and basetypes.
@@ -3584,7 +3625,11 @@  union GTY ((ptr_alias (union lang_tree_node),
   struct tree_function_decl GTY ((tag ("TS_FUNCTION_DECL"))) function_decl;
   struct tree_translation_unit_decl GTY ((tag ("TS_TRANSLATION_UNIT_DECL")))
     translation_unit_decl;
-  struct tree_type GTY ((tag ("TS_TYPE"))) type;
+  struct tree_type_common GTY ((tag ("TS_TYPE_COMMON"))) type_common;
+  struct tree_type_with_lang_specific GTY ((tag ("TS_TYPE_WITH_LANG_SPECIFIC")))
+    type_with_lang_specific;
+  struct tree_type_non_common GTY ((tag ("TS_TYPE_NON_COMMON")))
+    type_non_common;
   struct tree_list GTY ((tag ("TS_LIST"))) list;
   struct tree_vec GTY ((tag ("TS_VEC"))) vec;
   struct tree_exp GTY ((tag ("TS_EXP"))) exp;
diff --git a/gcc/treestruct.def b/gcc/treestruct.def
index b65bdc2..1e5f32d 100644
--- a/gcc/treestruct.def
+++ b/gcc/treestruct.def
@@ -54,7 +54,9 @@  DEFTREESTRUCT(TS_CONST_DECL, "const decl")
 DEFTREESTRUCT(TS_TYPE_DECL, "label decl")
 DEFTREESTRUCT(TS_FUNCTION_DECL, "function decl")
 DEFTREESTRUCT(TS_TRANSLATION_UNIT_DECL, "translation-unit decl")
-DEFTREESTRUCT(TS_TYPE, "type")
+DEFTREESTRUCT(TS_TYPE_COMMON, "type common")
+DEFTREESTRUCT(TS_TYPE_WITH_LANG_SPECIFIC, "type with lang-specific")
+DEFTREESTRUCT(TS_TYPE_NON_COMMON, "type non-common")
 DEFTREESTRUCT(TS_LIST, "list")
 DEFTREESTRUCT(TS_VEC, "vec")
 DEFTREESTRUCT(TS_EXP, "exp")