Hi!

For C++26 P2786R13 I'm afraid I'll need 4 new flags on class types
in struct lang_type (1 bit for trivially_relocatable_if_eligible,
1 for replaceable_if_eligible, 1 for not_trivially_relocatable and
1 for not_replaceable) and there are just 2 bits left.

The following patch is an attempt to save 8 bytes of memory
in those structures when not compiling ObjC or ObjC++ (I think those
are used fairly rarely and the patch keeps the sizes unmodified for
those 2).  The old allocations were 32 bytes for C and 120 bytes
for C++.  The patch moves the objc_info member last in the C++ case
(it was already last in the C case), arranges for GC to skip it
for C and C++ but walk for ObjC and ObjC++ and allocates or
copies over just offsetof bytes instead of sizeof.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2025-06-09  Jakub Jelinek  <ja...@redhat.com>

gcc/c/
        * c-lang.h (union lang_type::maybe_objc_info): New type.
        (struct lang_type): Use union maybe_objc_info info member
        instead of tree objc_info.
        * c-decl.cc (finish_struct): Allocate struct lang_type using
        ggc_internal_cleared_alloc instead of ggc_cleared_alloc,
        and use sizeof (struct lang_type) for ObjC and otherwise
        offsetof (struct lang_type, info) as size.
        (finish_enum): Likewise.
gcc/cp/
        * cp-tree.h (union lang_type::maybe_objc_info): New type.
        (struct lang_type): Use union maybe_objc_info info member
        instead of tree objc_info.
        * lex.cc (copy_lang_type): Use sizeof (struct lang_type)
        just for ObjC++ and otherwise offsetof (struct lang_type, info).
        (maybe_add_lang_type_raw): Likewise.
        (cxx_make_type): Formatting fix.
gcc/objc/
        * objc-act.h (TYPE_OBJC_INFO): Define to info.objc_info
        instead of objc_info.
gcc/objcp/
        * objcp-decl.h (TYPE_OBJC_INFO): Define to info.objc_info
        instead of objc_info.

