> 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) >>
0002-genoutput-emit-insn_data-and-operand_data-compactly.patch
Description: 0002-genoutput-emit-insn_data-and-operand_data-compactly.patch
