<[email protected]> writes:
> From: Kyrylo Tkachov <[email protected]>
>
> Let genattrtab write multiple attribute outputs, following genemit and
> genrecog.  Reuse --with-insnemit-partitions and make -A repeatable.  Register
> the -A, -D, and -L outputs through the common gensupport machinery.  This 
> gives
> all output roles one validation, open, selection, and close lifecycle.  Also
> distribute the fixed delay and length functions.  Keep DFA and latency
> functions in their existing single files.
>
> choose_output places each function in the shortest partition so far, which
> only balances well if the large functions are placed early.  Attribute
> functions differ in size by two orders of magnitude, so an arbitrary order
> lets a late large function land on an already full partition.  Sort the
> functions by the amount of text write_attr_get will produce, largest first.
> For a derived attribute that amount is the length of its lookup table, and
> otherwise the number of case labels that survive find_most_used.
>
> The functions refer to one another through insn-attr.h and
> insn-attr-common.h, so generated headers do not change.  With one -A option
> the delay and latency outputs are byte-identical to the previous generator.
> The attribute output holds the same lines at the same total size, reordered,
> because the sort applies at any partition count.
>
> On AArch64 with eight partitions the sorted order reduces the spread between
> the largest and smallest partition from 5.9x to 2.3x.  The largest partition
> is then within 0.1% of the size that no assignment can beat, since one
> attribute function alone accounts for that much of the total.  The largest
> attribute part is about 83% smaller than the original single source, and the
> slowest attribute object compiles about 76% faster.  Native AArch64 and
> RISC-V cross all-gcc builds pass.
>
> Bootstrapped on aarch64-none-linux-gnu.  Ok for trunk?
>
> gcc/ChangeLog:
>
>       * Makefile.in (INSNATTRTAB_SPLITS_SEQ, INSNATTRTAB_SEQ_SRC)
>       (INSNATTRTAB_SEQ_TMP, INSNATTRTAB_SEQ_O): New variables.
>       (OBJS): Replace insn-attrtab.o with $(INSNATTRTAB_SEQ_O).
>       (MOSTLYCLEANFILES): Add $(INSNATTRTAB_SEQ_SRC), retaining the legacy
>       unnumbered source for cleanup.
>       (.PRECIOUS): Use $(INSNATTRTAB_SEQ_SRC).
>       (s-attrtab): Generate and move numbered attribute files.  Stop when a
>       move fails.
>       * configure.ac (--with-insnemit-partitions): Document all generators
>       which use the option.
>       * configure: Regenerate.
>       * genattrtab.cc (attr_file_name, attr_file): Remove.
>       (output_files): New variable.
>       (dfa_file_name, latency_file_name): Retain output names.
>       (make_automaton_attrs): Write to the first attribute partition.
>       (handle_arg): Register repeatable attribute outputs.
>       (attr_output_size, cmp_attr_output_size): New functions.
>       (main): Register fixed outputs and use the common output helpers.
>       Distribute attribute, delay, and length functions, largest first.
>       * final.cc (length_unit_log): Update comment for partitioned output.
>       * config/arc/arc-protos.h (regno_clobbered_p): Likewise.
>       * config/ia64/ia64.cc (bundling): Likewise.
>       * config/ia64/t-ia64 (insn-attrtab.o-warn): Replace with per-partition
>       warning variables.
>       * config/sh/sh.h (code_for_indirect_jump_scratch): Update comment for
>       partitioned output.
>
> contrib/ChangeLog:
>
>       * filter-clang-warnings.py (skip_warning): Match numbered attribute
>       files.
>
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> [...]
> @@ -5500,9 +5527,22 @@ main (int argc, const char **argv)
>    if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
>      return FATAL_EXIT_CODE;
>  
> -  attr_file = open_outfile (attr_file_name);
> -  dfa_file = open_outfile (dfa_file_name);
> -  latency_file = open_outfile (latency_file_name);
> +  if (output_files.is_empty ())
> +    fatal ("no -A output file specified");
> +  if (!dfa_file_name)
> +    fatal ("no -D output file specified");
> +  if (!latency_file_name)
> +    fatal ("no -L output file specified");
> +

