This handles $subject which allows us to simplify the return expression
all the way to w for the following testcase (going via
pow (x, -0.5) * x -> pow (x, 0.5) -> sqrt (w * w) -> w)

double test4 (double w)
{
  double x = w * w;
  double y = __builtin_pow (x, -0.5);
  return y * x;
}

Committed to the branch.

Richard.

2014-05-14  Richard Biener  <rguent...@suse.de>

        * gimple-match-head.c (REAL_CST_P): New predicate.
        (gimple_match_and_simplify): Support re-simplification of
        two-argument builtin functions.
        * match.pd: Add pattern simplifying pow (x, 0.5) to sqrt (x).

        testsuite/
        * gcc.dg/tree-ssa/match-1.c: Add testcase involving two-argument
        function re-simplification.

Index: gcc/gimple-match-head.c
===================================================================
--- gcc/gimple-match-head.c     (revision 210415)
+++ gcc/gimple-match-head.c     (working copy)
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.
 
 #define INTEGER_CST_P(node) (TREE_CODE(node) == INTEGER_CST)
 #define integral_op_p(node) INTEGRAL_TYPE_P(TREE_TYPE(node))
+#define REAL_CST_P(node) (TREE_CODE(node) == REAL_CST)
 
 
 /* Helper to transparently allow tree codes and builtin function codes
@@ -495,6 +496,27 @@ gimple_match_and_simplify (gimple stmt,
                                              rcode, ops,
                                              seq, valueize);
          }
+       case 2:
+         {
+           tree arg1 = gimple_call_arg (stmt, 0);
+           if (valueize && TREE_CODE (arg1) == SSA_NAME)
+             {
+               arg1 = valueize (arg1);
+               if (!arg1)
+                 return false;
+             }
+           tree arg2 = gimple_call_arg (stmt, 0);
+           if (valueize && TREE_CODE (arg2) == SSA_NAME)
+             {
+               arg2 = valueize (arg2);
+               if (!arg2)
+                 return false;
+             }
+           return gimple_match_and_simplify (DECL_FUNCTION_CODE (decl),
+                                             type, arg1, arg2,
+                                             rcode, ops,
+                                             seq, valueize);
+         }
        default:
          return false;
        }
Index: gcc/match.pd
===================================================================
--- gcc/match.pd        (revision 210414)
+++ gcc/match.pd        (working copy)
@@ -163,6 +163,10 @@ to (minus @1 @0)
 (match_and_simplify
   (mult (BUILT_IN_POW @0 @1) @0)
   (BUILT_IN_POW @0 (PLUS_EXPR @1 { build_one_cst (TREE_TYPE (@1)); })))
+(match_and_simplify
+  (BUILT_IN_POW @0 REAL_CST_P@1)
+  if (REAL_VALUES_EQUAL (TREE_REAL_CST (@1), dconsthalf))
+  (BUILT_IN_SQRT @0))
 
 /* ????s
 
Index: gcc/testsuite/gcc.dg/tree-ssa/match-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/match-1.c     (revision 210414)
+++ gcc/testsuite/gcc.dg/tree-ssa/match-1.c     (working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-forwprop" }  */
+/* { dg-options "-O -fdump-tree-forwprop1-details" }  */
 
 double test1 (_Complex double z)
 {
@@ -7,6 +7,8 @@ double test1 (_Complex double z)
   return __builtin_cabs (z);
 }
 
+/* { dg-final { scan-tree-dump "gimple_match_and_simplified to \[^\n\r\]*fabs" 
"forwprop1" } } */
+
 double test2 (double x)
 {
   _Complex z = x;
@@ -14,12 +16,23 @@ double test2 (double x)
   return __builtin_cabs (z);
 }
 
+/* { dg-final { scan-tree-dump "gimple_match_and_simplified to \[^\n\r\]*= 
_\\d\+ \\* 1.41" "forwprop1" } } */
+
 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" } } */
+/* { dg-final { scan-tree-dump "gimple_match_and_simplified to \[^\n\r\]*pow 
\\(x_\\d\+\\(D\\), 6" "forwprop1" } } */
+
+double test4 (double w)
+{
+  double x = w * w;
+  double y = __builtin_pow (x, -0.5);
+  return y * x;
+}
+
+/* { dg-final { scan-tree-dump "gimple_match_and_simplified to \[^\n\r\]*= 
w_\\d\+\\(D\\)" "forwprop1" } } */
+
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */

Reply via email to