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" } } */