From d531830f5db3d08322202915d9b44572f410841e Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Mon, 28 Nov 2005 07:29:43 +0000 Subject: [PATCH] re PR middle-end/20219 (Missed optimisation sin / tan --> cos) PR middle-end/20219 * fold-const.c (fold binary) : 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 From-SVN: r107597 --- gcc/ChangeLog | 12 ++++ gcc/fold-const.c | 103 ++++++++++++++++++++--------- gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/gcc.dg/builtins-20.c | 18 +++++ 4 files changed, 110 insertions(+), 30 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 89e752e38464..52b1880eb0da 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2005-11-28 Roger Sayle + Uros Bizjak + + PR middle-end/20219 + * fold-const.c (fold binary) : 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 * gcc.c (main): Change type of argv to "char **". diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 45863ee77e3c..2d80e66eb05f 100644 --- a/gcc/fold-const.c +++ b/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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c38c8803177..75ca6e4214c3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2005-11-28 Roger Sayle + Uros Bizjak + + 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 PR middle-end/24575 diff --git a/gcc/testsuite/gcc.dg/builtins-20.c b/gcc/testsuite/gcc.dg/builtins-20.c index dbcf96c3c07b..a8ada8a8606c 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 } -- 2.47.2