On Mon, Jun 9, 2025 at 7:28 PM Jakub Jelinek <ja...@redhat.com> wrote: > > 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?
Just as reminder, not necessarily to make use of them, there are 10 spare bits in tree_base::u.bits, we could add lang_flag_{7,8,...} Richard. > 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 >