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
>

Reply via email to