diff options
author | Roger Sayle <roger@eyesopen.com> | 2005-11-28 07:29:43 +0000 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2005-11-28 08:29:43 +0100 |
commit | d531830f5db3d08322202915d9b44572f410841e (patch) | |
tree | 9646964189188ede7d11f7784543cb37d50fac04 | |
parent | 401cd90a905d8cf4ad2339da824e13943912a89c (diff) | |
download | gcc-d531830f5db3d08322202915d9b44572f410841e.zip gcc-d531830f5db3d08322202915d9b44572f410841e.tar.gz gcc-d531830f5db3d08322202915d9b44572f410841e.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/fold-const.c | 103 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-20.c | 18 |
4 files changed, 110 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 89e752e..52b1880 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 **". diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 45863ee..2d80e66 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8365,36 +8365,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) 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); enum built_in_function fcode1 = builtin_mathfn_code (arg1); @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c38c88..75ca6e4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/gcc.dg/builtins-20.c b/gcc/testsuite/gcc.dg/builtins-20.c index dbcf96c3..a8ada8a 100644 --- a/gcc/testsuite/gcc.dg/builtins-20.c +++ b/gcc/testsuite/gcc.dg/builtins-20.c @@ -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 } |