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. >