> On 13 Aug 2026, at 20:33, Andrea Pinski <[email protected]> 
> wrote:
> 
> On Thu, Aug 13, 2026 at 6:27 AM <[email protected]> wrote:
>> 
>> From: Kyrylo Tkachov <[email protected]>
>> 
>> insn_data[] is 65% of insn-output.cc.  Every one of its rows carried its
>> own HAVE_DESIGNATED_UNION_INITIALIZERS conditional, and both tables put
>> one field on each line.  On aarch64 that is 85621 preprocessor lines
>> (1.48MB) and 1.04MB of indentation in a 11.37MB file.
>> 
>> Give the output union constexpr constructors, one per member, and emit
>> one table row per line.  The constructors pick the union member from the
>> argument's type, so genoutput just writes the value.  A row
>> 
>>  /* .../aarch64-simd.md:9549 */
>>  {
>>    "*aarch64_simd_ld1rv4bf",
>>  #if HAVE_DESIGNATED_UNION_INITIALIZERS
>>    { .single =
>>  #else
>>    {
>>  #endif
>>    "ld1r\t{%0.4h}, %1",
>>  #if HAVE_DESIGNATED_UNION_INITIALIZERS
>>    },
>>  #else
>>    0, 0 },
>>  #endif
>>    { 0 },
>>    &operand_data[6252],
>>    2,
>>    2,
>>    0,
>>    1,
>>    1
>>  },
>> 
>> becomes
>> 
>>  /* .../aarch64-simd.md:9549 */
>>  { "*aarch64_simd_ld1rv4bf", "ld1r\t{%0.4h}, %1", { 0 }, \
>>    &operand_data[6252], 2, 2, 0, 1, 1 },
>> 
>> Designated initialisers for unions are a GNU extension in C++; they are
>> not standard before C++20.  Constexpr constructors say the same thing in
>> C++14, which GCC has required of the host compiler since GCC 15, so
>> HAVE_DESIGNATED_UNION_INITIALIZERS goes away entirely.  Hosts without the
>> extension no longer fall back to a three-pointer struct, which is a third
>> larger than the union.
>> 
>> insn-output.cc shrinks from 11.37MB/670505 lines to 7.57MB/125441 lines
>> on aarch64, and by a similar fraction on riscv64 (39.12MB), x86_64
>> (8.53MB), i686 (8.00MB) and avr (1.94MB).
>> Compile time is unchanged, which is expected: the file's cost is its 1685 
>> output_* function
>> bodies, not its source text.  Peak memory drops from 498MB to 461MB.
>> 
>> insn-output.o keeps an identical .rodata and identical text, data and
>> bss sizes, and gains no dynamic initialiser, so the tables are still
>> built entirely at compile time.  The preprocessed, whitespace-normalised
>> token streams of the two tables are also identical before and after on
>> all five targets above.
>> 
>> Bootstrapped on aarch64-none-linux-gnu.
>> Ok for trunk?
>> 
>> gcc/ChangeLog:
>> 
>>        * system.h (HAVE_DESIGNATED_UNION_INITIALIZERS): Remove.
> 
> I suspect you want to poison HAVE_DESIGNATED_UNION_INITIALIZERS too.
> Just in case someone still has
> `#if HAVE_DESIGNATED_UNION_INITIALIZERS` somewhere.

Thanks, done so in the attached respin.
Kyrill

