On 09/03/2018 04:00 PM, Richard Biener wrote:
> On Mon, 3 Sep 2018, Martin Liška wrote:
>
>> On 09/03/2018 02:54 PM, Martin Liška wrote:
>>> On 09/03/2018 02:41 PM, Richard Biener wrote:
>>>> On Mon, 3 Sep 2018, Martin Liška wrote:
>>>>
>>>>> On 04/25/2018 01:42 PM, Richard Biener wrote:
>>>>>>
>>>>>> The following patch^Whack splits $subject files into three, one
>>>>>> for the predicates (due to an implementation detail) and two for
>>>>>> the rest - for now into similar LOC size files.
>>>>>>
>>>>>> I'd like to get help on the makefile changes to make them less
>>>>>> verbose, somehow globbing the -[12p] parts.
>>>>>>
>>>>>> Also you can see the split point is manually chosen which means
>>>>>> it will bitrot. Timings for the stage2 compiles on a x86_64
>>>>>> box are
>>>>>>
>>>>>> gimple-match-p.c 5s
>>>>>> generic-match-p.c 3s
>>>>>> gimple-match-1.c 85s
>>>>>> generic-match-1.c 56s
>>>>>> gimple-match-2.c 82s
>>>>>> generic-match-2.c 31s
>>>>>>
>>>>>> the required header files are quite big (and of course everything
>>>>>> needs to be exported without the analysis work becoming too cumbersome),
>>>>>> it's 3342 LOC for gimple-match-head.h and 1556 LOC for
>>>>>> generic-match-head.h
>>>>>>
>>>>>> The machine I tested is quite fast so the 80ish second timings are still
>>>>>> too slow I guess and thus splitting up into four files for gimple and
>>>>>> three files for generic looks better.
>>>>>>
>>>>>> Note we lose some inlining/cloning capability in the splitting process
>>>>>> (I see quite a bit of constprop/isra work being done on the generated
>>>>>> files). I didn't try to measure the runtime impact though.
>>>>>>
>>>>>> The patch still needs quite some TLC, it really is a bit hacky but I'd
>>>>>> like to get feedback on the approach and I didn't want to spend time
>>>>>> on programatically finding optimal split points (so everything is output
>>>>>> in the same semi-random order as before).
>>>>>>
>>>>>> Richard.
>>>>>>
>>>>>> <insert ChangeLog here>
>>>>>>
>>>>>> Index: gcc/genmatch.c
>>>>>> ===================================================================
>>>>>> --- gcc/genmatch.c (revision 259638)
>>>>>> +++ gcc/genmatch.c (working copy)
>>>>>> @@ -1641,7 +1641,7 @@ struct decision_tree
>>>>>> dt_node *root;
>>>>>>
>>>>>> void insert (struct simplify *, unsigned);
>>>>>> - void gen (FILE *f, bool gimple);
>>>>>> + void gen (const char *, FILE *, vec<unsigned long> &, bool gimple);
>>>>>> void print (FILE *f = stderr);
>>>>>>
>>>>>> decision_tree () { root = new dt_node (dt_node::DT_NODE, NULL); }
>>>>>> @@ -3608,12 +3608,25 @@ sinfo_hashmap_traits::equal_keys (const
>>>>>> return compare_op (v->s->result, v->s, candidate->s->result,
>>>>>> candidate->s);
>>>>>> }
>>>>>>
>>>>>> +/* Write the common header for the GIMPLE/GENERIC IL matching routines.
>>>>>> */
>>>>>> +
>>>>>> +static void
>>>>>> +write_header (FILE *f, bool gimple)
>>>>>> +{
>>>>>> + fprintf (f, "/* Generated automatically by the program `genmatch'
>>>>>> from\n");
>>>>>> + fprintf (f, " a IL pattern matching and simplification description.
>>>>>> */\n");
>>>>>> +
>>>>>> + /* Include the header instead of writing it awkwardly quoted here. */
>>>>>> + fprintf (f, "\n#include \"%s-match-head.c\"\n",
>>>>>> + gimple ? "gimple" : "generic");
>>>>>> +}
>>>>>>
>>>>>> /* Main entry to generate code for matching GIMPLE IL off the decision
>>>>>> tree. */
>>>>>>
>>>>>> void
>>>>>> -decision_tree::gen (FILE *f, bool gimple)
>>>>>> +decision_tree::gen (const char *output, FILE *headerf,
>>>>>> + vec<unsigned long> &pieces, bool gimple)
>>>>>> {
>>>>>> sinfo_map_t si;
>>>>>>
>>>>>> @@ -3624,6 +3637,34 @@ decision_tree::gen (FILE *f, bool gimple
>>>>>> gimple ? "GIMPLE" : "GENERIC",
>>>>>> root->num_leafs, root->max_level, root->total_size);
>>>>>>
>>>>>> + FILE *f;
>>>>>> + char *outputtem = NULL;
>>>>>> + if (output)
>>>>>> + outputtem = XNEWVEC (char, strlen (output) + strlen ("-1.c") + 1);
>>>>>> +
>>>>>> + unsigned do_header = headerf ? 2 : 1;
>>>>>> + unsigned n_per_part = -1U;
>>>>>> + unsigned file_n = output ? 1 : 2;
>>>>>> + do
>>>>>> + {
>>>>>> + unsigned n_fn = 0;
>>>>>> + do_header--;
>>>>>> +
>>>>>> + if (do_header)
>>>>>> + f = headerf;
>>>>>> + else if (!output)
>>>>>> + f = stdout;
>>>>>> + else
>>>>>> + {
>>>>>> + sprintf (outputtem, "%s-%d.c", output, file_n++);
>>>>>> + f = fopen (outputtem, "w");
>>>>>> + if (!f)
>>>>>> + {
>>>>>> + perror ("failed to open output file");
>>>>>> + exit(1);
>>>>>> + }
>>>>>> + write_header (f, gimple);
>>>>>> + }
>>>>>> /* First split out the transform part of equal leafs. */
>>>>>> unsigned rcnt = 0;
>>>>>> unsigned fcnt = 1;
>>>>>> @@ -3643,21 +3684,22 @@ decision_tree::gen (FILE *f, bool gimple
>>>>>> }
>>>>>>
>>>>>> /* Generate a split out function with the leaf transform code. */
>>>>>> + if (do_header || !output)
>>>>>> s->fname = xasprintf ("%s_simplify_%u", gimple ? "gimple" :
>>>>>> "generic",
>>>>>> fcnt++);
>>>>>> if (gimple)
>>>>>> - fprintf (f, "\nstatic bool\n"
>>>>>> + fprintf (f, "\n%sbool\n"
>>>>>> "%s (code_helper *res_code, tree *res_ops,\n"
>>>>>> " gimple_seq *seq, tree
>>>>>> (*valueize)(tree) "
>>>>>> "ATTRIBUTE_UNUSED,\n"
>>>>>> " const tree ARG_UNUSED (type), tree
>>>>>> *ARG_UNUSED "
>>>>>> "(captures)\n",
>>>>>> - s->fname);
>>>>>> + headerf ? "" : "static ", s->fname);
>>>>>> else
>>>>>> {
>>>>>> - fprintf (f, "\nstatic tree\n"
>>>>>> + fprintf (f, "\n%stree\n"
>>>>>> "%s (location_t ARG_UNUSED (loc), const tree
>>>>>> ARG_UNUSED (type),\n",
>>>>>> - (*iter).second->fname);
>>>>>> + headerf ? "" : "static ", (*iter).second->fname);
>>>>>> for (unsigned i = 0;
>>>>>> i < as_a <expr *>(s->s->s->match)->ops.length (); ++i)
>>>>>> fprintf (f, " tree ARG_UNUSED (op%d),", i);
>>>>>> @@ -3674,7 +3716,12 @@ decision_tree::gen (FILE *f, bool gimple
>>>>>> fprintf (f, ", const combined_fn ARG_UNUSED (%s)",
>>>>>> s->s->s->for_subst_vec[i].first->id);
>>>>>> }
>>>>>> -
>>>>>> + n_fn++;
>>>>>> + if (do_header)
>>>>>> + {
>>>>>> + fprintf (f, ");\n");
>>>>>> + continue;
>>>>>> + }
>>>>>> fprintf (f, ")\n{\n");
>>>>>> s->s->gen_1 (f, 2, gimple, s->s->s->result);
>>>>>> if (gimple)
>>>>>> @@ -3682,7 +3729,22 @@ decision_tree::gen (FILE *f, bool gimple
>>>>>> else
>>>>>> fprintf (f, " return NULL_TREE;\n");
>>>>>> fprintf (f, "}\n");
>>>>>> +
>>>>>> + if (n_fn == pieces[file_n - 2])
>>>>>> + {
>>>>>> + fclose (f);
>>>>>> + sprintf (outputtem, "%s-%d.c", output, file_n++);
>>>>>> + f = fopen (outputtem, "w");
>>>>>> + if (!f)
>>>>>> + {
>>>>>> + perror ("failed to open output file");
>>>>>> + exit(1);
>>>>>> + }
>>>>>> + write_header (f, gimple);
>>>>>> + n_fn = 0;
>>>>>> + }
>>>>>> }
>>>>>> + if (!do_header)
>>>>>> fprintf (stderr, "removed %u duplicate tails\n", rcnt);
>>>>>>
>>>>>> for (unsigned n = 1; n <= 3; ++n)
>>>>>> @@ -3702,20 +3764,26 @@ decision_tree::gen (FILE *f, bool gimple
>>>>>> continue;
>>>>>>
>>>>>> if (gimple)
>>>>>> - fprintf (f, "\nstatic bool\n"
>>>>>> + fprintf (f, "\n%sbool\n"
>>>>>> "gimple_simplify_%s (code_helper *res_code, tree
>>>>>> *res_ops,\n"
>>>>>> " gimple_seq *seq, tree
>>>>>> (*valueize)(tree) "
>>>>>> "ATTRIBUTE_UNUSED,\n"
>>>>>> " code_helper ARG_UNUSED (code),
>>>>>> tree "
>>>>>> "ARG_UNUSED (type)\n",
>>>>>> - e->operation->id);
>>>>>> + headerf ? "" : "static ", e->operation->id);
>>>>>> else
>>>>>> - fprintf (f, "\nstatic tree\n"
>>>>>> + fprintf (f, "\n%stree\n"
>>>>>> "generic_simplify_%s (location_t ARG_UNUSED (loc),
>>>>>> enum "
>>>>>> "tree_code ARG_UNUSED (code), const tree
>>>>>> ARG_UNUSED (type)",
>>>>>> - e->operation->id);
>>>>>> + headerf ? "" : "static ", e->operation->id);
>>>>>> for (unsigned i = 0; i < n; ++i)
>>>>>> fprintf (f, ", tree op%d", i);
>>>>>> + n_fn++;
>>>>>> + if (do_header)
>>>>>> + {
>>>>>> + fprintf (f, ");\n");
>>>>>> + continue;
>>>>>> + }
>>>>>> fprintf (f, ")\n");
>>>>>> fprintf (f, "{\n");
>>>>>> dop->gen_kids (f, 2, gimple);
>>>>>> @@ -3724,21 +3792,43 @@ decision_tree::gen (FILE *f, bool gimple
>>>>>> else
>>>>>> fprintf (f, " return NULL_TREE;\n");
>>>>>> fprintf (f, "}\n");
>>>>>> +
>>>>>> + if (n_fn == pieces[file_n - 2])
>>>>>> + {
>>>>>> + fclose (f);
>>>>>> + sprintf (outputtem, "%s-%d.c", output, file_n++);
>>>>>> + f = fopen (outputtem, "w");
>>>>>> + if (!f)
>>>>>> + {
>>>>>> + perror ("failed to open output file");
>>>>>> + exit(1);
>>>>>> + }
>>>>>> + write_header (f, gimple);
>>>>>> + n_fn = 0;
>>>>>> + }
>>>>>> +
>>>>>> }
>>>>>>
>>>>>> /* Then generate the main entry with the outermost switch and
>>>>>> tail-calls to the split-out functions. */
>>>>>> if (gimple)
>>>>>> - fprintf (f, "\nstatic bool\n"
>>>>>> + fprintf (f, "\n%sbool\n"
>>>>>> "gimple_simplify (code_helper *res_code, tree
>>>>>> *res_ops,\n"
>>>>>> " gimple_seq *seq, tree
>>>>>> (*valueize)(tree),\n"
>>>>>> - " code_helper code, const tree type");
>>>>>> + " code_helper code, const tree type",
>>>>>> + headerf ? "" : "static ");
>>>>>> else
>>>>>> fprintf (f, "\ntree\n"
>>>>>> "generic_simplify (location_t loc, enum tree_code
>>>>>> code, "
>>>>>> "const tree type ATTRIBUTE_UNUSED");
>>>>>> for (unsigned i = 0; i < n; ++i)
>>>>>> fprintf (f, ", tree op%d", i);
>>>>>> + n_fn++;
>>>>>> + if (do_header)
>>>>>> + {
>>>>>> + fprintf (f, ");\n");
>>>>>> + continue;
>>>>>> + }
>>>>>> fprintf (f, ")\n");
>>>>>> fprintf (f, "{\n");
>>>>>>
>>>>>> @@ -3786,19 +3876,46 @@ decision_tree::gen (FILE *f, bool gimple
>>>>>> else
>>>>>> fprintf (f, " return NULL_TREE;\n");
>>>>>> fprintf (f, "}\n");
>>>>>> + if (n_fn == pieces[file_n - 2])
>>>>>> + {
>>>>>> + fclose (f);
>>>>>> + sprintf (outputtem, "%s-%d.c", output, file_n++);
>>>>>> + f = fopen (outputtem, "w");
>>>>>> + if (!f)
>>>>>> + {
>>>>>> + perror ("failed to open output file");
>>>>>> + exit(1);
>>>>>> + }
>>>>>> + write_header (f, gimple);
>>>>>> + n_fn = 0;
>>>>>> + }
>>>>>> + }
>>>>>> +
>>>>>> + n_per_part = n_fn / 4 + 1;
>>>>>> }
>>>>>> + while (do_header);
>>>>>> + if (output)
>>>>>> + fclose (f);
>>>>>> }
>>>>>>
>>>>>> /* Output code to implement the predicate P from the decision tree DT.
>>>>>> */
>>>>>>
>>>>>> void
>>>>>> -write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool
>>>>>> gimple)
>>>>>> +write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool
>>>>>> gimple,
>>>>>> + bool for_header)
>>>>>> {
>>>>>> fprintf (f, "\nbool\n"
>>>>>> - "%s%s (tree t%s%s)\n"
>>>>>> - "{\n", gimple ? "gimple_" : "tree_", p->id,
>>>>>> + "%s%s (tree t%s%s)",
>>>>>> + gimple ? "gimple_" : "tree_", p->id,
>>>>>> p->nargs > 0 ? ", tree *res_ops" : "",
>>>>>> gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : "");
>>>>>> + if (for_header)
>>>>>> + {
>>>>>> + fprintf (f, ";\n");
>>>>>> + return;
>>>>>> + }
>>>>>> +
>>>>>> + fprintf (f, "\n{\n");
>>>>>> /* Conveniently make 'type' available. */
>>>>>> fprintf_indent (f, 2, "const tree type = TREE_TYPE (t);\n");
>>>>>>
>>>>>> @@ -3810,18 +3927,6 @@ write_predicate (FILE *f, predicate_id *
>>>>>> "}\n");
>>>>>> }
>>>>>>
>>>>>> -/* Write the common header for the GIMPLE/GENERIC IL matching routines.
>>>>>> */
>>>>>> -
>>>>>> -static void
>>>>>> -write_header (FILE *f, const char *head)
>>>>>> -{
>>>>>> - fprintf (f, "/* Generated automatically by the program `genmatch'
>>>>>> from\n");
>>>>>> - fprintf (f, " a IL pattern matching and simplification description.
>>>>>> */\n");
>>>>>> -
>>>>>> - /* Include the header instead of writing it awkwardly quoted here. */
>>>>>> - fprintf (f, "\n#include \"%s\"\n", head);
>>>>>> -}
>>>>>> -
>>>>>>
>>>>>>
>>>>>> /* AST parsing. */
>>>>>> @@ -4969,6 +5074,9 @@ main (int argc, char **argv)
>>>>>>
>>>>>> bool gimple = true;
>>>>>> char *input = argv[argc-1];
>>>>>> + char *output = NULL;
>>>>>> + char *header = NULL;
>>>>>> + auto_vec<unsigned long> pieces;
>>>>>> for (int i = 1; i < argc - 1; ++i)
>>>>>> {
>>>>>> if (strcmp (argv[i], "--gimple") == 0)
>>>>>> @@ -4979,13 +5087,25 @@ main (int argc, char **argv)
>>>>>> verbose = 1;
>>>>>> else if (strcmp (argv[i], "-vv") == 0)
>>>>>> verbose = 2;
>>>>>> + else if (strcmp (argv[i], "-c") == 0)
>>>>>> + {
>>>>>> + char *endp;
>>>>>> + output = argv[++i];
>>>>>> + while (i + 1 < argc - 1
>>>>>> + && ISDIGIT (argv[i + 1][0]))
>>>>>> + pieces.safe_push (strtoul (argv[++i], &endp, 10));
>>>>>> + }
>>>>>> + else if (strcmp (argv[i], "-h") == 0)
>>>>>> + header = argv[++i];
>>>>>> else
>>>>>> {
>>>>>> fprintf (stderr, "Usage: genmatch "
>>>>>> - "[--gimple] [--generic] [-v[v]] input\n");
>>>>>> + "[--gimple] [--generic] [-v[v]] "
>>>>>> + "[-c output num...] [-h header] input\n");
>>>>>> return 1;
>>>>>> }
>>>>>> }
>>>>>> + pieces.safe_push (-1UL);
>>>>>>
>>>>>> line_table = XCNEW (struct line_maps);
>>>>>> linemap_init (line_table, 0);
>>>>>> @@ -5039,10 +5159,32 @@ add_operator (VIEW_CONVERT2, "view_conve
>>>>>> /* Parse ahead! */
>>>>>> parser p (r);
>>>>>>
>>>>>> - if (gimple)
>>>>>> - write_header (stdout, "gimple-match-head.c");
>>>>>> + FILE *f, *headerf = NULL;
>>>>>> + if (!output)
>>>>>> + f = stdout;
>>>>>> else
>>>>>> - write_header (stdout, "generic-match-head.c");
>>>>>> + {
>>>>>> + char *outputtem = XNEWVEC (char, strlen (output) + strlen
>>>>>> ("-1.c") + 1);
>>>>>> + sprintf (outputtem, "%s-p.c", output);
>>>>>> + f = fopen (outputtem, "w");
>>>>>> + if (!f)
>>>>>> + {
>>>>>> + perror ("failed to open output file");
>>>>>> + exit(1);
>>>>>> + }
>>>>>> + }
>>>>>> + if (header)
>>>>>> + {
>>>>>> + headerf = fopen (header, "w");
>>>>>> + if (!headerf)
>>>>>> + {
>>>>>> + perror ("failed to open output file");
>>>>>> + exit(1);
>>>>>> + }
>>>>>> + }
>>>>>> +
>>>>>> + fprintf (f, "#define GENFOO_MAIN_FILE 1\n");
>>>>>> + write_header (f, gimple);
>>>>>>
>>>>>> /* Go over all predicates defined with patterns and perform
>>>>>> lowering and code generation. */
>>>>>> @@ -5062,8 +5204,12 @@ add_operator (VIEW_CONVERT2, "view_conve
>>>>>> if (verbose == 2)
>>>>>> dt.print (stderr);
>>>>>>
>>>>>> - write_predicate (stdout, pred, dt, gimple);
>>>>>> + if (header)
>>>>>> + write_predicate (headerf, pred, dt, gimple, true);
>>>>>> + write_predicate (f, pred, dt, gimple, false);
>>>>>> }
>>>>>> + if (output)
>>>>>> + fclose (f);
>>>>>>
>>>>>> /* Lower the main simplifiers and generate code for them. */
>>>>>> lower (p.simplifiers, gimple);
>>>>>> @@ -5079,7 +5225,10 @@ add_operator (VIEW_CONVERT2, "view_conve
>>>>>> if (verbose == 2)
>>>>>> dt.print (stderr);
>>>>>>
>>>>>> - dt.gen (stdout, gimple);
>>>>>> + dt.gen (output, headerf, pieces, gimple);
>>>>>> +
>>>>>> + if (header)
>>>>>> + fclose (headerf);
>>>>>>
>>>>>> /* Finalize. */
>>>>>> cpp_finish (r, NULL);
>>>>>> Index: gcc/gimple-match-head.c
>>>>>> ===================================================================
>>>>>> --- gcc/gimple-match-head.c (revision 259638)
>>>>>> +++ gcc/gimple-match-head.c (working copy)
>>>>>> @@ -40,21 +40,10 @@ along with GCC; see the file COPYING3.
>>>>>> #include "case-cfn-macros.h"
>>>>>> #include "gimplify.h"
>>>>>> #include "optabs-tree.h"
>>>>>> +#include "gimple-match-head.h"
>>>>>>
>>>>>>
>>>>>> -/* Forward declarations of the private auto-generated matchers.
>>>>>> - They expect valueized operands in canonical order and do not
>>>>>> - perform simplification of all-constant operands. */
>>>>>> -static bool gimple_simplify (code_helper *, tree *,
>>>>>> - gimple_seq *, tree (*)(tree),
>>>>>> - code_helper, tree, tree);
>>>>>> -static bool gimple_simplify (code_helper *, tree *,
>>>>>> - gimple_seq *, tree (*)(tree),
>>>>>> - code_helper, tree, tree, tree);
>>>>>> -static bool gimple_simplify (code_helper *, tree *,
>>>>>> - gimple_seq *, tree (*)(tree),
>>>>>> - code_helper, tree, tree, tree, tree);
>>>>>> -
>>>>>> +#if GENFOO_MAIN_FILE
>>>>>>
>>>>>> /* Return whether T is a constant that we'll dispatch to fold to
>>>>>> evaluate fully constant expressions. */
>>>>>> @@ -772,6 +761,8 @@ gimple_simplify (gimple *stmt,
>>>>>> return false;
>>>>>> }
>>>>>>
>>>>>> +#endif
>>>>>> +
>>>>>>
>>>>>> /* Helper for the autogenerated code, valueize OP. */
>>>>>>
>>>>>> Index: gcc/generic-match-head.c
>>>>>> ===================================================================
>>>>>> --- gcc/generic-match-head.c (revision 259638)
>>>>>> +++ gcc/generic-match-head.c (working copy)
>>>>>> @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.
>>>>>> #include "case-cfn-macros.h"
>>>>>> #include "gimplify.h"
>>>>>> #include "optabs-tree.h"
>>>>>> +#include "generic-match-head.h"
>>>>>>
>>>>>>
>>>>>> /* Routine to determine if the types T1 and T2 are effectively
>>>>>> Index: gcc/Makefile.in
>>>>>> ===================================================================
>>>>>> --- gcc/Makefile.in (revision 259638)
>>>>>> +++ gcc/Makefile.in (working copy)
>>>>>> @@ -216,8 +216,12 @@ gengtype-lex.o-warn = -Wno-error
>>>>>> libgcov-util.o-warn = -Wno-error
>>>>>> libgcov-driver-tool.o-warn = -Wno-error
>>>>>> libgcov-merge-tool.o-warn = -Wno-error
>>>>>> -gimple-match.o-warn = -Wno-unused
>>>>>> -generic-match.o-warn = -Wno-unused
>>>>>> +gimple-match-p.o-warn = -Wno-unused
>>>>>> +gimple-match-1.o-warn = -Wno-unused
>>>>>> +gimple-match-2.o-warn = -Wno-unused
>>>>>> +generic-match-p.o-warn = -Wno-unused
>>>>>> +generic-match-1.o-warn = -Wno-unused
>>>>>> +generic-match-2.o-warn = -Wno-unused
>>>>>> dfp.o-warn = -Wno-strict-aliasing
>>>>>>
>>>>>> # All warnings have to be shut off in stage1 if the compiler used then
>>>>>> @@ -771,7 +775,7 @@ COMPILERS = @all_compilers@
>>>>>>
>>>>>> # List of things which should already be built whenever we try to use
>>>>>> xgcc
>>>>>> # to compile anything (without linking).
>>>>>> -GCC_PASSES=xgcc$(exeext) specs
>>>>>> +GCC_PASSES=xgcc$(exeext)
>>>>>>
>>>>>> # Directory to link to, when using the target `maketest'.
>>>>>> DIR = ../gcc
>>>>>> @@ -1207,8 +1211,12 @@ C_COMMON_OBJS = c-family/c-common.o c-fa
>>>>>> # will build them sooner, because they are large and otherwise tend to
>>>>>> be
>>>>>> # the last objects to finish building.
>>>>>> OBJS = \
>>>>>> - gimple-match.o \
>>>>>> - generic-match.o \
>>>>>> + gimple-match-p.o \
>>>>>> + generic-match-p.o \
>>>>>> + gimple-match-1.o \
>>>>>> + generic-match-1.o \
>>>>>> + gimple-match-2.o \
>>>>>> + generic-match-2.o \
>>>>>> insn-attrtab.o \
>>>>>> insn-automata.o \
>>>>>> insn-dfatab.o \
>>>>>> @@ -1654,7 +1662,9 @@ MOSTLYCLEANFILES = insn-flags.h insn-con
>>>>>> insn-output.c insn-recog.c insn-emit.c insn-extract.c insn-peep.c \
>>>>>> insn-attr.h insn-attr-common.h insn-attrtab.c insn-dfatab.c \
>>>>>> insn-latencytab.c insn-opinit.c insn-opinit.h insn-preds.c
>>>>>> insn-constants.h \
>>>>>> - tm-preds.h tm-constrs.h checksum-options gimple-match.c
>>>>>> generic-match.c \
>>>>>> + tm-preds.h tm-constrs.h checksum-options gimple-match-head.h
>>>>>> gimple-match-1.c \
>>>>>> + gimple-match-2.c gimple-match-p.c generic-match-head.h
>>>>>> generic-match-1.c \
>>>>>> + generic-match-p.c generic-match-2.c \
>>>>>> tree-check.h min-insn-modes.c insn-modes.c insn-modes.h
>>>>>> insn-modes-inline.h \
>>>>>> genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
>>>>>> case-cfn-macros.h cfn-operators.pd \
>>>>>> @@ -1899,7 +1909,7 @@ all.internal: start.encap rest.encap doc
>>>>>> all.cross: native gcc-cross$(exeext) cpp$(exeext) specs \
>>>>>> libgcc-support lang.all.cross doc selftest @GENINSRC@ srcextra
>>>>>> # This is what must be made before installing GCC and converting
>>>>>> libraries.
>>>>>> -start.encap: native xgcc$(exeext) cpp$(exeext) specs \
>>>>>> +start.encap: native xgcc$(exeext) cpp$(exeext) \
>>>>>> libgcc-support lang.start.encap @GENINSRC@ srcextra
>>>>>> # These can't be made until after GCC can run.
>>>>>> rest.encap: lang.rest.encap
>>>>>> @@ -2054,7 +2064,7 @@ checksum-options:
>>>>>> libgcc-support: libgcc.mvars stmp-int-hdrs $(TCONFIG_H) \
>>>>>> $(MACHMODE_H) gcov-iov.h
>>>>>>
>>>>>> -libgcc.mvars: config.status Makefile specs xgcc$(exeext)
>>>>>> +libgcc.mvars: config.status Makefile xgcc$(exeext)
>>>>>> : > tmp-libgcc.mvars
>>>>>> echo GCC_CFLAGS = '$(GCC_CFLAGS)' >> tmp-libgcc.mvars
>>>>>> echo INHIBIT_LIBC_CFLAGS = '$(INHIBIT_LIBC_CFLAGS)' >>
>>>>>> tmp-libgcc.mvars
>>>>>> @@ -2271,8 +2281,9 @@ $(common_out_object_file): $(common_out_
>>>>>> .PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \
>>>>>> insn-emit.c insn-recog.c insn-extract.c insn-output.c insn-peep.c \
>>>>>> insn-attr.h insn-attr-common.h insn-attrtab.c insn-dfatab.c \
>>>>>> - insn-latencytab.c insn-preds.c gimple-match.c generic-match.c \
>>>>>> - insn-target-def.h
>>>>>> + insn-latencytab.c insn-preds.c gimple-match-head.h gimple-match-1.c \
>>>>>> + gimple-match-2.c generic-match-head.h generic-match-1.c
>>>>>> generic-match-2.c \
>>>>>> + gimple-match-p.c generic-match-p.c insn-target-def.h
>>>>>>
>>>>>> # Dependencies for the md file. The first time through, we just assume
>>>>>> # the md file itself and the generated dependency file (in order to get
>>>>>> @@ -2504,18 +2515,36 @@ s-tm-texi: build/genhooks$(build_exeext)
>>>>>> false; \
>>>>>> fi
>>>>>>
>>>>>> -gimple-match.c: s-match gimple-match-head.c ; @true
>>>>>> -generic-match.c: s-match generic-match-head.c ; @true
>>>>>> +gimple-match-p.c: s-match gimple-match-head.c ; @true
>>>>>> +gimple-match-1.c: s-match gimple-match-head.c ; @true
>>>>>> +gimple-match-2.c: s-match gimple-match-head.c ; @true
>>>>>> +generic-match-p.c: s-match generic-match-head.c ; @true
>>>>>> +generic-match-1.c: s-match generic-match-head.c ; @true
>>>>>> +generic-match-2.c: s-match generic-match-head.c ; @true
>>>>>>
>>>>>> s-match: build/genmatch$(build_exeext) $(srcdir)/match.pd
>>>>>> cfn-operators.pd
>>>>>> - $(RUN_GEN) build/genmatch$(build_exeext) --gimple
>>>>>> $(srcdir)/match.pd \
>>>>>> - > tmp-gimple-match.c
>>>>>> - $(RUN_GEN) build/genmatch$(build_exeext) --generic
>>>>>> $(srcdir)/match.pd \
>>>>>> - > tmp-generic-match.c
>>>>>> - $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match.c \
>>>>>> - gimple-match.c
>>>>>> - $(SHELL) $(srcdir)/../move-if-change tmp-generic-match.c \
>>>>>> - generic-match.c
>>>>>> + $(RUN_GEN) build/genmatch$(build_exeext) --gimple \
>>>>>> + -h tmp-gimple-match-head.h -c tmp-gimple-match 460 \
>>>>>> + $(srcdir)/match.pd
>>>>>> + $(RUN_GEN) build/genmatch$(build_exeext) --generic \
>>>>>> + -h tmp-generic-match-head.h -c tmp-generic-match 290 \
>>>>>> + $(srcdir)/match.pd
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match-head.h \
>>>>>> + gimple-match-head.h
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match-1.c \
>>>>>> + gimple-match-1.c
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match-2.c \
>>>>>> + gimple-match-2.c
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match-p.c \
>>>>>> + gimple-match-p.c
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-generic-match-head.h \
>>>>>> + generic-match-head.h
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-generic-match-1.c \
>>>>>> + generic-match-1.c
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-generic-match-2.c \
>>>>>> + generic-match-2.c
>>>>>> + $(SHELL) $(srcdir)/../move-if-change tmp-generic-match-p.c \
>>>>>> + generic-match-p.c
>>>>>> $(STAMP) s-match
>>>>>>
>>>>>> GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
>>>>>>
>>>>>
>>>>> Hi.
>>>>>
>>>>> I took a look at gimple-match.c and what about doing a split in following
>>>>> way:
>>>>> - all gimple_simplify_$number going into a separate header file (~12000
>>>>> LOC)
>>>>> - all the function can be marked as static inline
>>>>> - all other gimple_simplify_$code can be split into arbitrary number of
>>>>> parts
>>>>> - we have 287 such functions where each function only calls
>>>>> gimple_simplify_$number and
>>>>> on average there 10 of such calls
>>>>> - that would allow to remove most of gimple_simplify_$number functions
>>>>> from the header file
>>>>>
>>>>> Richi do you think it will be viable?
>>>>
>>>> That relies on the cgraph code DCEing all unused gimple_simplify_$number
>>>> functions from the header fast as they are now effectively duplicated
>>>> into all parts, correct? Also I'm not sure if we actually want to inline
>>>> them... they are split out to get both code size and compile-time
>>>> under control. Unfortunately we have still high max-inline-insns-single
>>>> which is used for inline marked functions.
>>>>
>>>> Eventually doing a "proper" partitioning algorithm is viable, that is,
>>>> partition based on gimple_simplify_$code and put gimple_simplify_$number
>>>> where they are used. If they are used across different codes then
>>>> merge those partitions. I guess you'll see that that'll merge the
>>>> biggest _$code parititions :/ (MINUS_EXPR, PLUS_EXPR).
>>>
>>> Yes, that should be much better. I'm attaching a 'callgraph' that was done
>>> by grepping.
>>> Function starting at the beginning of a line is function definition, with
>>> an indentation
>>> one can see calls.
>>>
>>> Yes, PLUS and MINUS call ~20 gimple_simplify_$number calls.
>>>
>>> Well, generating some simple call graph format for the source file and a
>>> source file
>>> annotation of nodes can be input for a partitioning tool that can do the
>>> split.
>>>
>>> Issue with the generated files is that one needs to fix the most offenders
>>> (*-match.c, insn-recog.c, insn-emit.c, ..)
>>> in order to see some improvement.
>>>
>>> Looking at insn-recog.c, maybe similar callgraph-based split can be done
>>> for recog_$number functions?
>>>
>>> Martin
>>>
>>>>
>>>> Richard.
>>>>
>>>
>>
>> I'm sending SCC components for gimple-match.c. So there are 3 quite big one
>> and rest is small. It's questionable
>> whether partitioning based on that will provide desired speed up?
>
> When I experimented split based on # of functions wasn't working well,
> only split based on # of lines did. I'd still expect that eventually
> basing the split on the SCC components makes sense if you use say,
> the biggest 4 (but measure size in # lines) and merge the rest evenly.
I see! Note that shrinking gimple-match.o 4 times will be probably sufficient
for general
speed up:
https://gcc.gnu.org/bugzilla/attachment.cgi?id=43440
>
> It would be nice if that all would be scriptable instead of coding it
> into genmatch.c but that's of course possible as well - just add
> some extra "passes" over code-gen as I did in the hac^Wpatch. You
That would be my plan, genmatch can mark in C comments function that can be
partitioned
and callgraph of these functions.
> could use graphds.c routines to compute SCCs for example. Knowing
> # lines beforehand is a bit hard though - code-generating into
> a set of character buffers might be possible but I wired everything
> to use FILE ... (and no stringstreams in the C library).
> And no, please do not convert to C++ streams ;))
... and a C++ splitter can do the rest: read content, do SCC, split to N parts
and stream out.
I can work on that. Questionable is still Makefile integration of such
parallelism?
Martin
>
> Richard.
>