diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6dec962d283..75c4c17dd35 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2015-10-15 Richard Sandiford + + PR tree-optimization/67945 + * tree-pass.h (PROP_gimple_opt_math): New property flag. + * generic-match-head.c (canonicalize_math_p): New function. + * gimple-match-head.c: Include tree-pass.h. + (canonicalize_math_p): New function. + * match.pd: Group math built-in rules into simplifications + and canonicalizations. Guard the latter with canonicalize_math_p. + * tree-ssa-math-opts.c (pass_data_cse_sincos): Provide the + PROP_gimple_opt_math property. + 2015-10-15 Marek Polacek PR tree-optimization/67953 diff --git a/gcc/generic-match-head.c b/gcc/generic-match-head.c index 0a7038dfc86..94135b36555 100644 --- a/gcc/generic-match-head.c +++ b/gcc/generic-match-head.c @@ -73,3 +73,12 @@ single_use (tree t ATTRIBUTE_UNUSED) { return true; } + +/* Return true if math operations should be canonicalized, + e.g. sqrt(sqrt(x)) -> pow(x, 0.25). */ + +static inline bool +canonicalize_math_p () +{ + return true; +} diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index 16d8c5b7eb1..8f7291912c7 100644 --- a/gcc/gimple-match-head.c +++ b/gcc/gimple-match-head.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "cgraph.h" #include "gimple-match.h" +#include "tree-pass.h" /* Forward declarations of the private auto-generated matchers. @@ -825,3 +826,12 @@ single_use (tree t) { return TREE_CODE (t) != SSA_NAME || has_zero_uses (t) || has_single_use (t); } + +/* Return true if math operations should be canonicalized, + e.g. sqrt(sqrt(x)) -> pow(x, 0.25). */ + +static inline bool +canonicalize_math_p () +{ + return !cfun || (cfun->curr_properties & PROP_gimple_opt_math) == 0; +} diff --git a/gcc/match.pd b/gcc/match.pd index 24e19a96472..e0ecbe2e776 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2135,11 +2135,25 @@ along with GCC; see the file COPYING3. If not see clearly less optimal and which we'll transform again in forwprop. */ -/* Simplification of math builtins. */ +/* Simplification of math builtins. These rules must all be optimizations + as well as IL simplifications. If there is a possibility that the new + form could be a pessimization, the rule should go in the canonicalization + section that follows this one. + + Rules can generally go in this section if they satisfy one of + the following: + + - the rule describes an identity + + - the rule replaces calls with something as simple as addition or + multiplication + + - the rule contains unary calls only and simplifies the surrounding + arithmetic. (The idea here is to exclude non-unary calls in which + one operand is constant and in which the call is known to be cheap + when the operand has that value.) */ -/* fold_builtin_logarithm */ (if (flag_unsafe_math_optimizations) - /* Simplify sqrt(x) * sqrt(x) -> x. */ (simplify (mult (SQRT@1 @0) @1) @@ -2152,22 +2166,117 @@ along with GCC; see the file COPYING3. If not see (mult (root:s @0) (root:s @1)) (root (mult @0 @1)))) - /* Simplify pow(x,y) * pow(x,z) -> pow(x,y+z). */ - (simplify - (mult (POW:s @0 @1) (POW:s @0 @2)) - (POW @0 (plus @1 @2))) - - /* Simplify pow(x,y) * pow(z,y) -> pow(x*z,y). */ - (simplify - (mult (POW:s @0 @1) (POW:s @2 @1)) - (POW (mult @0 @2) @1)) - /* Simplify expN(x) * expN(y) -> expN(x+y). */ (for exps (EXP EXP2 EXP10 POW10) (simplify (mult (exps:s @0) (exps:s @1)) (exps (plus @0 @1)))) + /* Simplify a/root(b/c) into a*root(c/b). */ + (for root (SQRT CBRT) + (simplify + (rdiv @0 (root:s (rdiv:s @1 @2))) + (mult @0 (root (rdiv @2 @1))))) + + /* Simplify x/expN(y) into x*expN(-y). */ + (for exps (EXP EXP2 EXP10 POW10) + (simplify + (rdiv @0 (exps:s @1)) + (mult @0 (exps (negate @1))))) + + /* Special case, optimize logN(expN(x)) = x. */ + (for logs (LOG LOG2 LOG10 LOG10) + exps (EXP EXP2 EXP10 POW10) + (simplify + (logs (exps @0)) + @0)) + + /* Optimize logN(func()) for various exponential functions. We + want to determine the value "x" and the power "exponent" in + order to transform logN(x**exponent) into exponent*logN(x). */ + (for logs (LOG LOG LOG LOG2 LOG2 LOG2 LOG10 LOG10) + exps (EXP2 EXP10 POW10 EXP EXP10 POW10 EXP EXP2) + (simplify + (logs (exps @0)) + (with { + tree x; + switch (exps) + { + CASE_FLT_FN (BUILT_IN_EXP): + /* Prepare to do logN(exp(exponent)) -> exponent*logN(e). */ + x = build_real_truncate (type, dconst_e ()); + break; + CASE_FLT_FN (BUILT_IN_EXP2): + /* Prepare to do logN(exp2(exponent)) -> exponent*logN(2). */ + x = build_real (type, dconst2); + break; + CASE_FLT_FN (BUILT_IN_EXP10): + CASE_FLT_FN (BUILT_IN_POW10): + /* Prepare to do logN(exp10(exponent)) -> exponent*logN(10). */ + { + REAL_VALUE_TYPE dconst10; + real_from_integer (&dconst10, VOIDmode, 10, SIGNED); + x = build_real (type, dconst10); + } + break; + default: + gcc_unreachable (); + } + } + (mult (logs { x; }) @0)))) + + (for logs (LOG LOG + LOG2 LOG2 + LOG10 LOG10) + exps (SQRT CBRT) + (simplify + (logs (exps @0)) + (with { + tree x; + switch (exps) + { + CASE_FLT_FN (BUILT_IN_SQRT): + /* Prepare to do logN(sqrt(x)) -> 0.5*logN(x). */ + x = build_real (type, dconsthalf); + break; + CASE_FLT_FN (BUILT_IN_CBRT): + /* Prepare to do logN(cbrt(x)) -> (1/3)*logN(x). */ + x = build_real_truncate (type, dconst_third ()); + break; + default: + gcc_unreachable (); + } + } + (mult { x; } (logs @0))))) + + /* logN(pow(x,exponent)) -> exponent*logN(x). */ + (for logs (LOG LOG2 LOG10) + pows (POW) + (simplify + (logs (pows @0 @1)) + (mult @1 (logs @0)))) + + (for sqrts (SQRT) + cbrts (CBRT) + exps (EXP EXP2 EXP10 POW10) + /* sqrt(expN(x)) -> expN(x*0.5). */ + (simplify + (sqrts (exps @0)) + (exps (mult @0 { build_real (type, dconsthalf); }))) + /* cbrt(expN(x)) -> expN(x/3). */ + (simplify + (cbrts (exps @0)) + (exps (mult @0 { build_real_truncate (type, dconst_third ()); }))))) + +/* Canonicalization of sequences of math builtins. These rules represent + IL simplifications but are not necessarily optimizations. + + The sincos pass is responsible for picking "optimal" implementations + of math builtins, which may be more complicated and can sometimes go + the other way, e.g. converting pow into a sequence of sqrts. + We only want to do these canonicalizations before the pass has run. */ + +(if (flag_unsafe_math_optimizations && canonicalize_math_p ()) /* Simplify tan(x) * cos(x) -> sin(x). */ (simplify (mult:c (TAN:s @0) (COS:s @0)) @@ -2203,97 +2312,54 @@ along with GCC; see the file COPYING3. If not see && ! HONOR_INFINITIES (@0)) (rdiv { build_one_cst (type); } (COS @0)))) + /* Simplify pow(x,y) * pow(x,z) -> pow(x,y+z). */ + (simplify + (mult (POW:s @0 @1) (POW:s @0 @2)) + (POW @0 (plus @1 @2))) + + /* Simplify pow(x,y) * pow(z,y) -> pow(x*z,y). */ + (simplify + (mult (POW:s @0 @1) (POW:s @2 @1)) + (POW (mult @0 @2) @1)) + /* Simplify pow(x,c) / x -> pow(x,c-1). */ (simplify (rdiv (POW:s @0 REAL_CST@1) @0) (if (!TREE_OVERFLOW (@1)) (POW @0 (minus @1 { build_one_cst (type); })))) - /* Simplify a/root(b/c) into a*root(c/b). */ - (for root (SQRT CBRT) - (simplify - (rdiv @0 (root:s (rdiv:s @1 @2))) - (mult @0 (root (rdiv @2 @1))))) - - /* Simplify x/expN(y) into x*expN(-y). */ - (for exps (EXP EXP2 EXP10 POW10) - (simplify - (rdiv @0 (exps:s @1)) - (mult @0 (exps (negate @1))))) - /* Simplify x / pow (y,z) -> x * pow(y,-z). */ (simplify (rdiv @0 (POW:s @1 @2)) (mult @0 (POW @1 (negate @2)))) - /* Special case, optimize logN(expN(x)) = x. */ - (for logs (LOG LOG2 LOG10 LOG10) - exps (EXP EXP2 EXP10 POW10) - (simplify - (logs (exps @0)) - @0)) - /* Optimize logN(func()) for various exponential functions. We - want to determine the value "x" and the power "exponent" in - order to transform logN(x**exponent) into exponent*logN(x). */ - (for logs (LOG LOG LOG LOG2 LOG2 LOG2 LOG10 LOG10) - exps (EXP2 EXP10 POW10 EXP EXP10 POW10 EXP EXP2) - (simplify - (logs (exps @0)) - (with { - tree x; - switch (exps) - { - CASE_FLT_FN (BUILT_IN_EXP): - /* Prepare to do logN(exp(exponent) -> exponent*logN(e). */ - x = build_real_truncate (type, dconst_e ()); - break; - CASE_FLT_FN (BUILT_IN_EXP2): - /* Prepare to do logN(exp2(exponent) -> exponent*logN(2). */ - x = build_real (type, dconst2); - break; - CASE_FLT_FN (BUILT_IN_EXP10): - CASE_FLT_FN (BUILT_IN_POW10): - /* Prepare to do logN(exp10(exponent) -> exponent*logN(10). */ - { - REAL_VALUE_TYPE dconst10; - real_from_integer (&dconst10, VOIDmode, 10, SIGNED); - x = build_real (type, dconst10); - } - break; - default: - gcc_unreachable (); - } - } - (mult (logs { x; }) @0)))) - (for logs (LOG LOG - LOG2 LOG2 - LOG10 LOG10) - exps (SQRT CBRT) - (simplify - (logs (exps @0)) - (with { - tree x; - switch (exps) - { - CASE_FLT_FN (BUILT_IN_SQRT): - /* Prepare to do logN(sqrt(x) -> 0.5*logN(x). */ - x = build_real (type, dconsthalf); - break; - CASE_FLT_FN (BUILT_IN_CBRT): - /* Prepare to do logN(cbrt(x) -> (1/3)*logN(x). */ - x = build_real_truncate (type, dconst_third ()); - break; - default: - gcc_unreachable (); - } - } - (mult { x; } (logs @0))))) - /* logN(pow(x,exponent) -> exponent*logN(x). */ - (for logs (LOG LOG2 LOG10) + (for sqrts (SQRT) + cbrts (CBRT) pows (POW) + /* sqrt(sqrt(x)) -> pow(x,1/4). */ (simplify - (logs (pows @0 @1)) - (mult @1 (logs @0))))) + (sqrts (sqrts @0)) + (pows @0 { build_real (type, dconst_quarter ()); })) + /* sqrt(cbrt(x)) -> pow(x,1/6). */ + (simplify + (sqrts (cbrts @0)) + (pows @0 { build_real_truncate (type, dconst_sixth ()); })) + /* cbrt(sqrt(x)) -> pow(x,1/6). */ + (simplify + (cbrts (sqrts @0)) + (pows @0 { build_real_truncate (type, dconst_sixth ()); })) + /* cbrt(cbrt(x)) -> pow(x,1/9), iff x is nonnegative. */ + (simplify + (cbrts (cbrts tree_expr_nonnegative_p@0)) + (pows @0 { build_real_truncate (type, dconst_ninth ()); })) + /* sqrt(pow(x,y)) -> pow(|x|,y*0.5). */ + (simplify + (sqrts (pows @0 @1)) + (pows (abs @0) (mult @1 { build_real (type, dconsthalf); }))) + /* cbrt(pow(x,y)) -> pow(x,y/3), iff x is nonnegative. */ + (simplify + (cbrts (pows tree_expr_nonnegative_p@0 @1)) + (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); }))))) /* Narrowing of arithmetic and logical operations. @@ -2365,44 +2431,3 @@ along with GCC; see the file COPYING3. If not see (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); } (convert (bit_and (op (convert:utype @0) (convert:utype @1)) (convert:utype @4)))))))) - -(if (flag_unsafe_math_optimizations) - (for sqrts (SQRT) - cbrts (CBRT) - exps (EXP EXP2 EXP10 POW10) - /* sqrt(expN(x)) -> expN(x*0.5). */ - (simplify - (sqrts (exps @0)) - (exps (mult @0 { build_real (type, dconsthalf); }))) - /* cbrt(expN(x)) -> expN(x/3). */ - (simplify - (cbrts (exps @0)) - (exps (mult @0 { build_real_truncate (type, dconst_third ()); })))) - - (for sqrts (SQRT) - cbrts (CBRT) - pows (POW) - /* sqrt(sqrt(x)) -> pow(x,1/4). */ - (simplify - (sqrts (sqrts @0)) - (pows @0 { build_real (type, dconst_quarter ()); })) - /* sqrt(cbrt(x)) -> pow(x,1/6). */ - (simplify - (sqrts (cbrts @0)) - (pows @0 { build_real_truncate (type, dconst_sixth ()); })) - /* cbrt(sqrt(x)) -> pow(x,1/6). */ - (simplify - (cbrts (sqrts @0)) - (pows @0 { build_real_truncate (type, dconst_sixth ()); })) - /* cbrt(cbrt(x)) -> pow(x,1/9), iff x is nonnegative. */ - (simplify - (cbrts (cbrts tree_expr_nonnegative_p@0)) - (pows @0 { build_real_truncate (type, dconst_ninth ()); })) - /* sqrt(pow(x,y)) -> pow(|x|,y*0.5). */ - (simplify - (sqrts (pows @0 @1)) - (pows (abs @0) (mult @1 { build_real (type, dconsthalf); }))) - /* cbrt(pow(x,y)) -> pow(x,y/3), iff x is nonnegative. */ - (simplify - (cbrts (pows tree_expr_nonnegative_p@0 @1)) - (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); }))))) diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 91f63a8d4a6..c37e4b2c2e9 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -222,6 +222,10 @@ protected: #define PROP_gimple_lvec (1 << 12) /* lowered vector */ #define PROP_gimple_eomp (1 << 13) /* no OpenMP directives */ #define PROP_gimple_lva (1 << 14) /* No va_arg internal function. */ +#define PROP_gimple_opt_math (1 << 15) /* Disable canonicalization + of math functions; the + current choices have + been optimized. */ #define PROP_trees \ (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp) diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 21604f592ed..92236422f2a 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1689,7 +1689,7 @@ const pass_data pass_data_cse_sincos = OPTGROUP_NONE, /* optinfo_flags */ TV_NONE, /* tv_id */ PROP_ssa, /* properties_required */ - 0, /* properties_provided */ + PROP_gimple_opt_math, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ TODO_update_ssa, /* todo_flags_finish */