[PATCH][RFT] Reduce gimple-match.c compile-time(?)

2015-07-24 Thread Richard Biener

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(?)

2015-07-27 Thread Richard Biener
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");