builtins.c (fold_builtin): Optimize cos(-x) as cos(x).
* builtins.c (fold_builtin): Optimize cos(-x) as cos(x). * fold-const.c (fold <NEGATE_EXPR>): Convert -f(x) into f(-x) when x is easily negated and f is sin, tan or atan. (fold <MULT_EXPR>): Optimize tan(x)*cos(x) and cos(x)*tan(x) as sin(x) with flag_unsafe_math_optimizations. (fold <RDIV_EXPR>): With flag_unsafe_math_optimizations fold sin(x)/cos(x) as tan(x) and cos(x)/sin(x) as 1.0/tan(x). * gcc.dg/builtins-20.c: New test case. From-SVN: r67701
This commit is contained in:
parent
8936c82f1e
commit
9f0a7f9dcc
@ -1,3 +1,13 @@
|
||||
2003-06-10 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* builtins.c (fold_builtin): Optimize cos(-x) as cos(x).
|
||||
* fold-const.c (fold <NEGATE_EXPR>): Convert -f(x) into f(-x)
|
||||
when x is easily negated and f is sin, tan or atan.
|
||||
(fold <MULT_EXPR>): Optimize tan(x)*cos(x) and cos(x)*tan(x) as
|
||||
sin(x) with flag_unsafe_math_optimizations.
|
||||
(fold <RDIV_EXPR>): With flag_unsafe_math_optimizations fold
|
||||
sin(x)/cos(x) as tan(x) and cos(x)/sin(x) as 1.0/tan(x).
|
||||
|
||||
2003-06-10 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* fold-const.c (fold <EQ_EXPR>): Don't fold x == x only if x
|
||||
|
@ -5346,6 +5346,14 @@ fold_builtin (exp)
|
||||
/* Optimize cos(0.0) = 1.0. */
|
||||
if (real_zerop (arg))
|
||||
return build_real (type, dconst1);
|
||||
|
||||
/* Optimize cos(-x) into cos(x). */
|
||||
if (TREE_CODE (arg) == NEGATE_EXPR)
|
||||
{
|
||||
tree arglist = build_tree_list (NULL_TREE,
|
||||
TREE_OPERAND (arg, 0));
|
||||
return build_function_call_expr (fndecl, arglist);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
119
gcc/fold-const.c
119
gcc/fold-const.c
@ -5376,6 +5376,33 @@ fold (expr)
|
||||
return build (MINUS_EXPR, type, TREE_OPERAND (arg0, 1),
|
||||
TREE_OPERAND (arg0, 0));
|
||||
|
||||
/* Convert -f(x) into f(-x) where f is sin, tan or atan. */
|
||||
switch (builtin_mathfn_code (arg0))
|
||||
{
|
||||
case BUILT_IN_SIN:
|
||||
case BUILT_IN_SINF:
|
||||
case BUILT_IN_SINL:
|
||||
case BUILT_IN_TAN:
|
||||
case BUILT_IN_TANF:
|
||||
case BUILT_IN_TANL:
|
||||
case BUILT_IN_ATAN:
|
||||
case BUILT_IN_ATANF:
|
||||
case BUILT_IN_ATANL:
|
||||
if (negate_expr_p (TREE_VALUE (TREE_OPERAND (arg0, 1))))
|
||||
{
|
||||
tree fndecl, arg, arglist;
|
||||
|
||||
fndecl = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
|
||||
arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
|
||||
arg = fold (build1 (NEGATE_EXPR, type, arg));
|
||||
arglist = build_tree_list (NULL_TREE, arg);
|
||||
return build_function_call_expr (fndecl, arglist);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return t;
|
||||
|
||||
case ABS_EXPR:
|
||||
@ -5965,6 +5992,41 @@ fold (expr)
|
||||
return build_function_call_expr (powfn, arglist);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (TREE_VALUE (TREE_OPERAND (arg0, 1)),
|
||||
TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
|
||||
{
|
||||
tree sinfn;
|
||||
|
||||
switch (fcode0)
|
||||
{
|
||||
case BUILT_IN_TAN:
|
||||
case BUILT_IN_COS:
|
||||
sinfn = implicit_built_in_decls[BUILT_IN_SIN];
|
||||
break;
|
||||
case BUILT_IN_TANF:
|
||||
case BUILT_IN_COSF:
|
||||
sinfn = implicit_built_in_decls[BUILT_IN_SINF];
|
||||
break;
|
||||
case BUILT_IN_TANL:
|
||||
case BUILT_IN_COSL:
|
||||
sinfn = implicit_built_in_decls[BUILT_IN_SINL];
|
||||
break;
|
||||
default:
|
||||
sinfn = NULL_TREE;
|
||||
}
|
||||
|
||||
if (sinfn != NULL_TREE)
|
||||
return build_function_call_expr (sinfn,
|
||||
TREE_OPERAND (arg0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
goto associate;
|
||||
@ -6166,6 +6228,63 @@ fold (expr)
|
||||
return fold (build (MULT_EXPR, type, arg0, arg1));
|
||||
}
|
||||
}
|
||||
|
||||
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 (TREE_VALUE (TREE_OPERAND (arg0, 1)),
|
||||
TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
|
||||
{
|
||||
tree tanfn;
|
||||
|
||||
if (fcode0 == BUILT_IN_SIN)
|
||||
tanfn = implicit_built_in_decls[BUILT_IN_TAN];
|
||||
else if (fcode0 == BUILT_IN_SINF)
|
||||
tanfn = implicit_built_in_decls[BUILT_IN_TANF];
|
||||
else if (fcode0 == BUILT_IN_SINL)
|
||||
tanfn = implicit_built_in_decls[BUILT_IN_TANL];
|
||||
else
|
||||
tanfn = NULL_TREE;
|
||||
|
||||
if (tanfn != NULL_TREE)
|
||||
return build_function_call_expr (tanfn,
|
||||
TREE_OPERAND (arg0, 1));
|
||||
}
|
||||
|
||||
/* 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 (TREE_VALUE (TREE_OPERAND (arg0, 1)),
|
||||
TREE_VALUE (TREE_OPERAND (arg1, 1)), 0))
|
||||
{
|
||||
tree tanfn;
|
||||
|
||||
if (fcode0 == BUILT_IN_COS)
|
||||
tanfn = implicit_built_in_decls[BUILT_IN_TAN];
|
||||
else if (fcode0 == BUILT_IN_COSF)
|
||||
tanfn = implicit_built_in_decls[BUILT_IN_TANF];
|
||||
else if (fcode0 == BUILT_IN_COSL)
|
||||
tanfn = implicit_built_in_decls[BUILT_IN_TANL];
|
||||
else
|
||||
tanfn = NULL_TREE;
|
||||
|
||||
if (tanfn != NULL_TREE)
|
||||
{
|
||||
tree tmp = TREE_OPERAND (arg0, 1);
|
||||
tmp = build_function_call_expr (tanfn, tmp);
|
||||
return fold (build (RDIV_EXPR, type,
|
||||
build_real (type, dconst1),
|
||||
tmp));
|
||||
}
|
||||
}
|
||||
}
|
||||
goto binary;
|
||||
|
||||
case TRUNC_DIV_EXPR:
|
||||
|
@ -1,3 +1,7 @@
|
||||
2003-06-10 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.dg/builtins-20.c: New test case.
|
||||
|
||||
2003-06-10 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/11131
|
||||
|
108
gcc/testsuite/gcc.dg/builtins-20.c
Normal file
108
gcc/testsuite/gcc.dg/builtins-20.c
Normal file
@ -0,0 +1,108 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Verify that built-in math function constant folding doesn't break
|
||||
anything and produces the expected results.
|
||||
|
||||
Written by Roger Sayle, 8th June 2003. */
|
||||
|
||||
/* { dg-do link } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
extern void link_error(void);
|
||||
|
||||
void test1(double x)
|
||||
{
|
||||
if (cos(x) != cos(-x))
|
||||
link_error ();
|
||||
|
||||
if (sin(x)/cos(x) != tan(x))
|
||||
link_error ();
|
||||
|
||||
if (cos(x)/sin(x) != 1.0/tan(x))
|
||||
link_error ();
|
||||
|
||||
if (tan(x)*cos(x) != sin(x))
|
||||
link_error ();
|
||||
|
||||
if (cos(x)*tan(x) != sin(x))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void test2(double x, double y)
|
||||
{
|
||||
if (-tan(x-y) != tan(y-x))
|
||||
link_error ();
|
||||
|
||||
if (-sin(x-y) != sin(y-x))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void test1f(float x)
|
||||
{
|
||||
if (cosf(x) != cosf(-x))
|
||||
link_error ();
|
||||
|
||||
if (sinf(x)/cosf(x) != tanf(x))
|
||||
link_error ();
|
||||
|
||||
if (cosf(x)/sinf(x) != 1.0f/tanf(x))
|
||||
link_error ();
|
||||
|
||||
if (tanf(x)*cosf(x) != sinf(x))
|
||||
link_error ();
|
||||
|
||||
if (cosf(x)*tanf(x) != sinf(x))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void test2f(float x, float y)
|
||||
{
|
||||
if (-tanf(x-y) != tanf(y-x))
|
||||
link_error ();
|
||||
|
||||
if (-sinf(x-y) != sinf(y-x))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
|
||||
void test1l(long double x)
|
||||
{
|
||||
if (cosl(x) != cosl(-x))
|
||||
link_error ();
|
||||
|
||||
if (sinl(x)/cosl(x) != tanl(x))
|
||||
link_error ();
|
||||
|
||||
if (cosl(x)/sinl(x) != 1.0l/tanl(x))
|
||||
link_error ();
|
||||
|
||||
if (tanl(x)*cosl(x) != sinl(x))
|
||||
link_error ();
|
||||
|
||||
if (cosl(x)*tanl(x) != sinl(x))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void test2l(long double x, long double y)
|
||||
{
|
||||
if (-tanl(x-y) != tanl(y-x))
|
||||
link_error ();
|
||||
|
||||
if (-sinl(x-y) != sinl(y-x))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test1 (1.0);
|
||||
test2 (1.0, 2.0);
|
||||
|
||||
test1f (1.0f);
|
||||
test2f (1.0f, 2.0f);
|
||||
|
||||
test1l (1.0l);
|
||||
test2l (1.0l, 2.0l);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user