The following patch enables running the GENERIC match-and-simplify
portion via fold_{unary,binary,ternary}.  One pattern needs
disabling to avoid endless recursion from addr-expression expansion
so I added the planned defines.  I've also split the generated
routines into three again (will help the compiler optimizing those)
because then we can create the "final" API for the GENERIC part
directly.

Installed.

Richard.

2014-06-25  Richard Biener  <rguent...@suse.de>

        * genmatch.c (decision_tree::gen_gimple): Create three
        gimple_match_and_simplify overloads again.
        (decision_tree::gen_generic): Likewise.  Create final API
        with enum tree_code arguments.
        (main): Define GIMPLE or GENERIC dependent on code generation mode.
        * gimple-match-head.c (gimple_match_and_simplify): Adjust
        prototypes.
        * match.pd: Disable P p+ CST -> &MEM[P, CST] transform for GENERIC.
        * fold-const.c (fold_unary_loc): First dispatch to
        generic_match_and_simplify.
        (fold_binary_loc): Likewise.
        (fold_ternary_loc): Likewise.

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c      (revision 211968)
+++ gcc/genmatch.c      (working copy)
@@ -1253,64 +1253,85 @@ dt_simplify::gen_generic (FILE *f)
 void
 decision_tree::gen_gimple (FILE *f)
 {
-  fprintf (f, "static bool\n"
-          "gimple_match_and_simplify (code_helper *res_code, tree *res_ops,\n"
-          "                           gimple_seq *seq, tree 
(*valueize)(tree),\n"
-          "                           code_helper code, tree type");
-  for (unsigned i = 0; i < 3; ++i)
-    fprintf (f, ", tree op%d", i);
-  fprintf (f, ")\n");
-  fprintf (f, "{\n");
-
-  for (unsigned i = 0; i < root->kids.length (); i++)
-    {
-      dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
-      expr *e = static_cast<expr *>(dop->op);
-
-      if (i)
-        fprintf (f, "else ");
-      fprintf (f, "if (code == %s)\n", e->operation->op->id);
+  for (unsigned n = 1; n <= 3; ++n)
+    {
+      fprintf (f, "\nstatic bool\n"
+              "gimple_match_and_simplify (code_helper *res_code, tree 
*res_ops,\n"
+              "                           gimple_seq *seq, tree 
(*valueize)(tree),\n"
+              "                           code_helper code, tree type");
+      for (unsigned i = 0; i < n; ++i)
+       fprintf (f, ", tree op%d", i);
+      fprintf (f, ")\n");
       fprintf (f, "{\n");
 
-      for (unsigned j = 0; j < dop->kids.length (); ++j)
-       dop->kids[j]->gen_gimple (f);
+      bool first = true;
+      for (unsigned i = 0; i < root->kids.length (); i++)
+       {
+         dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
+         expr *e = static_cast<expr *>(dop->op);
+         if (e->ops.length () != n)
+           continue;
+
+         if (!first)
+           fprintf (f, "else ");
+         fprintf (f, "if (code == %s)\n", e->operation->op->id);
+         fprintf (f, "{\n");
+
+         for (unsigned j = 0; j < dop->kids.length (); ++j)
+           dop->kids[j]->gen_gimple (f);
+
+         fprintf (f, "}\n");
+
+         first = false;
+       }
 
+      fprintf (f, "return false;\n");
       fprintf (f, "}\n");
     }
-
-  fprintf (f, "return false;\n");
-  fprintf (f, "}\n");
 }
 
 
 void
 decision_tree::gen_generic (FILE *f)
 {
-  fprintf (f, "tree\n"
-          "generic_match_and_simplify (code_helper code, tree type");
-  for (unsigned i = 0; i < 3; ++i)
-    fprintf (f, ", tree op%d", i);
-  fprintf (f, ")\n");
-  fprintf (f, "{\n");
-
-  for (unsigned i = 0; i < root->kids.length (); i++)
-    {
-      dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
-      expr *e = static_cast<expr *>(dop->op);
-
-      if (i)
-        fprintf (f, "else ");
-      fprintf (f, "if (code == %s)\n", e->operation->op->id);
+  for (unsigned n = 1; n <= 3; ++n)
+    {
+      fprintf (f, "\ntree\n"
+              "generic_match_and_simplify (enum tree_code code, tree type");
+      for (unsigned i = 0; i < n; ++i)
+       fprintf (f, ", tree op%d", i);
+      fprintf (f, ")\n");
       fprintf (f, "{\n");
 
-      for (unsigned j = 0; j < dop->kids.length (); ++j)
-       dop->kids[j]->gen_generic (f);
+      bool first = true;
+      for (unsigned i = 0; i < root->kids.length (); i++)
+       {
+         dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
+         expr *e = static_cast<expr *>(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->op->kind != id_base::CODE)
+           continue;
+
+         if (!first)
+           fprintf (f, "else ");
+         fprintf (f, "if (code == %s)\n", e->operation->op->id);
+         fprintf (f, "{\n");
+
+         for (unsigned j = 0; j < dop->kids.length (); ++j)
+           dop->kids[j]->gen_generic (f);
+
+         fprintf (f, "}\n");
+
+         first = false;
+       }
 
+      fprintf (f, "return NULL_TREE;\n");
       fprintf (f, "}\n");
     }
-
-  fprintf (f, "return NULL_TREE;\n");
-  fprintf (f, "}\n");
 }
 
 
@@ -1697,6 +1718,14 @@ main(int argc, char **argv)
   if (argc != 3)
     return 1;
 
+  bool gimple;
+  if (strcmp (argv[1], "-gimple") == 0)
+    gimple = true;
+  else if (strcmp (argv[1], "-generic") == 0)
+    gimple = false;
+  else
+    return 1;
+
   line_table = XCNEW (struct line_maps);
   linemap_init (line_table);
   line_table->reallocator = xrealloc;
@@ -1708,6 +1737,7 @@ main(int argc, char **argv)
 
   if (!cpp_read_main_file (r, argv[2]))
     return 1;
+  cpp_define (r, gimple ? "GIMPLE=1": "GENERIC=1");
 
   /* Pre-seed operators.  */
   operators.create (1024);
@@ -1756,18 +1786,16 @@ main(int argc, char **argv)
 
   dt.print (stderr);
  
-  if (strcmp (argv[1], "-gimple") == 0)
+  if (gimple)
     {
       write_header (stdout, simplifiers, "gimple-match-head.c");
       dt.gen_gimple (stdout);
     }
-  else if (strcmp (argv[1], "-generic") == 0)
+  else
     {
       write_header (stdout, simplifiers, "generic-match-head.c");
       dt.gen_generic (stdout);
     }
-  else
-    return 1;
 
   cpp_finish (r, NULL);
   cpp_destroy (r);
Index: gcc/gimple-match-head.c
===================================================================
--- gcc/gimple-match-head.c     (revision 211941)
+++ gcc/gimple-match-head.c     (working copy)
@@ -60,13 +60,18 @@ private:
   int rep;
 };
 
-/* Forward declarations of the private auto-generated matcher.
-   It expects valueized operands in canonical order and does not
+/* 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_match_and_simplify (code_helper *, tree *,
                                       gimple_seq *, tree (*)(tree),
-                                      code_helper, tree,
-                                      tree, tree = NULL_TREE, tree = 
NULL_TREE);
+                                      code_helper, tree, tree);
+static bool gimple_match_and_simplify (code_helper *, tree *,
+                                      gimple_seq *, tree (*)(tree),
+                                      code_helper, tree, tree, tree);
+static bool gimple_match_and_simplify (code_helper *, tree *,
+                                      gimple_seq *, tree (*)(tree),
+                                      code_helper, tree, tree, tree, tree);
 
 
 /* Return whether T is a constant that we'll dispatch to fold to
Index: gcc/match.pd
===================================================================
--- gcc/match.pd        (revision 211903)
+++ gcc/match.pd        (working copy)
@@ -86,6 +86,10 @@ along with GCC; see the file COPYING3.
    invariant_addr + cst.  It may not be generally wanted
    (builtin-object-size) and thus may want to be restricted to 'simple'
    forms like &mem-ref or &decl.  */
+/* Disable for GENERIC, this causes endless recursions of addr-expr
+   expansion which folds a POINTER_PLUS_EXPR and doesn't expect
+   an ADDR_EXPR in return.  */
+#if GIMPLE
 (match_and_simplify
   (pointer_plus (addr@2 @0) INTEGER_CST_P@1)
   if (is_gimple_min_invariant (@2))
@@ -100,6 +104,7 @@ along with GCC; see the file COPYING3.
                    build_fold_addr_expr (base),
                    build_int_cst (ptr_type_node, off)));
   })
