]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/20219 (Missed optimisation sin / tan --> cos)
authorRoger Sayle <roger@eyesopen.com>
Mon, 28 Nov 2005 07:29:43 +0000 (07:29 +0000)
committerUros Bizjak <uros@gcc.gnu.org>
Mon, 28 Nov 2005 07:29:43 +0000 (08:29 +0100)
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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-20.c

index 89e752e384640e0c1caed2c0b811863669d76fc6..52b1880eb0da99d0b119f52e19985e341c6588d7 100644 (file)
@@ -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 **".
index 45863ee77e3c90f9cd119ff69d7a255e0d71c12e..2d80e66eb05f08fdaf671e0b8c6e152d64053658 100644 (file)
@@ -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;
 
index 8c38c880317711805b3390c01e21594694e463f9..75ca6e4214c3347739f44e37124d7edaa451af30 100644 (file)
@@ -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
index dbcf96c3c07b6440a6068a0bbe4e1bac6669c057..a8ada8a8606c8d150f04adb6669d56bd2b6971eb 100644 (file)
@@ -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
 }