re PR middle-end/20219 (Missed optimisation sin / tan --> cos)
PR middle-end/20219 * fold-const.c (fold binary) <RDIV_EXPR>: Optimize sin(x)/tan(x) as cos(x) and tan(x)/sin(x) as 1.0/cos(x) when flag_unsafe_math_optimizations is set and we don't care about NaNs or Infinities. Move x/expN(y) and x/pow(y,z) transformation into common flag_unsafe_math_optimizations section. testsuite/ * gcc.dg/builtins-20.c: Add checks for sin(x)/tan(x) and tan(x)/sin(x) transformations. Co-Authored-By: Uros Bizjak <uros@kss-loka.si> From-SVN: r107597
This commit is contained in:
parent
401cd90a90
commit
d531830f5d
|
@ -1,3 +1,15 @@
|
|||
2005-11-28 Roger Sayle <roger@eyesopen.com>
|
||||
Uros Bizjak <uros@kss-loka.si>
|
||||
|
||||
PR middle-end/20219
|
||||
* fold-const.c (fold binary) <RDIV_EXPR>: Optimize
|
||||
sin(x)/tan(x) as cos(x) and tan(x)/sin(x) as 1.0/cos(x)
|
||||
when flag_unsafe_math_optimizations is set and
|
||||
we don't care about NaNs or Infinities.
|
||||
|
||||
Move x/expN(y) and x/pow(y,z) transformation into common
|
||||
flag_unsafe_math_optimizations section.
|
||||
|
||||
2005-11-27 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* gcc.c (main): Change type of argv to "char **".
|
||||
|
|
103
gcc/fold-const.c
103
gcc/fold-const.c
|
@ -8363,36 +8363,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|
|||
TREE_OPERAND (arg1, 0));
|
||||
}
|
||||
|
||||
if (flag_unsafe_math_optimizations)
|
||||
{
|
||||
enum built_in_function fcode = builtin_mathfn_code (arg1);
|
||||
/* Optimize x/expN(y) into x*expN(-y). */
|
||||
if (BUILTIN_EXPONENT_P (fcode))
|
||||
{
|
||||
tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
|
||||
tree arg = negate_expr (TREE_VALUE (TREE_OPERAND (arg1, 1)));
|
||||
tree arglist = build_tree_list (NULL_TREE,
|
||||
fold_convert (type, arg));
|
||||
arg1 = build_function_call_expr (expfn, arglist);
|
||||
return fold_build2 (MULT_EXPR, type, arg0, arg1);
|
||||
}
|
||||
|
||||
/* Optimize x/pow(y,z) into x*pow(y,-z). */
|
||||
if (fcode == BUILT_IN_POW
|
||||
|| fcode == BUILT_IN_POWF
|
||||
|| fcode == BUILT_IN_POWL)
|
||||
{
|
||||
tree powfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
|
||||
tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
|
||||
tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, 1)));
|
||||
tree neg11 = fold_convert (type, negate_expr (arg11));
|
||||
tree arglist = tree_cons(NULL_TREE, arg10,
|
||||
build_tree_list (NULL_TREE, neg11));
|
||||
arg1 = build_function_call_expr (powfn, arglist);
|
||||
return fold_build2 (MULT_EXPR, type, arg0, arg1);
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_unsafe_math_optimizations)
|
||||
{
|
||||
enum built_in_function fcode0 = builtin_mathfn_code (arg0);
|
||||
|
@ -8430,6 +8400,53 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|
|||
}
|
||||
}
|
||||
|
||||
/* 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 = TREE_VALUE (TREE_OPERAND (arg0, 1));
|
||||
tree arg01 = TREE_VALUE (TREE_OPERAND (arg1, 1));
|
||||
|
||||
if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
|
||||
&& ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
|
||||
&& operand_equal_p (arg00, arg01, 0))
|
||||
{
|
||||
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
|
||||
|
||||
if (cosfn != NULL_TREE)
|
||||
return build_function_call_expr (cosfn,
|
||||
TREE_OPERAND (arg0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
/* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about
|
||||
NaNs or Infintes. */
|
||||
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 = TREE_VALUE (TREE_OPERAND (arg0, 1));
|
||||
tree arg01 = TREE_VALUE (TREE_OPERAND (arg1, 1));
|
||||
|
||||
if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00)))
|
||||
&& ! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (arg00)))
|
||||
&& operand_equal_p (arg00, arg01, 0))
|
||||
{
|
||||
tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
|
||||
|
||||
if (cosfn != NULL_TREE)
|
||||
{
|
||||
tree tmp = TREE_OPERAND (arg0, 1);
|
||||
tmp = build_function_call_expr (cosfn, tmp);
|
||||
return fold (build (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
|
||||
|
@ -8453,6 +8470,32 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|
|||
return build_function_call_expr (powfn, arglist);
|
||||
}
|
||||
}
|
||||
|
||||
/* Optimize x/expN(y) into x*expN(-y). */
|
||||
if (BUILTIN_EXPONENT_P (fcode1))
|
||||
{
|
||||
tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
|
||||
tree arg = negate_expr (TREE_VALUE (TREE_OPERAND (arg1, 1)));
|
||||
tree arglist = build_tree_list (NULL_TREE,
|
||||
fold_convert (type, arg));
|
||||
arg1 = build_function_call_expr (expfn, arglist);
|
||||
return fold_build2 (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 (TREE_OPERAND (arg1, 0), 0);
|
||||
tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
|
||||
tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1, 1)));
|
||||
tree neg11 = fold_convert (type, negate_expr (arg11));
|
||||
tree arglist = tree_cons(NULL_TREE, arg10,
|
||||
build_tree_list (NULL_TREE, neg11));
|
||||
arg1 = build_function_call_expr (powfn, arglist);
|
||||
return fold_build2 (MULT_EXPR, type, arg0, arg1);
|
||||
}
|
||||
}
|
||||
goto binary;
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2005-11-28 Roger Sayle <roger@eyesopen.com>
|
||||
Uros Bizjak <uros@kss-loka.si>
|
||||
|
||||
PR middle-end/20219
|
||||
* gcc.dg/builtins-20.c: Add checks for sin(x)/tan(x) and
|
||||
tan(x)/sin(x) transformations.
|
||||
|
||||
2005-11-27 Andrew Pinski <pinskia@physics.uc.edu>
|
||||
|
||||
PR middle-end/24575
|
||||
|
|
|
@ -39,6 +39,12 @@ void test1(double x)
|
|||
|
||||
if (cos(x)*tan(x) != sin(x))
|
||||
link_error ();
|
||||
|
||||
if (sin(x)/tan(x) != cos(x))
|
||||
link_error ();
|
||||
|
||||
if (tan(x)/sin(x) != 1.0/cos(x))
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void test2(double x, double y)
|
||||
|
@ -67,6 +73,12 @@ void test1f(float x)
|
|||
|
||||
if (cosf(x)*tanf(x) != sinf(x))
|
||||
link_error ();
|
||||
|
||||
if (sinf(x)/tanf(x) != cosf(x))
|
||||
link_error ();
|
||||
|
||||
if (tanf(x)/sinf(x) != 1.0f/cosf(x))
|
||||
link_error ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -97,6 +109,12 @@ void test1l(long double x)
|
|||
|
||||
if (cosl(x)*tanl(x) != sinl(x))
|
||||
link_error ();
|
||||
|
||||
if (sinl(x)/tanl(x) != cosl(x))
|
||||
link_error ();
|
||||
|
||||
if (tanl(x)/sinl(x) != 1.0l/cosl(x))
|
||||
link_error ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue