From: Kyrylo Tkachov <[email protected]>
insn-attrtab.cc contains many independent get_attr_* functions. Several have
large switches over every instruction code, making the single source one of
the slowest objects in each bootstrap stage.
Let genattrtab write multiple attribute outputs, following genemit and
genrecog. Reuse --with-insnemit-partitions and make -A repeatable. Record and
validate every output name before opening files, rejecting duplicates and
resolvable aliases across -A, -D, and -L. Place each attribute function in
the shortest output, along with the fixed delay and length functions. Keep
DFA and latency
functions in their existing single files.
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 all
three outputs are byte-identical to the previous generator. Close diagnostics
retain the affected filename.
With the default AArch64 partition count, the largest attribute part is about
85% smaller and compiles about 67% faster than the original source.
Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-linux.
Ok for trunk?
Thanks,
Kyrill
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.
(attr_files, attr_file_names): New variables.
(dfa_file_name, latency_file_name): Retain output names.
(choose_attr_output, check_output_name): New functions.
(make_automaton_attrs): Write to the first attribute file.
(handle_arg): Record and validate repeatable output names.
(main): Open outputs after complete validation. Distribute attribute,
delay, and length functions. Diagnose close failures.
* 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]>
---
contrib/filter-clang-warnings.py | 2 +-
gcc/Makefile.in | 32 +++++++---
gcc/config/arc/arc-protos.h | 3 +-
gcc/config/ia64/ia64.cc | 4 +-
gcc/config/ia64/t-ia64 | 3 +-
gcc/config/sh/sh.h | 5 +-
gcc/configure | 11 ++--
gcc/configure.ac | 7 ++-
gcc/final.cc | 2 +-
gcc/genattrtab.cc | 105 ++++++++++++++++++++++---------
10 files changed, 121 insertions(+), 53 deletions(-)
diff --git a/contrib/filter-clang-warnings.py b/contrib/filter-clang-warnings.py
index 8eec366b4bc..6b01b559b6e 100755
--- a/contrib/filter-clang-warnings.py
+++ b/contrib/filter-clang-warnings.py
@@ -56,7 +56,7 @@ def skip_warning(filename, message):
'ipa-strub.cc': ['-Wunused-but-set-variable'],
'insn-modes.cc': ['-Wshift-count-overflow'],
'insn-emit.cc': ['-Wtautological-compare'],
- 'insn-attrtab.cc': ['-Wparentheses-equality'],
+ 'insn-attrtab': ['-Wparentheses-equality'],
'omp-builtins.def': ['-Wc++11-narrowing'],
'wide-int.h': ['-Wnontrivial-memcall'],
'i386.md': ['-Wparentheses-equality', '-Wtautological-compare',
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 42c8e8f9062..fd20812703b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -247,6 +247,14 @@ INSNOPINIT_SEQ_SRC = $(patsubst %, insn-opinit-%.cc,
$(INSNOPINIT_SPLITS_SEQ))
INSNOPINIT_SEQ_TMP = $(patsubst %, tmp-opinit-%.cc, $(INSNOPINIT_SPLITS_SEQ))
INSNOPINIT_SEQ_O = $(patsubst %, insn-opinit-%.o, $(INSNOPINIT_SPLITS_SEQ))
+# Re-use the split number for insn-attrtab as well.
+INSNATTRTAB_SPLITS_SEQ = $(INSNEMIT_SPLITS_SEQ)
+INSNATTRTAB_SEQ_SRC = $(patsubst %, insn-attrtab-%.cc, \
+ $(INSNATTRTAB_SPLITS_SEQ))
+INSNATTRTAB_SEQ_TMP = $(patsubst %, tmp-attrtab-%.cc, \
+ $(INSNATTRTAB_SPLITS_SEQ))
+INSNATTRTAB_SEQ_O = $(patsubst %, insn-attrtab-%.o, $(INSNATTRTAB_SPLITS_SEQ))
+
# These files are to have specific diagnostics suppressed, or are not to
# be subject to -Werror:
# flex output may yield harmless "no previous prototype" warnings
@@ -1409,7 +1417,7 @@ OBJS = \
$(GIMPLE_MATCH_PD_SEQ_O) \
gimple-match-exports.o \
$(GENERIC_MATCH_PD_SEQ_O) \
- insn-attrtab.o \
+ $(INSNATTRTAB_SEQ_O) \
insn-automata.o \
insn-dfatab.o \
$(INSNEMIT_SEQ_O) \
@@ -1990,9 +1998,9 @@
FULL_DRIVER_NAME=$(target_noncanonical)-gcc-$(version)$(exeext)
MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
insn-output.cc $(INSNRECOG_SEQ_SRC) insn-recog.h \
$(INSNEMIT_SEQ_SRC) insn-extract.cc insn-peep.cc \
- insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \
- insn-latencytab.cc $(INSNOPINIT_SEQ_SRC) insn-opinit.cc insn-opinit.h \
- insn-preds.cc \
+ insn-attr.h insn-attr-common.h $(INSNATTRTAB_SEQ_SRC) insn-attrtab.cc \
+ insn-dfatab.cc insn-latencytab.cc $(INSNOPINIT_SEQ_SRC) insn-opinit.cc \
+ insn-opinit.h insn-preds.cc \
insn-constants.h \
tm-preds.h tm-constrs.h checksum-options $(GIMPLE_MATCH_PD_SEQ_SRC) \
$(GENERIC_MATCH_PD_SEQ_SRC) gimple-match-auto.h generic-match-auto.h \
@@ -2768,7 +2776,7 @@ $(common_out_object_file): $(common_out_file)
.PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \
$(INSNEMIT_SEQ_SRC) insn-recog.h $(INSNRECOG_SEQ_SRC) \
insn-extract.cc insn-output.cc \
- insn-peep.cc insn-attr.h insn-attr-common.h insn-attrtab.cc \
+ insn-peep.cc insn-attr.h insn-attr-common.h $(INSNATTRTAB_SEQ_SRC) \
insn-dfatab.cc insn-latencytab.cc insn-preds.cc \
$(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
gimple-match-auto.h generic-match-auto.h insn-target-def.h
@@ -2855,13 +2863,19 @@ s-check : build/gencheck$(build_exeext)
$(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
$(STAMP) s-check
-# genattrtab produces three files: tmp-{attrtab.cc,dfatab.cc,latencytab.cc}
-insn-attrtab.cc insn-dfatab.cc insn-latencytab.cc: s-attrtab ; @true
+# genattrtab splits the attribute functions like genemit and additionally
+# produces tmp-dfatab.cc and tmp-latencytab.cc.
+$(INSNATTRTAB_SEQ_SRC): s-attrtab ; @true
+insn-dfatab.cc insn-latencytab.cc: s-attrtab ; @true
s-attrtab : $(MD_DEPS) build/genattrtab$(build_exeext) \
insn-conditions.md
$(RUN_GEN) build/genattrtab$(build_exeext) $(md_file)
insn-conditions.md \
- -Atmp-attrtab.cc -Dtmp-dfatab.cc -Ltmp-latencytab.cc
- $(SHELL) $(srcdir)/../move-if-change tmp-attrtab.cc insn-attrtab.cc
+ $(addprefix -A,${INSNATTRTAB_SEQ_TMP}) \
+ -Dtmp-dfatab.cc -Ltmp-latencytab.cc
+ for id in $(INSNATTRTAB_SPLITS_SEQ); do \
+ $(SHELL) $(srcdir)/../move-if-change tmp-attrtab-$$id.cc \
+ insn-attrtab-$$id.cc || exit 1; \
+ done
$(SHELL) $(srcdir)/../move-if-change tmp-dfatab.cc insn-dfatab.cc
$(SHELL) $(srcdir)/../move-if-change tmp-latencytab.cc
insn-latencytab.cc
$(STAMP) s-attrtab
diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h
index fc36d52ead0..380f2c39777 100644
--- a/gcc/config/arc/arc-protos.h
+++ b/gcc/config/arc/arc-protos.h
@@ -93,7 +93,8 @@ extern bool arc_text_label (rtx_insn *insn);
extern bool arc_short_comparison_p (rtx, int);
extern bool arc_epilogue_uses (int regno);
extern bool arc_eh_uses (int regno);
-/* insn-attrtab.cc doesn't include reload.h, which declares regno_clobbered_p.
*/
+/* Generated attribute code does not include reload.h, which declares
+ regno_clobbered_p. */
extern int regno_clobbered_p (unsigned int, rtx_insn *, machine_mode, int);
extern bool arc_legitimize_reload_address (rtx *, machine_mode, int, int);
extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
index b06158ba7bc..292c6b3d939 100644
--- a/gcc/config/ia64/ia64.cc
+++ b/gcc/config/ia64/ia64.cc
@@ -9286,8 +9286,8 @@ bundling (FILE *dump, int verbose, rtx_insn
*prev_head_insn, rtx_insn *tail)
curr_state = curr_state->next)
if (verbose >= 2 && dump)
{
- /* This structure is taken from generated code of the
- pipeline hazard recognizer (see file insn-attrtab.cc).
+ /* This structure is taken from the generated pipeline hazard
+ recognizer code.
Please don't forget to change the structure if a new
automaton is added to .md file. */
struct DFA_chip
diff --git a/gcc/config/ia64/t-ia64 b/gcc/config/ia64/t-ia64
index 4c37dd89fba..2bf590d89df 100644
--- a/gcc/config/ia64/t-ia64
+++ b/gcc/config/ia64/t-ia64
@@ -22,7 +22,8 @@ ia64-c.o: $(srcdir)/config/ia64/ia64-c.cc $(CONFIG_H)
$(SYSTEM_H) \
$(srcdir)/config/ia64/ia64-c.cc
# genattrtab generates very long string literals.
-insn-attrtab.o-warn = -Wno-error
+$(foreach id, $(INSNATTRTAB_SPLITS_SEQ), \
+ $(eval insn-attrtab-$(id).o-warn = -Wno-error))
ia64.o: $(srcdir)/config/ia64/ia64.cc debug.h $(PARAMS_H) sel-sched.h reload.h
\
$(OPTS_H) dumpfile.h $(HASH_TABLE_H)
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 9b2ed6a33db..f3973e7fcab 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -24,8 +24,9 @@ along with GCC; see the file COPYING3. If not see
#include "config/vxworks-dummy.h"
-/* Unfortunately, insn-attrtab.cc doesn't include insn-codes.h. We can't
- include it here, because bconfig.h is also included by gencodes.cc . */
+/* Unfortunately, generated attribute code does not include insn-codes.h.
+ We can't include it here, because bconfig.h is also included by
+ gencodes.cc . */
/* ??? No longer true. */
extern int code_for_indirect_jump_scratch;
diff --git a/gcc/configure b/gcc/configure
index b1f31b61725..846426e5908 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -1882,8 +1882,8 @@ Optional Packages:
Set the number of partitions to make for gimple and
generic when splitting match.pd. [default=10]
--with-insnemit-partitions=num
- Set the number of insn-emit, insn-recog and
- insn-opinit partitions to generate. [default=10]
+ Set the number of partitions used by genemit,
+ genrecog, genopinit and genattrtab. [default=10]
--with-dwarf2 force the default debug format to be DWARF 2 (or
later)
--with-specs=SPECS add SPECS to driver command-line processing
@@ -7907,7 +7907,8 @@ fi
-# Specify the number of output files used by the insn generators.
+# Specify the number of output partitions used by the machine-description
+# generators.
# Check whether --with-insnemit-partitions was given.
if test "${with_insnemit_partitions+set}" = set; then :
@@ -21921,7 +21922,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21924 "configure"
+#line 21925 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -22027,7 +22028,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 22030 "configure"
+#line 22031 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 9e767a7fc5f..e332c6382ab 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -902,11 +902,12 @@ fi
AC_SUBST(DEFAULT_MATCHPD_PARTITIONS)
-# Specify the number of output files used by the insn generators.
+# Specify the number of output partitions used by the machine-description
+# generators.
AC_ARG_WITH(insnemit-partitions,
[AS_HELP_STRING([--with-insnemit-partitions=num],
-[Set the number of insn-emit, insn-recog and insn-opinit partitions to
-generate. [default=10]])],
+[Set the number of partitions used by genemit, genrecog, genopinit and
+genattrtab. [default=10]])],
[DEFAULT_INSNEMIT_PARTITIONS="$with_insnemit_partitions"],
[DEFAULT_INSNEMIT_PARTITIONS=10])
if (test $DEFAULT_INSNEMIT_PARTITIONS -lt 1); then
AC_MSG_ERROR(m4_normalize([
diff --git a/gcc/final.cc b/gcc/final.cc
index 0152be59fc8..e2761d056ea 100644
--- a/gcc/final.cc
+++ b/gcc/final.cc
@@ -142,7 +142,7 @@ static int override_discriminator;
/* Whether to force emission of a line note before the next insn. */
static bool force_source_line = false;
-extern const int length_unit_log; /* This is defined in insn-attrtab.cc. */
+extern const int length_unit_log; /* Defined in generated attribute code. */
/* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't die.
diff --git a/gcc/genattrtab.cc b/gcc/genattrtab.cc
index a2cf08d5305..3e22e828488 100644
--- a/gcc/genattrtab.cc
+++ b/gcc/genattrtab.cc
@@ -305,16 +305,41 @@ static rtx min_fn (rtx);
functions and tables. This made insn-attrtab.cc _the_ bottle-neck in
a parallel build, and even made it impossible to build GCC on machines
with relatively small RAM space (PR other/29442). Therefore, the
- attribute functions/tables are now written out to three separate
- files: all "*insn_default_latency" functions go to LATENCY_FILE_NAME,
- all "*internal_dfa_insn_code" functions go to DFA_FILE_NAME, and the
- rest goes to ATTR_FILE_NAME. */
+ attribute functions/tables are now written out to separate files: all
+ "*insn_default_latency" functions go to LATENCY_FILE, all
+ "*internal_dfa_insn_code" functions go to DFA_FILE, and the rest is
+ distributed across ATTR_FILES the way genemit and genrecog distribute
+ their output. */
-static const char *attr_file_name = NULL;
-static const char *dfa_file_name = NULL;
-static const char *latency_file_name = NULL;
+/* The files to distribute the attribute functions across. */
+static auto_vec<FILE *, 10> attr_files;
+static auto_vec<const char *, 10> attr_file_names;
-static FILE *attr_file, *dfa_file, *latency_file;
+static FILE *dfa_file, *latency_file;
+static const char *dfa_file_name, *latency_file_name;
+
+/* Return the shortest attribute output file. */
+
+static FILE *
+choose_attr_output ()
+{
+ unsigned file_idx;
+ return choose_output (attr_files, file_idx);
+}
+
+/* Reject NAME if another output already uses it. */
+
+static void
+check_output_name (const char *name)
+{
+ for (const char *attr_name : attr_file_names)
+ if (canonical_filename_eq (name, attr_name))
+ fatal ("output file %s specified more than once", name);
+ if ((dfa_file_name && canonical_filename_eq (name, dfa_file_name))
+ || (latency_file_name
+ && canonical_filename_eq (name, latency_file_name)))
+ fatal ("output file %s specified more than once", name);
+}
/* Hash table for sharing RTL and strings. */
@@ -4981,6 +5006,9 @@ make_automaton_attrs (void)
tune_attr = find_tune_attr (all_insn_reservs->condexp);
if (tune_attr != NULL)
{
+ /* The function pointers and init_sched_attrs go to the first
+ attribute file. */
+ FILE *attr_file = attr_files[0];
rtx *condexps = XNEWVEC (rtx, n_insn_reservs * 3);
struct attr_value *val;
bool first = true;
@@ -5223,12 +5251,19 @@ handle_arg (const char *arg)
switch (arg[1])
{
case 'A':
- attr_file_name = &arg[2];
+ check_output_name (&arg[2]);
+ attr_file_names.safe_push (&arg[2]);
return true;
case 'D':
+ if (dfa_file_name)
+ fatal ("option -D specified more than once");
+ check_output_name (&arg[2]);
dfa_file_name = &arg[2];
return true;
case 'L':
+ if (latency_file_name)
+ fatal ("option -L specified more than once");
+ check_output_name (&arg[2]);
latency_file_name = &arg[2];
return true;
default:
@@ -5248,7 +5283,15 @@ 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);
+ if (attr_file_names.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");
+
+ for (const char *name : attr_file_names)
+ attr_files.safe_push (open_outfile (name));
dfa_file = open_outfile (dfa_file_name);
latency_file = open_outfile (latency_file_name);
@@ -5363,50 +5406,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. */
for (i = 0; i < MAX_ATTRS_INDEX; i++)
for (attr = attrs[i]; attr; attr = attr->next)
{
- FILE *outf;
+ FILE *outf;
+
+ if (attr->is_special || attr->is_const)
+ continue;
- if (startswith(attr->name, "*internal_dfa_insn_code"))
+ 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;
+ outf = choose_attr_output ();
- if (! attr->is_special && ! attr->is_const)
- write_attr_get (outf, attr);
+ write_attr_get (outf, attr);
}
/* 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_attr_output (), "delay");
if (have_annul_true)
- write_eligible_delay (attr_file, "annul_true");
+ write_eligible_delay (choose_attr_output (), "annul_true");
else
- write_dummy_eligible_delay (attr_file, "annul_true");
+ write_dummy_eligible_delay (choose_attr_output (), "annul_true");
if (have_annul_false)
- write_eligible_delay (attr_file, "annul_false");
+ write_eligible_delay (choose_attr_output (), "annul_false");
else
- write_dummy_eligible_delay (attr_file, "annul_false");
+ write_dummy_eligible_delay (choose_attr_output (), "annul_false");
/* Write out constant delay slot info. */
- write_const_num_delay_slots (attr_file);
+ write_const_num_delay_slots (choose_attr_output ());
- write_length_unit_log (attr_file);
+ write_length_unit_log (choose_attr_output ());
- if (fclose (attr_file) != 0)
- fatal ("cannot close file %s: %s", attr_file_name, xstrerror (errno));
+ for (unsigned int i = 0; i < attr_files.length (); ++i)
+ if (fclose (attr_files[i]) != 0)
+ fatal ("cannot close file %s: %s", attr_file_names[i],
+ 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));
+ fatal ("cannot close file %s: %s", latency_file_name,
+ xstrerror (errno));
return SUCCESS_EXIT_CODE;
}
-
--
2.50.1 (Apple Git-155)