+#endif
 
 
 /* Transforms formerly done by tree-ssa-forwprop.c:associate_plusminus  */
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    (revision 211887)
+++ gcc/fold-const.c    (working copy)
@@ -7757,6 +7757,11 @@ fold_unary_loc (location_t loc, enum tre
   gcc_assert (IS_EXPR_CODE_CLASS (kind)
              && TREE_CODE_LENGTH (code) == 1);
 
+  extern tree generic_match_and_simplify (enum tree_code, tree, tree);
+  tem = generic_match_and_simplify (code, type, op0);
+  if (tem)
+    return tem;
+
   arg0 = op0;
   if (arg0)
     {
@@ -10041,6 +10046,11 @@ fold_binary_loc (location_t loc,
              && op0 != NULL_TREE
              && op1 != NULL_TREE);
 
+  extern tree generic_match_and_simplify (enum tree_code, tree, tree, tree);
+  tem = generic_match_and_simplify (code, type, op0, op1);
+  if (tem)
+    return tem;
+
   arg0 = op0;
   arg1 = op1;
 
@@ -13985,6 +13995,11 @@ fold_ternary_loc (location_t loc, enum t
   gcc_assert (IS_EXPR_CODE_CLASS (kind)
              && TREE_CODE_LENGTH (code) == 3);
 
+  extern tree generic_match_and_simplify (enum tree_code, tree, tree, tree, 
tree);
+  tem = generic_match_and_simplify (code, type, op0, op1, op2);
+  if (tem)
+    return tem;
+
   /* Strip any conversions that don't change the mode.  This is safe
      for every expression, except for a comparison expression because
      its signedness is derived from its operands.  So, in the latter

Reply via email to