This re-structues GENERIC code to the suggested switch-stmt use
which ideally should behave sanely wrt backtracking now
(fingers crossing - we don't have any testcases yet excercising
the GENERIC code-path).

Installed.

Richard.

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

        * genmatch.c (dt_operand::gen_generic_kids): New function.
        (dt_operand::gen_generic_expr_expr): Conditionalize matching
        of code to GIMPLE code-gen.
        (dt_operand::gen_generic_expr_fn): Likewise.
        (dt_operand::gen_generic_expr): Adjust to close parens.
        (dt_operand::gen_generic): Call gen_generic_kids.
        (decision_tree::gen_generic): Likewise, use a switch stmt.

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c      (revision 212021)
+++ gcc/genmatch.c      (working copy)
@@ -367,6 +367,7 @@ struct dt_operand: public dt_node
 
   void grok_kids(kids_type&);
   void gen_gimple_kids (FILE *);
+  void gen_generic_kids (FILE *);
 };
 
 
@@ -978,8 +979,16 @@ dt_operand::gen_generic_expr_expr (FILE
 {
   unsigned n_ops = e->ops.length ();
 
-  fprintf (f, "if (TREE_CODE (%s) == %s)\n", opname, e->operation->op->id);
-  fprintf (f, "{\n");
+  operator_id *op_id = static_cast <operator_id *> (e->operation->op);
+
+  if (valueize)
+    {
+      if (op_id->code == NOP_EXPR || op_id->code == CONVERT_EXPR)
+       fprintf (f, "if (CONVERT_EXPR_P (%s))\n", opname);
+      else
+       fprintf (f, "if (TREE_CODE (%s) == %s)\n", opname, 
e->operation->op->id);
+      fprintf (f, "{\n");
+    }
 
   for (unsigned i = 0; i < n_ops; ++i)
     {
@@ -1001,13 +1010,16 @@ dt_operand::gen_generic_expr_fn (FILE *f
   unsigned n_ops = e->ops.length ();
   fn_id *op = static_cast <fn_id *> (e->operation->op);
 
-  fprintf (f, "if (TREE_CODE (%s) == CALL_EXPR\n"
-               "    && TREE_CODE (CALL_EXPR_FN (%s)) == ADDR_EXPR\n"
-               "    && TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (%s), 0)) == 
FUNCTION_DECL\n"
-               "    && DECL_BUILT_IN_CLASS (TREE_OPERAND (CALL_EXPR_FN (%s), 
0)) == BUILT_IN_NORMAL\n"
-               "    && DECL_FUNCTION_CODE (TREE_OPERAND (CALL_EXPR_FN (%s), 
0)) == %s)\n",
-               opname, opname, opname, opname, opname, op->id);
-  fprintf (f, "  {\n");
+  if (valueize)
+    {
+      fprintf (f, "if (TREE_CODE (%s) == CALL_EXPR\n"
+              "    && TREE_CODE (CALL_EXPR_FN (%s)) == ADDR_EXPR\n"
+              "    && TREE_CODE (TREE_OPERAND (CALL_EXPR_FN (%s), 0)) == 
FUNCTION_DECL\n"
+              "    && DECL_BUILT_IN_CLASS (TREE_OPERAND (CALL_EXPR_FN (%s), 
0)) == BUILT_IN_NORMAL\n"
+              "    && DECL_FUNCTION_CODE (TREE_OPERAND (CALL_EXPR_FN (%s), 0)) 
== %s)\n",
+              opname, opname, opname, opname, opname, op->id);
+      fprintf (f, "  {\n");
+    }
 
   for (unsigned i = 0; i < n_ops; ++i)
     {
@@ -1028,7 +1040,7 @@ dt_operand::gen_generic_expr (FILE *f, c
 {
   expr *e = static_cast<expr *> (op);
   (e->operation->op->kind == id_base::CODE) ? gen_generic_expr_expr (f, e, 
opname, valueize) : gen_generic_expr_fn (f, e, opname, valueize);
-  return valueize ? e->ops.length () + 1 : 1;
+  return valueize ? e->ops.length () + 1 : 0;
 }
 
 bool
@@ -1197,6 +1209,7 @@ dt_operand::gen_gimple (FILE *f)
   fprintf (f, "}\n");
 }
 
+
 void
 dt_operand::gen_generic (FILE *f)
 {
@@ -1230,8 +1243,7 @@ dt_operand::gen_generic (FILE *f)
 
   unsigned i;
 
-  for (i = 0; i < kids.length (); ++i)
-    kids[i]->gen_generic (f);
+  gen_generic_kids (f);
 
   for (i = 0; i < n_braces; ++i)
     fprintf (f, "}\n");
@@ -1240,6 +1252,100 @@ dt_operand::gen_generic (FILE *f)
 }
 
 void
+dt_operand::gen_generic_kids (FILE *f)
+{
+  bool any = false;
+  for (unsigned j = 0; j < kids.length (); ++j)
+    {
+      dt_node *node = kids[j];
+      if (node->type == DT_OPERAND)
+       {
+         dt_operand *kid = static_cast<dt_operand *>(node);
+         if (kid->op->type == operand::OP_EXPR)
+           any = true;
+       }
+    }
+
+  if (any)
+    {
+      char opname[20];
+      static_cast <dt_operand *>(kids[0])->get_name (opname); 
+      fprintf (f, "switch (TREE_CODE (%s))\n"
+              "{\n", opname);
+      for (unsigned j = 0; j < kids.length (); ++j)
+       {
+         dt_node *node = kids[j];
+         if (node->type != DT_OPERAND)
+           continue;
+         dt_operand *kid = static_cast<dt_operand *>(node);
+         if (kid->op->type != operand::OP_EXPR)
+           continue;
+         expr *e = static_cast <expr *>(kid->op);
+         if (e->operation->op->kind != id_base::CODE)
+           continue;
+
+         /* ??? CONVERT */
+         fprintf (f, "case %s:\n"
+                  "{\n", e->operation->op->id);
+         kid->gen_generic (f);
+         fprintf (f, "break;\n"
+                  "}\n");
+       }
+
+      bool first = true;
+      for (unsigned j = 0; j < kids.length (); ++j)
+       {
+         dt_node *node = kids[j];
+         if (node->type != DT_OPERAND)
+           continue;
+         dt_operand *kid = static_cast<dt_operand *>(node);
+         if (kid->op->type != operand::OP_EXPR)
+           continue;
+         expr *e = static_cast <expr *>(kid->op);
+         if (e->operation->op->kind != id_base::FN)
+           continue;
+
+         if (first)
+           fprintf (f, "case CALL_EXPR:\n"
+                    "{\n"
+                    "tree fndecl = get_callee_fndecl (%s);\n"
+                    "if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == 
BUILT_IN_NORMAL)\n"
+                    "switch (DECL_FUNCTION_CODE (fndecl))\n"
+                    "{\n", opname);
+         first = false;
+
+         fprintf (f, "case %s:\n"
+                  "{\n", e->operation->op->id);
+         kid->gen_generic (f);
+         fprintf (f, "break;\n"
+                  "}\n");
+       }
+      if (!first)
+       fprintf (f, "default:;\n"
+                "}\n"
+                "break;\n"
+                "}\n");
+      /* Close switch of TREE_CODE.  */
+      fprintf (f, "default:;\n"
+              "}\n");
+    }
+
+  for (unsigned j = 0; j < kids.length (); ++j)
+    {
+      dt_node *node = kids[j];
+      if (node->type == DT_OPERAND)
+       {
+         dt_operand *kid = static_cast<dt_operand *>(node);
+         if (kid->op->type == operand::OP_EXPR)
+           continue;
+       }
+
+      node->gen_generic (f);
+    }
+}
+
+
+void
 dt_simplify::gen_gimple (FILE *f)
 {
 
@@ -1412,7 +1518,8 @@ decision_tree::gen_generic (FILE *f)
       fprintf (f, ")\n");
       fprintf (f, "{\n");
 
-      bool first = true;
+      fprintf (f, "switch (code)\n"
+              "{\n");
       for (unsigned i = 0; i < root->kids.length (); i++)
        {
          dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
@@ -1425,18 +1532,18 @@ decision_tree::gen_generic (FILE *f)
              || e->operation->op->kind != id_base::CODE)
            continue;
 
-         if (!first)
-           fprintf (f, "else ");
-         fprintf (f, "if (code == %s)\n", e->operation->op->id);
+         operator_id *op_id = static_cast <operator_id *> (e->operation->op);
+         if (op_id->code == NOP_EXPR || op_id->code == CONVERT_EXPR)
+           fprintf (f, "CASE_CONVERT:\n");
+         else
+           fprintf (f, "case %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;
+         dop->gen_generic_kids (f);
+         fprintf (f, "break;\n"
+                  "}\n");
        }
+      fprintf (f, "default:;\n"
+              "}\n");
 
       fprintf (f, "return NULL_TREE;\n");
       fprintf (f, "}\n");

Reply via email to