> 
>>        * recog.h (insn_data_d::insn_output_u): New union, replacing the
>>        anonymous one and its non-designated fallback.  Add a constructor
>>        per member.
>>        * genoutput.cc (output_operand_data): Emit one row per line.
>>        (output_insn_data): Likewise, and initialise the output member
>>        directly rather than through a designated initialiser.
>> 
>> Signed-off-by: Kyrylo Tkachov <[email protected]>
>> ---
>> gcc/genoutput.cc | 83 ++++++++++++++----------------------------------
>> gcc/recog.h      | 20 ++++++------
>> gcc/system.h     |  9 ------
>> 3 files changed, 34 insertions(+), 78 deletions(-)
>> 
>> diff --git a/gcc/genoutput.cc b/gcc/genoutput.cc
>> index d2e2507f25e..115b9bbc21a 100644
>> --- a/gcc/genoutput.cc
>> +++ b/gcc/genoutput.cc
>> @@ -253,29 +253,19 @@ output_operand_data (void)
>> 
>>   for (d = odata; d; d = d->next)
>>     {
>> -      struct pred_data *pred;
>> +      struct pred_data *pred = NULL;
>> 
>> -      printf ("  {\n");
>> -
>> -      printf ("    %s,\n",
>> -             d->predicate && d->predicate[0] ? d->predicate : "0");
>> -
>> -      printf ("    \"%s\",\n", d->constraint ? d->constraint : "");
>> -
>> -      printf ("    E_%smode,\n", GET_MODE_NAME (d->mode));
>> -
>> -      printf ("    %d,\n", d->strict_low);
>> -
>> -      printf ("    %d,\n", d->constraint == NULL ? 1 : 0);
>> -
>> -      printf ("    %d,\n", d->eliminable);
>> -
>> -      pred = NULL;
>>       if (d->predicate)
>>        pred = lookup_predicate (d->predicate);
>> -      printf ("    %d\n", pred && pred->codes[MEM]);
>> 
>> -      printf ("  },\n");
>> +      printf ("  { %s, \"%s\", E_%smode, %d, %d, %d, %d },\n",
>> +             d->predicate && d->predicate[0] ? d->predicate : "0",
>> +             d->constraint ? d->constraint : "",
>> +             GET_MODE_NAME (d->mode),
>> +             d->strict_low,
>> +             d->constraint == NULL ? 1 : 0,
>> +             d->eliminable,
>> +             pred && pred->codes[MEM]);
>>     }
>>   printf ("};\n\n\n");
>> }
>> @@ -303,11 +293,11 @@ output_insn_data (void)
>>   for (d = idata; d; d = d->next)
>>     {
>>       printf ("  /* %s:%d */\n", d->loc.filename, d->loc.lineno);
>> -      printf ("  {\n");
>> +      printf ("  { ");
>> 
>>       if (d->name)
>>        {
>> -         printf ("    \"%s\",\n", d->name);
>> +         printf ("\"%s\", ", d->name);
>>          name_offset = 0;
>>          last_name = d->name;
>>          next_name = 0;
>> @@ -326,32 +316,23 @@ output_insn_data (void)
>>          name_offset++;
>>          if (next_name && (last_name == 0
>>                            || name_offset > next_name_offset / 2))
>> -           printf ("    \"%s-%d\",\n", next_name,
>> +           printf ("\"%s-%d\", ", next_name,
>>                    next_name_offset - name_offset);
>>          else
>> -           printf ("    \"%s+%d\",\n", last_name, name_offset);
>> +           printf ("\"%s+%d\", ", last_name, name_offset);
>>        }
>> 
>>       switch (d->output_format)
>>        {
>>        case INSN_OUTPUT_FORMAT_NONE:
>> -         printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
>> -         printf ("    { 0 },\n");
>> -         printf ("#else\n");
>> -         printf ("    { 0, 0, 0 },\n");
>> -         printf ("#endif\n");
>> +         printf ("{}, ");
>>          break;
>>        case INSN_OUTPUT_FORMAT_SINGLE:
>>          {
>>            const char *p = d->template_code;
>>            char prev = 0;
>> 
>> -           printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
>> -           printf ("    { .single =\n");
>> -           printf ("#else\n");
>> -           printf ("    {\n");
>> -           printf ("#endif\n");
>> -           printf ("    \"");
>> +           printf ("\"");
>>            while (*p)
>>              {
>>                if (IS_VSPACE (*p) && prev != '\\')
>> @@ -366,45 +347,27 @@ output_insn_data (void)
>>                prev = *p;
>>                ++p;
>>              }
>> -           printf ("\",\n");
>> -           printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
>> -           printf ("    },\n");
>> -           printf ("#else\n");
>> -           printf ("    0, 0 },\n");
>> -           printf ("#endif\n");
>> +           printf ("\", ");
>>          }
>>          break;
>>        case INSN_OUTPUT_FORMAT_MULTI:
>> -         printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
>> -         printf ("    { .multi = output_%d },\n", d->code_number);
>> -         printf ("#else\n");
>> -         printf ("    { 0, output_%d, 0 },\n", d->code_number);
>> -         printf ("#endif\n");
>> +         printf ("output_%d, ", d->code_number);
>>          break;
>>        case INSN_OUTPUT_FORMAT_FUNCTION:
>> -         printf ("#if HAVE_DESIGNATED_UNION_INITIALIZERS\n");
>> -         printf ("    { .function = output_%d },\n", d->code_number);
>> -         printf ("#else\n");
>> -         printf ("    { 0, 0, output_%d },\n", d->code_number);
>> -         printf ("#endif\n");
>> +         printf ("output_%d, ", d->code_number);
>>          break;
>>        default:
>>          gcc_unreachable ();
>>        }
>> 
>>       if (d->name && d->name[0] != '*')
>> -       printf ("    { (insn_gen_fn::stored_funcptr) gen_%s },\n", d->name);
>> +       printf ("{ (insn_gen_fn::stored_funcptr) gen_%s }, ", d->name);
>>       else
>> -       printf ("    { 0 },\n");
>> -
>> -      printf ("    &operand_data[%d],\n", d->operand_number);
>> -      printf ("    %d,\n", d->n_generator_args);
>> -      printf ("    %d,\n", d->n_operands);
>> -      printf ("    %d,\n", d->n_dups);
>> -      printf ("    %d,\n", d->n_alternatives);
>> -      printf ("    %d\n", d->output_format);
>> +       printf ("{ 0 }, ");
>> 
>> -      printf ("  },\n");
>> +      printf ("&operand_data[%d], %d, %d, %d, %d, %d },\n",
>> +             d->operand_number, d->n_generator_args, d->n_operands,
>> +             d->n_dups, d->n_alternatives, d->output_format);
>>     }
>>   printf ("};\n\n\n");
>> }
>> diff --git a/gcc/recog.h b/gcc/recog.h
>> index d7c816a6097..34c7d17d902 100644
>> --- a/gcc/recog.h
>> +++ b/gcc/recog.h
>> @@ -526,19 +526,21 @@ struct insn_operand_data
>> struct insn_data_d
>> {
>>   const char *const name;
>> -#if HAVE_DESIGNATED_UNION_INITIALIZERS
>> -  union {
>> -    const char *single;
>> -    const char *const *multi;
>> -    insn_output_fn function;
>> -  } output;
>> -#else
>> -  struct {
>> +
>> +  /* How to print the insn.  OUTPUT_FORMAT says which member is live.  The
>> +     constructors let genoutput write the member's value directly, and pick
>> +     the member from its type.  */
>> +  union insn_output_u
>> +  {
>>     const char *single;
>>     const char *const *multi;
>>     insn_output_fn function;
>> +
>> +    constexpr insn_output_u () : single (nullptr) {}
>> +    constexpr insn_output_u (const char *s) : single (s) {}
>> +    constexpr insn_output_u (const char *const *m) : multi (m) {}
>> +    constexpr insn_output_u (insn_output_fn f) : function (f) {}
>>   } output;
>> -#endif
>>   const insn_gen_fn genfun;
>>   const struct insn_operand_data *const operand;
>> 
>> diff --git a/gcc/system.h b/gcc/system.h
>> index 08fefd6f054..eacc8675a5f 100644
>> --- a/gcc/system.h
>> +++ b/gcc/system.h
>> @@ -616,15 +616,6 @@ extern int vsnprintf (char *, size_t, const char *, 
>> va_list);
>> #endif
>> #endif
>> 
>> -#if !defined(HAVE_DESIGNATED_UNION_INITIALIZERS)
>> -#ifdef __cplusplus
>> -#define HAVE_DESIGNATED_UNION_INITIALIZERS (GCC_VERSION >= 4007)
>> -#else
>> -#define HAVE_DESIGNATED_UNION_INITIALIZERS \
>> -  ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L))
>> -#endif
>> -#endif
>> -
>> #if HAVE_SYS_STAT_H
>> # include <sys/stat.h>
>> #endif
>> --
>> 2.50.1 (Apple Git-155)
>> 

Attachment: 0002-genoutput-emit-insn_data-and-operand_data-compactly.patch
Description: 0002-genoutput-emit-insn_data-and-operand_data-compactly.patch

Reply via email to