The following finishes call matching support (see the added pattern
and the testcase amendment).  It also adds basic support for
matching GENERIC expressions and calls - to eventually handle
the weird case of GIMPLE containing a GENERIC tcc_comparison
as operand zero of a COND_EXPR rhs.

Committed.

Richard.

2014-03-13  Richard Biener  <rguent...@suse.de>

        * match.pd: Add pattern matching a call in a sub-expression.
        * genmatch.c (expr::gen_gimple_match): Complete call handling.
        Support matching GENERIC.

        testsuite/
        * gcc.dg/tree-ssa/match-1.c: Adjust.

Index: gcc/match.pd
===================================================================
--- gcc/match.pd        (revision 208478)
+++ gcc/match.pd        (working copy)
@@ -159,6 +202,10 @@ to (minus @1 @0)
 (match_and_simplify
   (BUILT_IN_CABS (complex @0 @0))
   (mult (BUILT_IN_FABS @0) { build_real (TREE_TYPE (@0), real_value_truncate 
(TYPE_MODE (TREE_TYPE (@0)), dconst_sqrt2 ())); }))
+/* One nested fn.  */
+(match_and_simplify
+  (mult (BUILT_IN_POW @0 @1) @0)
+  (BUILT_IN_POW @0 (PLUS_EXPR @1 { build_one_cst (TREE_TYPE (@1)); })))
 
 /* ????s
 
Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c      (revision 208539)
+++ gcc/genmatch.c      (working copy)
@@ -278,9 +278,9 @@ expr::gen_gimple_match (FILE *f, const c
   if (operation->op->kind == id_base::CODE)
     {
       operator_id *op = static_cast <operator_id *> (operation->op);
-      fprintf (f, "{\n");
-      fprintf (f, "if (TREE_CODE (%s) != SSA_NAME) ", name);
-      gen_gimple_match_fail (f, label);
+      /* The GIMPLE variant.  */
+      fprintf (f, "if (TREE_CODE (%s) == SSA_NAME)\n", name);
+      fprintf (f, "  {\n");
       fprintf (f, "gimple def_stmt = SSA_NAME_DEF_STMT (%s);\n", name);
       fprintf (f, "if (!is_gimple_assign (def_stmt)\n"
               "    || gimple_assign_rhs_code (def_stmt) != %s) ",  op->id);
@@ -321,11 +321,83 @@ expr::gen_gimple_match (FILE *f, const c
              fprintf (f, "   }\n");
            }
        }
-      fprintf (f, "}\n");
+      fprintf (f, "  }\n");
+      /* The GENERIC variant.  */
+      fprintf (f, "else if (TREE_CODE (%s) == %s)\n", name, op->id);
+      fprintf (f, "  {\n");
+      for (unsigned i = 0; i < ops.length (); ++i)
+       {
+         fprintf (f, "   {\n");
+         fprintf (f, "     tree op = TREE_OPERAND (%s, %d);\n", name, i);
+         fprintf (f, "     if (valueize && TREE_CODE (op) == SSA_NAME)\n");
+         fprintf (f, "       {\n");
+         fprintf (f, "         op = valueize (op);\n");
+         fprintf (f, "         if (!op) ");
+         gen_gimple_match_fail (f, label);
+         fprintf (f, "       }\n");
+         ops[i]->gen_gimple_match (f, "op", label);
+         fprintf (f, "   }\n");
+       }
+      fprintf (f, "  }\n");
+      fprintf (f, "else ");
+      gen_gimple_match_fail (f, label);
+    }
+  else if (operation->op->kind == id_base::FN)
+    {
+      fn_id *op = static_cast <fn_id *> (operation->op);
+      /* The GIMPLE variant.  */
+      fprintf (f, "if (TREE_CODE (%s) == SSA_NAME)\n", name);
+      fprintf (f, "  {\n");
+      fprintf (f, "gimple def_stmt = SSA_NAME_DEF_STMT (%s);\n", name);
+      fprintf (f, "tree fndecl;\n");
+      fprintf (f, "if (!gimple_call_builtin_p (def_stmt, %s)) ", op->id);
+      gen_gimple_match_fail (f, label);
+      for (unsigned i = 0; i < ops.length (); ++i)
+       {
+         fprintf (f, "   {\n");
+         fprintf (f, "     tree op = gimple_call_arg (def_stmt, %d);\n", i);
+         fprintf (f, "     if (valueize && TREE_CODE (op) == SSA_NAME)\n");
+         fprintf (f, "       {\n");
+         fprintf (f, "         op = valueize (op);\n");
+         fprintf (f, "         if (!op) ");
+         gen_gimple_match_fail (f, label);
+         fprintf (f, "       }\n");
+         ops[i]->gen_gimple_match (f, "op", label);
+         fprintf (f, "   }\n");
+       }
+      fprintf (f, "  }\n");
+      /* GENERIC handling for calls.  */
+      fprintf (f, "else 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",
+              name, name, name, name, name, op->id);
+      fprintf (f, "  {\n");
+      for (unsigned i = 0; i < ops.length (); ++i)
+       {
+         fprintf (f, "   {\n");
+         fprintf (f, "     tree op = CALL_EXPR_ARG (%s, %d);\n", name, i);
+         fprintf (f, "     if (valueize && TREE_CODE (op) == SSA_NAME)\n");
+         fprintf (f, "       {\n");
+         fprintf (f, "         op = valueize (op);\n");
+         fprintf (f, "         if (!op) ");
+         gen_gimple_match_fail (f, label);
+         fprintf (f, "       }\n");
+         ops[i]->gen_gimple_match (f, "op", label);
+         fprintf (f, "   }\n");
+       }
+      fprintf (f, "  }\n");
+      fprintf (f, "else ");
+      gen_gimple_match_fail (f, label);
     }
-  else
-    /* FIXME - implement call support.  */
-    gcc_unreachable ();
+  /* ???  Specifically COND_EXPR could also match on CFG diamonds.
+     (cond@3 @0 @1 @2) is
+     if (@0) goto bb2;
+     bb3:
+     bb2:
+     @3 = PHI <@1(2), @2(3)>
+   */
 }
 
 void
Index: gcc/testsuite/gcc.dg/tree-ssa/match-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/match-1.c     (revision 208478)
+++ gcc/testsuite/gcc.dg/tree-ssa/match-1.c     (working copy)
@@ -1,19 +1,25 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-forwprop2" }  */
+/* { dg-options "-O -fdump-tree-forwprop" }  */
 
-double foo (_Complex double z)
+double test1 (_Complex double z)
 {
   __imag z = 0.;
   return __builtin_cabs (z);
 }
 
-/* We don't have a lattice in forwprop, so the following needs two steps... */
-double bar (double x)
+double test2 (double x)
 {
   _Complex z = x;
   __imag z = x;
   return __builtin_cabs (z);
 }
 
-/* { dg-final { scan-tree-dump-not "cabs" "forwprop2" } } */
+double test3 (double x)
+{
+  double y = __builtin_pow (x, 5.);
+  return y * x;
+}
+
+/* { dg-final { scan-tree-dump-not "cabs" "forwprop1" } } */
+/* { dg-final { scan-tree-dump "pow \\\(\[^,\]*, 6" "forwprop1" } } */
 /* { dg-final { cleanup-tree-dump "forwprop2" } } */

Reply via email to