diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 93d6514..1e01726 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -9957,12 +9957,6 @@ fold_binary_loc (location_t loc, tree arg00 = CALL_EXPR_ARG (arg0, 0); tree arg10 = CALL_EXPR_ARG (arg1, 0); - /* Optimize sqrt(x)*sqrt(x) as x. */ - if (BUILTIN_SQRT_P (fcode0) - && operand_equal_p (arg00, arg10, 0) - && ! HONOR_SNANS (element_mode (type))) - return arg00; - /* Optimize root(x)*root(y) as root(x*y). */ rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); arg = fold_build2_loc (loc, MULT_EXPR, type, arg00, arg10); @@ -9989,15 +9983,6 @@ fold_binary_loc (location_t loc, tree arg10 = CALL_EXPR_ARG (arg1, 0); tree arg11 = CALL_EXPR_ARG (arg1, 1); - /* Optimize pow(x,y)*pow(z,y) as pow(x*z,y). */ - if (operand_equal_p (arg01, arg11, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - tree arg = fold_build2_loc (loc, MULT_EXPR, type, - arg00, arg10); - return build_call_expr_loc (loc, powfn, 2, arg, arg01); - } - /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z). */ if (operand_equal_p (arg00, arg10, 0)) { @@ -10008,67 +9993,6 @@ fold_binary_loc (location_t loc, } } - /* Optimize tan(x)*cos(x) as sin(x). */ - if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_COS) - || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_COSF) - || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_COSL) - || (fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_TAN) - || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_TANF) - || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_TANL)) - && operand_equal_p (CALL_EXPR_ARG (arg0, 0), - CALL_EXPR_ARG (arg1, 0), 0)) - { - tree sinfn = mathfn_built_in (type, BUILT_IN_SIN); - - if (sinfn != NULL_TREE) - return build_call_expr_loc (loc, sinfn, 1, - CALL_EXPR_ARG (arg0, 0)); - } - - /* Optimize x*pow(x,c) as pow(x,c+1). */ - if (fcode1 == BUILT_IN_POW - || fcode1 == BUILT_IN_POWF - || fcode1 == BUILT_IN_POWL) - { - tree arg10 = CALL_EXPR_ARG (arg1, 0); - tree arg11 = CALL_EXPR_ARG (arg1, 1); - if (TREE_CODE (arg11) == REAL_CST - && !TREE_OVERFLOW (arg11) - && operand_equal_p (arg0, arg10, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); - REAL_VALUE_TYPE c; - tree arg; - - c = TREE_REAL_CST (arg11); - real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); - arg = build_real (type, c); - return build_call_expr_loc (loc, powfn, 2, arg0, arg); - } - } - - /* Optimize pow(x,c)*x as pow(x,c+1). */ - if (fcode0 == BUILT_IN_POW - || fcode0 == BUILT_IN_POWF - || fcode0 == BUILT_IN_POWL) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg0, 1); - if (TREE_CODE (arg01) == REAL_CST - && !TREE_OVERFLOW (arg01) - && operand_equal_p (arg1, arg00, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - REAL_VALUE_TYPE c; - tree arg; - - c = TREE_REAL_CST (arg01); - real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); - arg = build_real (type, c); - return build_call_expr_loc (loc, powfn, 2, arg1, arg); - } - } - /* Canonicalize x*x as pow(x,2.0), which is expanded as x*x. */ if (!in_gimple_form && optimize @@ -10481,109 +10405,10 @@ fold_binary_loc (location_t loc, if (flag_unsafe_math_optimizations) { - enum built_in_function fcode0 = builtin_mathfn_code (arg0); enum built_in_function fcode1 = builtin_mathfn_code (arg1); - /* Optimize sin(x)/cos(x) as tan(x). */ - if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_COS) - || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_COSF) - || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_COSL)) - && operand_equal_p (CALL_EXPR_ARG (arg0, 0), - CALL_EXPR_ARG (arg1, 0), 0)) - { - tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); - - if (tanfn != NULL_TREE) - return build_call_expr_loc (loc, tanfn, 1, CALL_EXPR_ARG (arg0, 0)); - } - - /* Optimize cos(x)/sin(x) as 1.0/tan(x). */ - if (((fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_SIN) - || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_SINF) - || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_SINL)) - && operand_equal_p (CALL_EXPR_ARG (arg0, 0), - CALL_EXPR_ARG (arg1, 0), 0)) - { - tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); - - if (tanfn != NULL_TREE) - { - tree tmp = build_call_expr_loc (loc, tanfn, 1, - CALL_EXPR_ARG (arg0, 0)); - return fold_build2_loc (loc, RDIV_EXPR, type, - build_real (type, dconst1), tmp); - } - } - - /* Optimize sin(x)/tan(x) as cos(x) if we don't care about - NaNs or Infinities. */ - if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_TAN) - || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF) - || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL))) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg1, 0); - - if (! HONOR_NANS (arg00) - && ! HONOR_INFINITIES (element_mode (arg00)) - && operand_equal_p (arg00, arg01, 0)) - { - tree cosfn = mathfn_built_in (type, BUILT_IN_COS); - - if (cosfn != NULL_TREE) - return build_call_expr_loc (loc, cosfn, 1, arg00); - } - } - - /* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about - NaNs or Infinities. */ - if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_SIN) - || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF) - || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL))) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg1, 0); - - if (! HONOR_NANS (arg00) - && ! HONOR_INFINITIES (element_mode (arg00)) - && operand_equal_p (arg00, arg01, 0)) - { - tree cosfn = mathfn_built_in (type, BUILT_IN_COS); - - if (cosfn != NULL_TREE) - { - tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00); - return fold_build2_loc (loc, RDIV_EXPR, type, - build_real (type, dconst1), - tmp); - } - } - } - - /* Optimize pow(x,c)/x as pow(x,c-1). */ - if (fcode0 == BUILT_IN_POW - || fcode0 == BUILT_IN_POWF - || fcode0 == BUILT_IN_POWL) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg0, 1); - if (TREE_CODE (arg01) == REAL_CST - && !TREE_OVERFLOW (arg01) - && operand_equal_p (arg1, arg00, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - REAL_VALUE_TYPE c; - tree arg; - - c = TREE_REAL_CST (arg01); - real_arithmetic (&c, MINUS_EXPR, &c, &dconst1); - arg = build_real (type, c); - return build_call_expr_loc (loc, powfn, 2, arg1, arg); - } - } - /* Optimize a/root(b/c) into a*root(c/b). */ - if (BUILTIN_ROOT_P (fcode1)) + if (BUILTIN_CBRT_P (fcode1)) { tree rootarg = CALL_EXPR_ARG (arg1, 0); @@ -10611,19 +10436,6 @@ fold_binary_loc (location_t loc, return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1); } - /* Optimize x/pow(y,z) into x*pow(y,-z). */ - if (fcode1 == BUILT_IN_POW - || fcode1 == BUILT_IN_POWF - || fcode1 == BUILT_IN_POWL) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); - tree arg10 = CALL_EXPR_ARG (arg1, 0); - tree arg11 = CALL_EXPR_ARG (arg1, 1); - tree neg11 = fold_convert_loc (loc, type, - negate_expr (arg11)); - arg1 = build_call_expr_loc (loc, powfn, 2, arg10, neg11); - return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1); - } } return NULL_TREE; diff --git a/gcc/match.pd b/gcc/match.pd index 71f4127..5b41813 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -55,10 +55,11 @@ along with GCC; see the file COPYING3. If not see (define_operator_list POW10 BUILT_IN_POW10F BUILT_IN_POW10 BUILT_IN_POW10L) (define_operator_list SQRT BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL) (define_operator_list CBRT BUILT_IN_CBRTF BUILT_IN_CBRT BUILT_IN_CBRTL) +(define_operator_list SIN BUILT_IN_SIN BUILT_IN_SINL BUILT_IN_SINF) (define_operator_list COS BUILT_IN_COS BUILT_IN_COSL BUILT_IN_COSF) +(define_operator_list TAN BUILT_IN_TAN BUILT_IN_TANL BUILT_IN_TANF) (define_operator_list COSH BUILT_IN_COSH BUILT_IN_COSHL BUILT_IN_COSHF) - /* Simplifications of operations with one constant operand and simplifications to constants or single values. */ @@ -2006,6 +2007,72 @@ along with GCC; see the file COPYING3. If not see /* fold_builtin_logarithm */ (if (flag_unsafe_math_optimizations) + + /* Simplify sqrt(x) * sqrt(x) -> x. */ + (simplify + (mult (SQRT@1 @0) @1) + (if (!flag_errno_math + && !HONOR_SNANS (type)) + @0)) + + /* 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 tan(x) * cos(x) -> sin(x). */ + (simplify + (mult:c (TAN:s @0) (COS:s @0)) + (SIN @0)) + + /* Simplify x * pow(x,c) -> pow(x,c+1). */ + (simplify + (mult @0 (POW:s @0 REAL_CST@1)) + (if (!flag_errno_math + && !TREE_OVERFLOW (@1)) + (POW @0 (plus @1 { build_one_cst (type); })))) + + /* Simplify sin(x) / cos(x) -> tan(x). */ + (simplify + (rdiv (SIN:s @0) (COS:s @0)) + (TAN @0)) + + /* Simplify cos(x) / sin(x) -> 1 / tan(x). */ + (simplify + (rdiv (COS:s @0) (SIN:s @0)) + (rdiv { build_one_cst (type); } (TAN @0))) + + /* Simplify sin(x) / tan(x) -> cos(x). */ + (simplify + (rdiv (SIN:s @0) (TAN:s @0)) + (if (! HONOR_NANS (@0) + && ! HONOR_INFINITIES (@0)) + (cos @0))) + + /* Simplify tan(x) / sin(x) -> 1.0 / cos(x). */ + (simplify + (rdiv (TAN:s @0) (SIN:s @0)) + (if (! HONOR_NANS (@0) + && ! HONOR_INFINITIES (@0)) + (rdiv { build_one_cst (type); } (COS @0)))) + + /* Simplify pow(x,c) / x -> pow(x,c-1). */ + (simplify + (rdiv (POW:s @0 REAL_CST@1) @0) + (if (! flag_errno_math + && !TREE_OVERFLOW (@1)) + (POW @0 (minus @1 { build_one_cst (type); })))) + + /* Simplify a/root(b/c) into a*root(c/b). */ + (simplify + (rdiv @0 (SQRT:s (rdiv:s @1 @2))) + (mult @0 (SQRT (rdiv @2 @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) exps (EXP EXP2 EXP10)