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);
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))
{
}
}
- /* 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
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);
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;
(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. */
/* fold_builtin_logarithm */
(if (flag_unsafe_math_optimizations)
+
+ /* Simplify sqrt(x) * sqrt(x) -> x. */
+ (simplify
+ (mult (SQRT@1 @0) @1)
+ (if (!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 (!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 (!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)