--- gcc/c/c-lang.h.jj   2025-04-08 14:08:48.398321583 +0200
+++ gcc/c/c-lang.h      2025-06-09 12:50:21.631284689 +0200
@@ -35,10 +35,14 @@ struct GTY(()) lang_type {
   /* In an ENUMERAL_TYPE, the min and max values.  */
   tree enum_min;
   tree enum_max;
-  /* In a RECORD_TYPE, information specific to Objective-C, such
-     as a list of adopted protocols or a pointer to a corresponding
-     @interface.  See objc/objc-act.h for details.  */
-  tree objc_info;
+  union maybe_objc_info {
+    /* If not c_dialect_objc, this part is not even allocated.  */
+    char GTY((tag ("0"))) non_objc;
+    /* In a RECORD_TYPE, information specific to Objective-C, such
+       as a list of adopted protocols or a pointer to a corresponding
+       @interface.  See objc/objc-act.h for details.  */
+    tree GTY((tag ("1"))) objc_info;
+  } GTY ((desc ("c_dialect_objc ()"))) info;
 };
 
 struct GTY(()) lang_decl {
--- gcc/c/c-decl.cc.jj  2025-06-04 17:21:01.111783263 +0200
+++ gcc/c/c-decl.cc     2025-06-09 13:10:56.724561444 +0200
@@ -9790,12 +9790,17 @@ finish_struct (location_t loc, tree t, t
        len += list_length (x);
 
        /* Use the same allocation policy here that make_node uses, to
-         ensure that this lives as long as the rest of the struct decl.
-         All decls in an inline function need to be saved.  */
+          ensure that this lives as long as the rest of the struct decl.
+          All decls in an inline function need to be saved.  */
 
-       space = ggc_cleared_alloc<struct lang_type> ();
-       space2 = (sorted_fields_type *) ggc_internal_alloc
-         (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+       space = ((struct lang_type *)
+                ggc_internal_cleared_alloc (c_dialect_objc ()
+                                            ? sizeof (struct lang_type)
+                                            : offsetof (struct lang_type,
+                                                        info)));
+       space2 = ((sorted_fields_type *)
+                 ggc_internal_alloc (sizeof (struct sorted_fields_type)
+                                     + len * sizeof (tree)));
 
        len = 0;
        space->s = space2;
@@ -10269,7 +10274,10 @@ finish_enum (tree enumtype, tree values,
 
   /* Record the min/max values so that we can warn about bit-field
      enumerations that are too small for the values.  */
-  lt = ggc_cleared_alloc<struct lang_type> ();
+  lt = ((struct lang_type *)
+       ggc_internal_cleared_alloc (c_dialect_objc ()
+                                   ? sizeof (struct lang_type)
+                                   : offsetof (struct lang_type, info)));
   lt->enum_min = minnode;
   lt->enum_max = maxnode;
   TYPE_LANG_SPECIFIC (enumtype) = lt;
--- gcc/cp/cp-tree.h.jj 2025-06-07 09:46:31.602393864 +0200
+++ gcc/cp/cp-tree.h    2025-06-09 12:51:02.905724560 +0200
@@ -2514,12 +2514,16 @@ struct GTY(()) lang_type {
   tree key_method;
   tree decl_list;
   tree befriending_classes;
-  /* In a RECORD_TYPE, information specific to Objective-C++, such
-     as a list of adopted protocols or a pointer to a corresponding
-     @interface.  See objc/objc-act.h for details.  */
-  tree objc_info;
   /* FIXME reuse another field?  */
   tree lambda_expr;
+  union maybe_objc_info {
+    /* If not c_dialect_objc, this part is not even allocated.  */
+    char GTY((tag ("0"))) non_objc;
+    /* In a RECORD_TYPE, information specific to Objective-C, such
+       as a list of adopted protocols or a pointer to a corresponding
+       @interface.  See objc/objc-act.h for details.  */
+    tree GTY((tag ("1"))) objc_info;
+  } GTY ((desc ("c_dialect_objc ()"))) info;
 };
 
 /* We used to have a variant type for lang_type.  Keep the name of the
--- gcc/cp/lex.cc.jj    2025-04-18 11:23:53.809175088 +0200
+++ gcc/cp/lex.cc       2025-06-09 13:05:32.117951517 +0200
@@ -1082,15 +1082,17 @@ copy_lang_type (tree node)
   if (! TYPE_LANG_SPECIFIC (node))
     return;
 
-  auto *lt = (struct lang_type *) ggc_internal_alloc (sizeof (struct 
lang_type));
+  size_t sz = (c_dialect_objc () ? sizeof (struct lang_type)
+              : offsetof (struct lang_type, info));
+  auto *lt = (struct lang_type *) ggc_internal_alloc (sz);
 
-  memcpy (lt, TYPE_LANG_SPECIFIC (node), (sizeof (struct lang_type)));
+  memcpy (lt, TYPE_LANG_SPECIFIC (node), sz);
   TYPE_LANG_SPECIFIC (node) = lt;
 
   if (GATHER_STATISTICS)
     {
       tree_node_counts[(int)lang_type] += 1;
-      tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
+      tree_node_sizes[(int)lang_type] += sz;
     }
 }
 
@@ -1114,14 +1116,15 @@ maybe_add_lang_type_raw (tree t)
   if (!RECORD_OR_UNION_CODE_P (TREE_CODE (t)))
     return false;
 
-  auto *lt = (struct lang_type *) (ggc_internal_cleared_alloc
-                                  (sizeof (struct lang_type)));
+  size_t sz = (c_dialect_objc () ? sizeof (struct lang_type)
+              : offsetof (struct lang_type, info));
+  auto *lt = (struct lang_type *) (ggc_internal_cleared_alloc (sz));
   TYPE_LANG_SPECIFIC (t) = lt;
 
   if (GATHER_STATISTICS)
     {
       tree_node_counts[(int)lang_type] += 1;
-      tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
+      tree_node_sizes[(int)lang_type] += sz;
     }
 
   return true;
@@ -1135,8 +1138,8 @@ cxx_make_type (enum tree_code code MEM_S
   if (maybe_add_lang_type_raw (t))
     {
       /* Set up some flags that give proper default behavior.  */
-      struct c_fileinfo *finfo =
-       get_fileinfo (LOCATION_FILE (input_location));
+      struct c_fileinfo *finfo
+       = get_fileinfo (LOCATION_FILE (input_location));
       SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, finfo->interface_unknown);
       CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only;
     }
--- gcc/objc/objc-act.h.jj      2025-04-08 14:08:54.870231485 +0200
+++ gcc/objc/objc-act.h 2025-06-09 12:54:46.780686364 +0200
@@ -228,7 +228,7 @@ enum objc_property_nullability {
 
 /* The following three macros must be overridden (in objcp/objcp-decl.h)
    for Objective-C++.  */
-#define TYPE_OBJC_INFO(TYPE) TYPE_LANG_SPECIFIC (TYPE)->objc_info
+#define TYPE_OBJC_INFO(TYPE) TYPE_LANG_SPECIFIC (TYPE)->info.objc_info
 #define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type)
 #define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE)                            \
   do {                                                                 \
--- gcc/objcp/objcp-decl.h.jj   2025-04-08 14:08:54.874231429 +0200
+++ gcc/objcp/objcp-decl.h      2025-06-09 12:52:36.351456410 +0200
@@ -60,7 +60,7 @@ extern tree objcp_end_compound_stmt (tre
 #define OBJC_SET_TYPE_NAME(type, name) (TYPE_IDENTIFIER (type) = (name))
 
 #undef TYPE_OBJC_INFO
-#define TYPE_OBJC_INFO(TYPE) LANG_TYPE_CLASS_CHECK (TYPE)->objc_info
+#define TYPE_OBJC_INFO(TYPE) LANG_TYPE_CLASS_CHECK (TYPE)->info.objc_info
 #undef SIZEOF_OBJC_TYPE_LANG_SPECIFIC
 #define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type)
 #undef ALLOC_OBJC_TYPE_LANG_SPECIFIC

        Jakub

Reply via email to