https://gcc.gnu.org/g:a7dd44c02ec1047166b4bacc3faa6255c816da2a

commit r14-10277-ga7dd44c02ec1047166b4bacc3faa6255c816da2a
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Mon Jun 3 23:11:06 2024 +0200

    rs6000: Fix up PCH in --enable-host-pie builds [PR115324]
    
    PCH doesn't work properly in --enable-host-pie configurations on
    powerpc*-linux*.
    The problem is that the rs6000_builtin_info and rs6000_instance_info
    arrays mix pointers to .rodata/.data (bifname and attr_string point
    to string literals in .rodata section, and the next member is either NULL
    or &rs6000_instance_info[XXX]) and GC member (tree fntype).
    Now, for normal GC this works just fine, we emit
      {
        &rs6000_instance_info[0].fntype,
        1 * (RS6000_INST_MAX),
        sizeof (rs6000_instance_info[0]),
        &gt_ggc_mx_tree_node,
        &gt_pch_nx_tree_node
      },
      {
        &rs6000_builtin_info[0].fntype,
        1 * (RS6000_BIF_MAX),
        sizeof (rs6000_builtin_info[0]),
        &gt_ggc_mx_tree_node,
        &gt_pch_nx_tree_node
      },
    GC roots which are strided and thus cover only the fntype members of all
    the elements of the two arrays.
    For PCH though it actually results in saving those huge arrays (one is
    130832 bytes, another 81568 bytes) into the .gch files and loading them back
    in full.  While the bifname and attr_string and next pointers are marked as
    GTY((skip)), they are actually saved to point to the .rodata and .data
    sections of the process which writes the PCH, but because cc1/cc1plus etc.
    are position independent executables with --enable-host-pie, when it is
    loaded from the PCH file, it can point in a completely different addresses
    where nothing is mapped at all or some random different thing appears at.
    While gengtype supports the callback option, that one is meant for
    relocatable function pointers and doesn't work in the case of GTY arrays
    inside of .data section anyway.
    
    So, either we'd need to add some further GTY extensions, or the following
    patch instead reworks it such that the fntype members which were the only
    reason for PCH in those arrays are moved to separate arrays.
    
    Size-wise in .data sections it is (in bytes):
    
                                 vanilla    patched
    rs6000_builtin_info          130832     110704
    rs6000_instance_info          81568      40784
    rs6000_overload_info           7392       7392
    rs6000_builtin_info_fntype        0      10064
    rs6000_instance_info_fntype       0      20392
    sum                          219792     189336
    
    where previously we saved/restored for PCH those 130832+81568 bytes, now we
    save/restore just 10064+20392 bytes, so this change is beneficial for the
    data section size.
    
    Unfortunately, it grows the size of the rs6000_init_generated_builtins
    function, vanilla had 218328 bytes, patched has 228668.
    
    When I applied
     void
     rs6000_init_generated_builtins ()
     {
    +  bifdata *rs6000_builtin_info_p;
    +  tree *rs6000_builtin_info_fntype_p;
    +  ovlddata *rs6000_instance_info_p;
    +  tree *rs6000_instance_info_fntype_p;
    +  ovldrecord *rs6000_overload_info_p;
    +  __asm ("" : "=r" (rs6000_builtin_info_p) : "0" (rs6000_builtin_info));
    +  __asm ("" : "=r" (rs6000_builtin_info_fntype_p) : "0" 
(rs6000_builtin_info_fntype));
    +  __asm ("" : "=r" (rs6000_instance_info_p) : "0" (rs6000_instance_info));
    +  __asm ("" : "=r" (rs6000_instance_info_fntype_p) : "0" 
(rs6000_instance_info_fntype));
    +  __asm ("" : "=r" (rs6000_overload_info_p) : "0" (rs6000_overload_info));
    +  #define rs6000_builtin_info rs6000_builtin_info_p
    +  #define rs6000_builtin_info_fntype rs6000_builtin_info_fntype_p
    +  #define rs6000_instance_info rs6000_instance_info_p
    +  #define rs6000_instance_info_fntype rs6000_instance_info_fntype_p
    +  #define rs6000_overload_info rs6000_overload_info_p
    +
    hack by hand, the size of the function is 209700 though, so if really
    wanted, we could add __attribute__((__noipa__)) to the function when
    building with recent enough GCC and pass pointers to the first elements
    of the 5 arrays to the function as arguments.  If you want such a change,
    could that be done incrementally?
    
    2024-06-03  Jakub Jelinek  <ja...@redhat.com>
    
            PR target/115324
            * config/rs6000/rs6000-gen-builtins.cc (write_decls): Remove
            GTY markup from struct bifdata and struct ovlddata and remove their
            fntype members.  Change next member in struct ovlddata and
            first_instance member of struct ovldrecord to have int type rather
            than struct ovlddata *.  Remove GTY markup from rs6000_builtin_info
            and rs6000_instance_info arrays, declare new
            rs6000_builtin_info_fntype and rs6000_instance_info_fntype arrays,
            which have GTY markup.
            (write_bif_static_init): Adjust for the above changes.
            (write_ovld_static_init): Likewise.
            (write_init_bif_table): Likewise.
            (write_init_ovld_table): Likewise.
            * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Likewise.
            * config/rs6000/rs6000-c.cc (find_instance): Likewise.  Make static.
            (altivec_resolve_overloaded_builtin): Adjust for the above changes.
    
    (cherry picked from commit 4cf2de9b5268224816a3d53fdd2c3d799ebfd9c8)

Diff:
---
 gcc/config/rs6000/rs6000-builtin.cc      |  2 +-
 gcc/config/rs6000/rs6000-c.cc            | 62 ++++++++++++++-------------
 gcc/config/rs6000/rs6000-gen-builtins.cc | 72 +++++++++++++++++---------------
 3 files changed, 72 insertions(+), 64 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
b/gcc/config/rs6000/rs6000-builtin.cc
index 320affd79e3..e96d5157e4d 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -845,7 +845,7 @@ rs6000_init_builtins (void)
          enum rs6000_gen_builtins fn_code = (enum rs6000_gen_builtins) i;
          if (!rs6000_builtin_is_supported (fn_code))
            continue;
-         tree fntype = rs6000_builtin_info[i].fntype;
+         tree fntype = rs6000_builtin_info_fntype[i];
          tree t = TREE_TYPE (fntype);
          fprintf (stderr, "%s %s (", rs6000_type_string (t),
                   rs6000_builtin_info[i].bifname);
diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc
index bd493ab87c5..6229c503bd0 100644
--- a/gcc/config/rs6000/rs6000-c.cc
+++ b/gcc/config/rs6000/rs6000-c.cc
@@ -1664,22 +1664,25 @@ resolve_vec_step (resolution *res, vec<tree, va_gc> 
*arglist, unsigned nargs)
    true.  If we don't match, return error_mark_node and leave
    UNSUPPORTED_BUILTIN alone.  */
 
-tree
-find_instance (bool *unsupported_builtin, ovlddata **instance,
+static tree
+find_instance (bool *unsupported_builtin, int *instance,
               rs6000_gen_builtins instance_code,
               rs6000_gen_builtins fcode,
               tree *types, tree *args, int nargs)
 {
-  while (*instance && (*instance)->bifid != instance_code)
-    *instance = (*instance)->next;
+  while (*instance != -1
+        && rs6000_instance_info[*instance].bifid != instance_code)
+    *instance = rs6000_instance_info[*instance].next;
 
-  ovlddata *inst = *instance;
-  gcc_assert (inst != NULL);
+  int inst = *instance;
+  gcc_assert (inst != -1);
   /* It is possible for an instance to require a data type that isn't
-     defined on this target, in which case inst->fntype will be NULL.  */
-  if (!inst->fntype)
+     defined on this target, in which case rs6000_instance_info_fntype[inst]
+     will be NULL.  */
+  if (!rs6000_instance_info_fntype[inst])
     return error_mark_node;
-  tree fntype = rs6000_builtin_info[inst->bifid].fntype;
+  rs6000_gen_builtins bifid = rs6000_instance_info[inst].bifid;
+  tree fntype = rs6000_builtin_info_fntype[bifid];
   tree argtype = TYPE_ARG_TYPES (fntype);
   bool args_compatible = true;
 
@@ -1696,12 +1699,12 @@ find_instance (bool *unsupported_builtin, ovlddata 
**instance,
 
   if (args_compatible)
     {
-      if (rs6000_builtin_decl (inst->bifid, false) != error_mark_node
-         && rs6000_builtin_is_supported (inst->bifid))
+      if (rs6000_builtin_decl (bifid, false) != error_mark_node
+         && rs6000_builtin_is_supported (bifid))
        {
-         tree ret_type = TREE_TYPE (inst->fntype);
+         tree ret_type = TREE_TYPE (rs6000_instance_info_fntype[inst]);
          return altivec_build_resolved_builtin (args, nargs, fntype, ret_type,
-                                                inst->bifid, fcode);
+                                                bifid, fcode);
        }
       else
        *unsupported_builtin = true;
@@ -1884,11 +1887,11 @@ altivec_resolve_overloaded_builtin (location_t loc, 
tree fndecl,
   bool unsupported_builtin = false;
   rs6000_gen_builtins instance_code;
   bool supported = false;
-  ovlddata *instance = rs6000_overload_info[adj_fcode].first_instance;
-  gcc_assert (instance != NULL);
+  int instance = rs6000_overload_info[adj_fcode].first_instance;
+  gcc_assert (instance != -1);
 
   /* Functions with no arguments can have only one overloaded instance.  */
-  gcc_assert (nargs > 0 || !instance->next);
+  gcc_assert (nargs > 0 || rs6000_instance_info[instance].next == -1);
 
   /* Standard overload processing involves determining whether an instance
      exists that is type-compatible with the overloaded function call.  In
@@ -1989,16 +1992,18 @@ altivec_resolve_overloaded_builtin (location_t loc, 
tree fndecl,
       /* Standard overload processing.  Look for an instance with compatible
         parameter types.  If it is supported in the current context, resolve
         the overloaded call to that instance.  */
-      for (; instance != NULL; instance = instance->next)
+      for (; instance != -1; instance = rs6000_instance_info[instance].next)
        {
+         tree fntype = rs6000_instance_info_fntype[instance];
+         rs6000_gen_builtins bifid = rs6000_instance_info[instance].bifid;
          /* It is possible for an instance to require a data type that isn't
-            defined on this target, in which case instance->fntype will be
+            defined on this target, in which case fntype will be
             NULL.  */
-         if (!instance->fntype)
+         if (!fntype)
            continue;
 
          bool mismatch = false;
-         tree nextparm = TYPE_ARG_TYPES (instance->fntype);
+         tree nextparm = TYPE_ARG_TYPES (fntype);
 
          for (unsigned int arg_i = 0;
               arg_i < nargs && nextparm != NULL;
@@ -2016,15 +2021,14 @@ altivec_resolve_overloaded_builtin (location_t loc, 
tree fndecl,
          if (mismatch)
            continue;
 
-         supported = rs6000_builtin_is_supported (instance->bifid);
-         if (rs6000_builtin_decl (instance->bifid, false) != error_mark_node
+         supported = rs6000_builtin_is_supported (bifid);
+         if (rs6000_builtin_decl (bifid, false) != error_mark_node
              && supported)
            {
-             tree fntype = rs6000_builtin_info[instance->bifid].fntype;
-             tree ret_type = TREE_TYPE (instance->fntype);
+             tree ret_type = TREE_TYPE (fntype);
+             fntype = rs6000_builtin_info_fntype[bifid];
              return altivec_build_resolved_builtin (args, nargs, fntype,
-                                                    ret_type, instance->bifid,
-                                                    fcode);
+                                                    ret_type, bifid, fcode);
            }
          else
            {
@@ -2041,12 +2045,12 @@ altivec_resolve_overloaded_builtin (location_t loc, 
tree fndecl,
        {
          /* Indicate that the instantiation of the overloaded builtin
             name is not available with the target flags in effect.  */
-         rs6000_gen_builtins fcode = (rs6000_gen_builtins) instance->bifid;
+         rs6000_gen_builtins bifid = rs6000_instance_info[instance].bifid;
+         rs6000_gen_builtins fcode = (rs6000_gen_builtins) bifid;
          rs6000_invalid_builtin (fcode);
          /* Provide clarity of the relationship between the overload
             and the instantiation.  */
-         const char *internal_name
-           = rs6000_builtin_info[instance->bifid].bifname;
+         const char *internal_name = rs6000_builtin_info[bifid].bifname;
          rich_location richloc (line_table, input_location);
          inform (&richloc,
                  "overloaded builtin %qs is implemented by builtin %qs",
diff --git a/gcc/config/rs6000/rs6000-gen-builtins.cc 
b/gcc/config/rs6000/rs6000-gen-builtins.cc
index e32d1e2d134..7ae932220bb 100644
--- a/gcc/config/rs6000/rs6000-gen-builtins.cc
+++ b/gcc/config/rs6000/rs6000-gen-builtins.cc
@@ -2261,20 +2261,19 @@ write_decls (void)
   fprintf (header_file, "};\n\n");
 
   fprintf (header_file, "#define PPC_MAXRESTROPNDS 3\n");
-  fprintf (header_file, "struct GTY(()) bifdata\n");
+  fprintf (header_file, "struct bifdata\n");
   fprintf (header_file, "{\n");
-  fprintf (header_file, "  const char *GTY((skip(\"\"))) bifname;\n");
-  fprintf (header_file, "  bif_enable GTY((skip(\"\"))) enable;\n");
-  fprintf (header_file, "  tree fntype;\n");
-  fprintf (header_file, "  insn_code GTY((skip(\"\"))) icode;\n");
-  fprintf (header_file, "  int  nargs;\n");
-  fprintf (header_file, "  int  bifattrs;\n");
-  fprintf (header_file, "  int  restr_opnd[PPC_MAXRESTROPNDS];\n");
-  fprintf (header_file, "  restriction GTY((skip(\"\"))) 
restr[PPC_MAXRESTROPNDS];\n");
-  fprintf (header_file, "  int  restr_val1[PPC_MAXRESTROPNDS];\n");
-  fprintf (header_file, "  int  restr_val2[PPC_MAXRESTROPNDS];\n");
-  fprintf (header_file, "  const char *GTY((skip(\"\"))) attr_string;\n");
-  fprintf (header_file, "  rs6000_gen_builtins GTY((skip(\"\"))) 
assoc_bif;\n");
+  fprintf (header_file, "  const char *bifname;\n");
+  fprintf (header_file, "  bif_enable enable;\n");
+  fprintf (header_file, "  insn_code icode;\n");
+  fprintf (header_file, "  int nargs;\n");
+  fprintf (header_file, "  int bifattrs;\n");
+  fprintf (header_file, "  int restr_opnd[PPC_MAXRESTROPNDS];\n");
+  fprintf (header_file, "  restriction restr[PPC_MAXRESTROPNDS];\n");
+  fprintf (header_file, "  int restr_val1[PPC_MAXRESTROPNDS];\n");
+  fprintf (header_file, "  int restr_val2[PPC_MAXRESTROPNDS];\n");
+  fprintf (header_file, "  const char *attr_string;\n");
+  fprintf (header_file, "  rs6000_gen_builtins assoc_bif;\n");
   fprintf (header_file, "};\n\n");
 
   fprintf (header_file, "#define bif_init_bit\t\t(0x00000001)\n");
@@ -2353,24 +2352,28 @@ write_decls (void)
   fprintf (header_file, "\n");
 
   fprintf (header_file,
-          "extern GTY(()) bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n");
+          "extern bifdata rs6000_builtin_info[RS6000_BIF_MAX];\n\n");
 
-  fprintf (header_file, "struct GTY(()) ovlddata\n");
+  fprintf (header_file,
+          "extern GTY(()) tree 
rs6000_builtin_info_fntype[RS6000_BIF_MAX];\n\n");
+
+  fprintf (header_file, "struct ovlddata\n");
   fprintf (header_file, "{\n");
-  fprintf (header_file, "  const char *GTY((skip(\"\"))) bifname;\n");
-  fprintf (header_file, "  rs6000_gen_builtins GTY((skip(\"\"))) bifid;\n");
-  fprintf (header_file, "  tree fntype;\n");
-  fprintf (header_file, "  ovlddata *GTY((skip(\"\"))) next;\n");
+  fprintf (header_file, "  const char *bifname;\n");
+  fprintf (header_file, "  rs6000_gen_builtins bifid;\n");
+  fprintf (header_file, "  int next;\n");
   fprintf (header_file, "};\n\n");
 
   fprintf (header_file, "struct ovldrecord\n");
   fprintf (header_file, "{\n");
   fprintf (header_file, "  const char *ovld_name;\n");
-  fprintf (header_file, "  ovlddata *first_instance;\n");
+  fprintf (header_file, "  int first_instance;\n");
   fprintf (header_file, "};\n\n");
 
   fprintf (header_file,
-          "extern GTY(()) ovlddata rs6000_instance_info[RS6000_INST_MAX];\n");
+          "extern ovlddata rs6000_instance_info[RS6000_INST_MAX];\n");
+  fprintf (header_file, "extern GTY(()) tree "
+          "rs6000_instance_info_fntype[RS6000_INST_MAX];\n");
   fprintf (header_file, "extern ovldrecord rs6000_overload_info[];\n\n");
 
   fprintf (header_file, "extern void rs6000_init_generated_builtins ();\n\n");
@@ -2481,7 +2484,7 @@ write_bif_static_init (void)
   fprintf (init_file, "bifdata rs6000_builtin_info[RS6000_BIF_MAX] =\n");
   fprintf (init_file, "  {\n");
   fprintf (init_file, "    { /* RS6000_BIF_NONE: */\n");
-  fprintf (init_file, "      \"\", ENB_ALWAYS, 0, CODE_FOR_nothing, 0,\n");
+  fprintf (init_file, "      \"\", ENB_ALWAYS, CODE_FOR_nothing, 0,\n");
   fprintf (init_file, "      0, {0, 0, 0}, {RES_NONE, RES_NONE, RES_NONE},\n");
   fprintf (init_file, "      {0, 0, 0}, {0, 0, 0}, \"\", RS6000_BIF_NONE\n");
   fprintf (init_file, "    },\n");
@@ -2493,8 +2496,6 @@ write_bif_static_init (void)
               bifp->proto.bifname);
       fprintf (init_file, "      /* enable*/\t%s,\n",
               enable_string[bifp->stanza]);
-      /* Type must be instantiated at run time.  */
-      fprintf (init_file, "      /* fntype */\t0,\n");
       fprintf (init_file, "      /* icode */\tCODE_FOR_%s,\n",
               bifp->patname);
       fprintf (init_file, "      /* nargs */\t%d,\n",
@@ -2586,6 +2587,8 @@ write_bif_static_init (void)
       fprintf (init_file, "    },\n");
     }
   fprintf (init_file, "  };\n\n");
+
+  fprintf (init_file, "tree rs6000_builtin_info_fntype[RS6000_BIF_MAX];\n\n");
 }
 
 /* Write the decls and initializers for rs6000_overload_info[] and
@@ -2598,7 +2601,7 @@ write_ovld_static_init (void)
           "- RS6000_OVLD_NONE] =\n");
   fprintf (init_file, "  {\n");
   fprintf (init_file, "    { /* RS6000_OVLD_NONE: */\n");
-  fprintf (init_file, "      \"\", NULL\n");
+  fprintf (init_file, "      \"\", -1\n");
   fprintf (init_file, "    },\n");
   for (int i = 0; i <= curr_ovld_stanza; i++)
     {
@@ -2607,7 +2610,7 @@ write_ovld_static_init (void)
       fprintf (init_file, "      /* ovld_name */\t\"%s\",\n",
               ovld_stanzas[i].intern_name);
       /* First-instance must currently be instantiated at run time.  */
-      fprintf (init_file, "      /* first_instance */\tNULL\n");
+      fprintf (init_file, "      /* first_instance */\t-1\n");
       fprintf (init_file, "    },\n");
     }
   fprintf (init_file, "  };\n\n");
@@ -2615,7 +2618,7 @@ write_ovld_static_init (void)
   fprintf (init_file, "ovlddata rs6000_instance_info[RS6000_INST_MAX] =\n");
   fprintf (init_file, "  {\n");
   fprintf (init_file, "    { /* RS6000_INST_NONE: */\n");
-  fprintf (init_file, "      \"\", RS6000_BIF_NONE, NULL_TREE, NULL\n");
+  fprintf (init_file, "      \"\", RS6000_BIF_NONE, -1\n");
   fprintf (init_file, "    },\n");
   for (int i = 0; i <= curr_ovld; i++)
     {
@@ -2625,19 +2628,20 @@ write_ovld_static_init (void)
               ovlds[i].proto.bifname);
       fprintf (init_file, "      /* bifid */\tRS6000_BIF_%s,\n",
               ovlds[i].bif_id_name);
-      /* Type must be instantiated at run time.  */
-      fprintf (init_file, "      /* fntype */\t0,\n");
       fprintf (init_file, "      /* next */\t");
       if (i < curr_ovld
          && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname))
        fprintf (init_file,
-                "&rs6000_instance_info[RS6000_INST_%s]\n",
+                "RS6000_INST_%s\n",
                 ovlds[i+1].ovld_id_name);
       else
-       fprintf (init_file, "NULL\n");
+       fprintf (init_file, "-1\n");
       fprintf (init_file, "    },\n");
     }
   fprintf (init_file, "  };\n\n");
+
+  fprintf (init_file,
+          "tree rs6000_instance_info_fntype[RS6000_INST_MAX];\n\n");
 }
 
 /* Write code to initialize the built-in function table.  */
@@ -2647,7 +2651,7 @@ write_init_bif_table (void)
   for (int i = 0; i <= curr_bif; i++)
     {
       fprintf (init_file,
-              "  rs6000_builtin_info[RS6000_BIF_%s].fntype"
+              "  rs6000_builtin_info_fntype[RS6000_BIF_%s]"
               "\n    = %s;\n",
               bifs[i].idname, bifs[i].fndecl);
 
@@ -2736,7 +2740,7 @@ write_init_ovld_table (void)
   for (int i = 0; i <= curr_ovld; i++)
     {
       fprintf (init_file,
-              "  rs6000_instance_info[RS6000_INST_%s].fntype"
+              "  rs6000_instance_info_fntype[RS6000_INST_%s]"
               "\n    = %s;\n",
               ovlds[i].ovld_id_name, ovlds[i].fndecl);
 
@@ -2793,7 +2797,7 @@ write_init_ovld_table (void)
                   ".first_instance\n",
                   stanza->stanza_id);
          fprintf (init_file,
-                  "    = &rs6000_instance_info[RS6000_INST_%s];\n\n",
+                  "    = RS6000_INST_%s;\n\n",
                   ovlds[i].ovld_id_name);
        }
     }

Reply via email to