aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2005-11-28 07:29:43 +0000
committerUros Bizjak <uros@gcc.gnu.org>2005-11-28 08:29:43 +0100
commitd531830f5db3d08322202915d9b44572f410841e (patch)
tree9646964189188ede7d11f7784543cb37d50fac04
parent401cd90a905d8cf4ad2339da824e13943912a89c (diff)
downloadgcc-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/ChangeLog12
-rw-r--r--gcc/fold-const.c103
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/builtins-20.c18
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
}