https://gcc.gnu.org/g:3ce7b67bc53ecc07da7eddcf13d815e4733376c8

commit r16-1431-g3ce7b67bc53ecc07da7eddcf13d815e4733376c8
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Thu Jun 12 08:33:38 2025 +0200

    c, c++: Save 8 bytes of memory in lang_type for non-ObjC*
    
    For C++26 P2786R13 I'm afraid I'll need 4-6 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 perhaps 2 bits whether the last 2 have been
    computed already) 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.
    
    2025-06-12  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.

Diff:
---
 gcc/c/c-decl.cc        | 22 +++++++++++++++-------
 gcc/c/c-lang.h         | 12 ++++++++----
 gcc/cp/cp-tree.h       | 12 ++++++++----
 gcc/cp/lex.cc          | 19 +++++++++++--------
 gcc/objc/objc-act.h    |  2 +-
 gcc/objcp/objcp-decl.h |  2 +-
 6 files changed, 44 insertions(+), 25 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 2b0bd663ba91..8bbd6ebc66ad 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9790,12 +9790,17 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
        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.  */
-
-       space = ggc_cleared_alloc<struct lang_type> ();
-       space2 = (sorted_fields_type *) ggc_internal_alloc
-         (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+          ensure that this lives as long as the rest of the struct decl.
+          All decls in an inline function need to be saved.  */
+
+       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, tree 
attributes)
 
   /* 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;
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 4b93d184dbca..2e99b4d86176 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -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 {
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3cf4a7654b39..d663d6ec2256 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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
diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc
index 12af81ed078c..08a634830f52 100644
--- a/gcc/cp/lex.cc
+++ b/gcc/cp/lex.cc
@@ -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_STAT_DECL)
   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;
     }
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 39c29893fb0f..c7f92595d46e 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -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 {                                                                 \
diff --git a/gcc/objcp/objcp-decl.h b/gcc/objcp/objcp-decl.h
index 747fdae0dfdd..24896207d3dc 100644
--- a/gcc/objcp/objcp-decl.h
+++ b/gcc/objcp/objcp-decl.h
@@ -60,7 +60,7 @@ extern tree objcp_end_compound_stmt (tree, int);
 #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

Reply via email to