[PATCH][RFT] Reduce gimple-match.c compile-time(?)
The following patch implements the simplest approach of splitting the huge functions in gimple-match.c (not yet generic-match.c). In my dev tree it does: build/genmatch --gimple /space/rguenther/tramp3d/trunk/gcc/match.pd \ > tmp-gimple-match.c GIMPLE decision tree has 696 leafs, maximum depth 10 and a total number of 2786 nodes Splitting off BIT_NOT_EXPR with 27 leafs and 107 nodes Splitting off BUILT_IN_BSWAP16 with 8 leafs and 35 nodes Splitting off BUILT_IN_BSWAP32 with 8 leafs and 35 nodes Splitting off BUILT_IN_BSWAP64 with 8 leafs and 35 nodes Splitting off BUILT_IN_LOGF with 8 leafs and 24 nodes Splitting off BUILT_IN_LOG with 8 leafs and 24 nodes Splitting off BUILT_IN_LOGL with 8 leafs and 24 nodes Splitting off BUILT_IN_LOG2F with 8 leafs and 24 nodes Splitting off BUILT_IN_LOG2 with 8 leafs and 24 nodes Splitting off BUILT_IN_LOG2L with 8 leafs and 24 nodes Splitting off BUILT_IN_LOG10F with 8 leafs and 24 nodes Splitting off BUILT_IN_LOG10 with 8 leafs and 24 nodes Splitting off BUILT_IN_LOG10L with 8 leafs and 24 nodes Splitting off PLUS_EXPR with 47 leafs and 221 nodes Splitting off MINUS_EXPR with 47 leafs and 212 nodes Splitting off BIT_IOR_EXPR with 53 leafs and 224 nodes Splitting off BIT_XOR_EXPR with 56 leafs and 251 nodes Splitting off MULT_EXPR with 9 leafs and 31 nodes Splitting off RDIV_EXPR with 8 leafs and 22 nodes Splitting off TRUNC_MOD_EXPR with 10 leafs and 35 nodes Splitting off LT_EXPR with 21 leafs and 79 nodes Splitting off GE_EXPR with 21 leafs and 79 nodes Splitting off GT_EXPR with 21 leafs and 78 nodes Splitting off LE_EXPR with 21 leafs and 78 nodes Splitting off BIT_AND_EXPR with 62 leafs and 279 nodes Splitting off NE_EXPR with 39 leafs and 159 nodes Splitting off RSHIFT_EXPR with 8 leafs and 31 nodes Splitting off EQ_EXPR with 35 leafs and 138 nodes where you can see the maximum function size being around 3000 LOC after the patch. On x86_64-unknown-linux-gnu this makes not much difference (just tried building with an installed compiler using -O2 -g), it's 24s vs. 32s. Can people who reported huge compile-times test this patch and report back? Thanks, Richard. 2015-07-24 Richard Biener * genmatch.c (decision_tree::gen_gimple): Split out large subtrees into separate functions. Index: gcc/genmatch.c === --- gcc/genmatch.c (revision 226154) +++ gcc/genmatch.c (working copy) @@ -2949,8 +2962,38 @@ decision_tree::gen_gimple (FILE *f) "a total number of %u nodes\n", root->num_leafs, root->max_level, root->total_size); + const unsigned split_off_point = 8; + for (unsigned n = 1; n <= 3; ++n) { + /* First generate split-out functions. */ + for (unsigned i = 0; i < root->kids.length (); i++) + { + dt_operand *dop = static_cast(root->kids[i]); + expr *e = static_cast(dop->op); + if (e->ops.length () != n) + continue; + + if (dop->num_leafs < split_off_point) + continue; + + fprintf (stderr, "Splitting off %s with %u leafs and %u nodes\n", + e->operation->id, dop->num_leafs, dop->total_size); + + fprintf (f, "\nstatic bool\n" + "gimple_simplify_%s (code_helper *res_code, tree *res_ops,\n" + " gimple_seq *seq, tree (*valueize)(tree),\n" + " code_helper ARG_UNUSED (code), tree type", + e->operation->id); + for (unsigned i = 0; i < n; ++i) + fprintf (f, ", tree op%d", i); + fprintf (f, ")\n"); + fprintf (f, "{\n"); + dop->gen_kids (f, 2, true); + fprintf (f, " return false;\n"); + fprintf (f, "}\n"); + } + fprintf (f, "\nstatic bool\n" "gimple_simplify (code_helper *res_code, tree *res_ops,\n" " gimple_seq *seq, tree (*valueize)(tree),\n" @@ -2976,10 +3019,21 @@ decision_tree::gen_gimple (FILE *f) fprintf (f, "case %s%s:\n", is_a (e->operation) ? "-" : "", e->operation->id); - fprintf (f, " {\n"); - dop->gen_kids (f, 8, true); - fprintf (f, "break;\n"); - fprintf (f, " }\n"); + if (dop->num_leafs < split_off_point) + { + fprintf (f, " {\n"); + dop->gen_kids (f, 8, true); + fprintf (f, "break;\n"); + fprintf (f, " }\n"); + } + else + { + fprintf (f, " return gimple_simplify_%s (res_code, res_ops, " + "seq, valueize, code, type", e->operation->id); + for (unsigned i = 0; i < n; ++i) + fprintf (f, ", op%d", i); + fprintf (f, ");\n"); + } } fprintf (f, "default:;\n" "
Re: [PATCH][RFT] Reduce gimple-match.c compile-time(?)
On Fri, 24 Jul 2015, Richard Biener wrote: > > The following patch implements the simplest approach of splitting > the huge functions in gimple-match.c (not yet generic-match.c). ... > Can people who reported huge compile-times test this patch > and report back? Positive feedback on IRC and thus I am applying the following simplified variant. Bootstrapped and tested on x86_64-unknown-linux-gnu. Richard. 2015-07-27 Richard Biener * genmatch.c (decision_tree::gen_gimple): Split out large subtrees into separate functions. (decision_tree::gen_generic): Likewise. Index: gcc/genmatch.c === --- gcc/genmatch.c (revision 226240) +++ gcc/genmatch.c (working copy) @@ -2951,6 +2964,32 @@ decision_tree::gen_gimple (FILE *f) for (unsigned n = 1; n <= 3; ++n) { + /* First generate split-out functions. */ + for (unsigned i = 0; i < root->kids.length (); i++) + { + dt_operand *dop = static_cast(root->kids[i]); + expr *e = static_cast(dop->op); + if (e->ops.length () != n) + continue; + + fprintf (f, "\nstatic bool\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); + for (unsigned i = 0; i < n; ++i) + fprintf (f, ", tree op%d", i); + fprintf (f, ")\n"); + fprintf (f, "{\n"); + dop->gen_kids (f, 2, true); + fprintf (f, " return false;\n"); + fprintf (f, "}\n"); + } + + /* Then generate the main entry with the outermost switch and + tail-calls to the split-out functions. */ fprintf (f, "\nstatic bool\n" "gimple_simplify (code_helper *res_code, tree *res_ops,\n" " gimple_seq *seq, tree (*valueize)(tree),\n" @@ -2976,10 +3015,11 @@ decision_tree::gen_gimple (FILE *f) fprintf (f, "case %s%s:\n", is_a (e->operation) ? "-" : "", e->operation->id); - fprintf (f, " {\n"); - dop->gen_kids (f, 8, true); - fprintf (f, "break;\n"); - fprintf (f, " }\n"); + fprintf (f, " return gimple_simplify_%s (res_code, res_ops, " + "seq, valueize, code, type", e->operation->id); + for (unsigned i = 0; i < n; ++i) + fprintf (f, ", op%d", i); + fprintf (f, ");\n"); } fprintf (f, "default:;\n" "}\n"); @@ -3003,6 +3043,34 @@ decision_tree::gen_generic (FILE *f) for (unsigned n = 1; n <= 3; ++n) { + /* First generate split-out functions. */ + for (unsigned i = 0; i < root->kids.length (); i++) + { + dt_operand *dop = static_cast(root->kids[i]); + expr *e = static_cast(dop->op); + if (e->ops.length () != n + /* Builtin simplifications are somewhat premature on +GENERIC. The following drops patterns with outermost +calls. It's easy to emit overloads for function code +though if necessary. */ + || e->operation->kind != id_base::CODE) + continue; + + fprintf (f, "\nstatic tree\n" + "generic_simplify_%s (location_t ARG_UNUSED (loc), enum " + "tree_code ARG_UNUSED (code), tree ARG_UNUSED (type)", + e->operation->id); + for (unsigned i = 0; i < n; ++i) + fprintf (f, ", tree op%d", i); + fprintf (f, ")\n"); + fprintf (f, "{\n"); + dop->gen_kids (f, 2, false); + fprintf (f, " return NULL_TREE;\n"); + fprintf (f, "}\n"); + } + + /* Then generate the main entry with the outermost switch and + tail-calls to the split-out functions. */ fprintf (f, "\ntree\n" "generic_simplify (location_t loc, enum tree_code code, " "tree type ATTRIBUTE_UNUSED"); @@ -3030,10 +3098,11 @@ decision_tree::gen_generic (FILE *f) fprintf (f, "CASE_CONVERT:\n"); else fprintf (f, "case %s:\n", e->operation->id); - fprintf (f, " {\n"); - dop->gen_kids (f, 8, false); - fprintf (f, "break;\n" - " }\n"); + fprintf (f, " return generic_simplify_%s (loc, code, type", + e->operation->id); + for (unsigned i = 0; i < n; ++i) + fprintf (f, ", op%d", i); + fprintf (f, ");\n"); } fprintf (f, "default:;\n" "}\n");