This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][match-and-simplify] Complete call support, add GENERIC matching support (kind-of)
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 13 Mar 2014 15:56:38 +0100 (CET)
- Subject: [PATCH][match-and-simplify] Complete call support, add GENERIC matching support (kind-of)
- Authentication-results: sourceware.org; auth=none
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 <rguenther@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" } } */