I think it'd be worth adding a note here to say that the DFA and latency
files must be added after the attribute files (for make_automaton_attrs,
although the comment doesn't need to say that).

OK with that change, thanks.

Richard

> +  unsigned int dfa_index
> +    = add_generator_output (output_files, dfa_file_name, false);
> +  unsigned int latency_index
> +    = add_generator_output (output_files, latency_file_name, false);
> +  open_generator_outputs (output_files);
> +  dfa_file = output_files[dfa_index].file;
> +  latency_file = output_files[latency_index].file;
> +  for (generator_output &output : output_files)
> +    write_header (output.file);
>  
>    obstack_init (hash_obstack);
>    obstack_init (temp_obstack);
> @@ -5619,50 +5659,56 @@ main (int argc, const char **argv)
>    /* Perform any possible optimizations to speed up compilation.  */
>    optimize_attrs (num_insn_codes);
>  
> -  /* Now write out all the `gen_attr_...' routines.  Do these before the
> -     special routines so that they get defined before they are used.  */
> +  /* Now write out all the `get_attr_...' routines.  The DFA and latency
> +     routines go to their own files; the rest are distributed across the
> +     attribute files.  They only refer to each other through the extern
> +     declarations in insn-attr.h and insn-attr-common.h.  */
>  
> +  auto_vec<class attr_desc *> to_write;
>    for (i = 0; i < MAX_ATTRS_INDEX; i++)
>      for (attr = attrs[i]; attr; attr = attr->next)
> -      {
> -        FILE *outf;
> +      if (!attr->is_special && !attr->is_const)
> +     to_write.safe_push (attr);
>  
> -     if (startswith(attr->name, "*internal_dfa_insn_code"))
> -       outf = dfa_file;
> -     else if (startswith (attr->name, "*insn_default_latency"))
> -       outf = latency_file;
> -     else
> -       outf = attr_file;
> +  /* Give choose_output the largest functions first.  It assigns each one to
> +     the shortest output so far, and feeding it an arbitrary order lets a
> +     late large function land on an already full partition.  Attribute
> +     functions differ in size by two orders of magnitude, so that happens
> +     easily.  */
> +  to_write.qsort (cmp_attr_output_size);
>  
> -     if (! attr->is_special && ! attr->is_const)
> -       write_attr_get (outf, attr);
> -      }
> +  for (class attr_desc *a : to_write)
> +    {
> +      FILE *outf;
> +
> +      if (startswith (a->name, "*internal_dfa_insn_code"))
> +     outf = dfa_file;
> +      else if (startswith (a->name, "*insn_default_latency"))
> +     outf = latency_file;
> +      else
> +     outf = choose_output (output_files);
> +
> +      write_attr_get (outf, a);
> +    }
>  
>    /* Write out delay eligibility information, if DEFINE_DELAY present.
>       (The function to compute the number of delay slots will be written
>       below.)  */
> -  write_eligible_delay (attr_file, "delay");
> +  write_eligible_delay (choose_output (output_files), "delay");
>    if (have_annul_true)
> -    write_eligible_delay (attr_file, "annul_true");
> +    write_eligible_delay (choose_output (output_files), "annul_true");
>    else
> -    write_dummy_eligible_delay (attr_file, "annul_true");
> +    write_dummy_eligible_delay (choose_output (output_files), "annul_true");
>    if (have_annul_false)
> -    write_eligible_delay (attr_file, "annul_false");
> +    write_eligible_delay (choose_output (output_files), "annul_false");
>    else
> -    write_dummy_eligible_delay (attr_file, "annul_false");
> +    write_dummy_eligible_delay (choose_output (output_files), "annul_false");
>  
>    /* Write out constant delay slot info.  */
> -  write_const_num_delay_slots (attr_file);
> -
> -  write_length_unit_log (attr_file);
> +  write_const_num_delay_slots (choose_output (output_files));
>  
> -  if (fclose (attr_file) != 0)
> -    fatal ("cannot close file %s: %s", attr_file_name, xstrerror (errno));
> -  if (fclose (dfa_file) != 0)
> -    fatal ("cannot close file %s: %s", dfa_file_name, xstrerror (errno));
> -  if (fclose (latency_file) != 0)
> -    fatal ("cannot close file %s: %s", latency_file_name, xstrerror (errno));
> +  write_length_unit_log (choose_output (output_files));
>  
> -  return SUCCESS_EXIT_CODE;
> +  return (close_generator_outputs (output_files)
> +       ? SUCCESS_EXIT_CODE : FATAL_EXIT_CODE);
>  }
> -

Reply via email to