]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
emit-rtl.c (dconstm2, dconsthalf): New real constants.
authorRoger Sayle <roger@eyesopen.com>
Mon, 31 Mar 2003 14:30:29 +0000 (14:30 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Mon, 31 Mar 2003 14:30:29 +0000 (14:30 +0000)
* emit-rtl.c (dconstm2, dconsthalf): New real constants.
(init_emit_once): Initialize dconstm2 and dconsthalf here.
* real.h (dconstm2, dconsthalf): Add prototypes here.
* real.c (real_sqrt): Use dconsthalf rather than local copy.
* builtins.c (fold_builtin): When optimizing sqrt(exp(x)) as
exp(x/2.0) remember to fold the division if possible.
Fold sin(0.0) as 0.0, cos(0.0) as 1.0, pow(x,1.0) as x,
pow(x,-1.0) as 1.0/x, pow(x,2.0) as x*x, pow(x,-2.0) as
1.0/(x*x) and pow(x,0.5) as sqrt(x).

* gcc.dg/builtins-3.c: Add new tests for sin and cos.
* gcc.dg/builtins-7.c: New test case.
* gcc.dg/builtins-8.c: New test case.

From-SVN: r65088

gcc/ChangeLog
gcc/builtins.c
gcc/emit-rtl.c
gcc/real.c
gcc/real.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-3.c
gcc/testsuite/gcc.dg/builtins-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-8.c [new file with mode: 0644]

index fd3e32a6af914a2393558423e72ce0568a744874..c7b59f0071f2b5b3b964e04d872ac2eed90bb52e 100644 (file)
@@ -1,3 +1,15 @@
+2003-03-31  Roger Sayle  <roger@eyesopen.com>
+
+       * emit-rtl.c (dconstm2, dconsthalf): New real constants.
+       (init_emit_once): Initialize dconstm2 and dconsthalf here.
+       * real.h (dconstm2, dconsthalf): Add prototypes here.
+       * real.c (real_sqrt): Use dconsthalf rather than local copy.
+       * builtins.c (fold_builtin): When optimizing sqrt(exp(x)) as
+       exp(x/2.0) remember to fold the division if possible.
+       Fold sin(0.0) as 0.0, cos(0.0) as 1.0, pow(x,1.0) as x,
+       pow(x,-1.0) as 1.0/x, pow(x,2.0) as x*x, pow(x,-2.0) as
+       1.0/(x*x) and pow(x,0.5) as sqrt(x).
+
 2003-03-31  Kazu Hirata  <kazu@cs.umass.edu>
 
        * config/h8300/h8300.md (a new peephole2): New.
index b6fe4b4fbe60821269659184af7029e3bfe5631f..d446185c8c563aefbcb0f71eb94f02beee241384 100644 (file)
@@ -4743,15 +4743,41 @@ fold_builtin (exp)
                  || fcode == BUILT_IN_EXPL))
            {
              tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
-             arg = build (RDIV_EXPR, type,
-                          TREE_VALUE (TREE_OPERAND (arg, 1)),
-                          build_real (type, dconst2));
+             arg = fold (build (RDIV_EXPR, type,
+                                TREE_VALUE (TREE_OPERAND (arg, 1)),
+                                build_real (type, dconst2)));
              arglist = build_tree_list (NULL_TREE, arg);
              return build_function_call_expr (expfn, arglist);
            }
        }
       break;
 
+    case BUILT_IN_SIN:
+    case BUILT_IN_SINF:
+    case BUILT_IN_SINL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+       {
+         tree arg = TREE_VALUE (arglist);
+
+         /* Optimize sin(0.0) = 0.0.  */
+         if (real_zerop (arg))
+           return build_real (type, dconst0);
+       }
+      break;
+
+    case BUILT_IN_COS:
+    case BUILT_IN_COSF:
+    case BUILT_IN_COSL:
+      if (validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+       {
+         tree arg = TREE_VALUE (arglist);
+
+         /* Optimize cos(0.0) = 1.0.  */
+         if (real_zerop (arg))
+           return build_real (type, dconst1);
+       }
+      break;
+
     case BUILT_IN_EXP:
     case BUILT_IN_EXPF:
     case BUILT_IN_EXPL:
@@ -4816,13 +4842,75 @@ fold_builtin (exp)
          tree arg0 = TREE_VALUE (arglist);
          tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
 
-         /* Optimize pow(x,0.0) = 1.0.  */
-         if (real_zerop (arg1))
-           return omit_one_operand (type, build_real (type, dconst1), arg0);
-
          /* Optimize pow(1.0,y) = 1.0.  */
          if (real_onep (arg0))
            return omit_one_operand (type, build_real (type, dconst1), arg1);
+
+         if (TREE_CODE (arg1) == REAL_CST
+             && ! TREE_CONSTANT_OVERFLOW (arg1))
+           {
+             REAL_VALUE_TYPE c;
+             c = TREE_REAL_CST (arg1);
+
+             /* Optimize pow(x,0.0) = 1.0.  */
+             if (REAL_VALUES_EQUAL (c, dconst0))
+               return omit_one_operand (type, build_real (type, dconst1),
+                                        arg0);
+
+             /* Optimize pow(x,1.0) = x.  */
+             if (REAL_VALUES_EQUAL (c, dconst1))
+               return arg0;
+
+             /* Optimize pow(x,-1.0) = 1.0/x.  */
+             if (REAL_VALUES_EQUAL (c, dconstm1))
+               return fold (build (RDIV_EXPR, type,
+                                   build_real (type, dconst1),
+                                   arg0));
+
+             /* Optimize pow(x,2.0) = x*x.  */
+             if (REAL_VALUES_EQUAL (c, dconst2)
+                 && (*lang_hooks.decls.global_bindings_p) () == 0
+                 && ! contains_placeholder_p (arg0))
+               {
+                 arg0 = save_expr (arg0);
+                 return fold (build (MULT_EXPR, type, arg0, arg0));
+               }
+
+             /* Optimize pow(x,-2.0) = 1.0/(x*x).  */
+             if (flag_unsafe_math_optimizations
+                 && REAL_VALUES_EQUAL (c, dconstm2)
+                 && (*lang_hooks.decls.global_bindings_p) () == 0
+                 && ! contains_placeholder_p (arg0))
+               {
+                 arg0 = save_expr (arg0);
+                 return fold (build (RDIV_EXPR, type,
+                                     build_real (type, dconst1),
+                                     fold (build (MULT_EXPR, type,
+                                                  arg0, arg0))));
+               }
+
+             /* Optimize pow(x,0.5) = sqrt(x).  */
+             if (flag_unsafe_math_optimizations
+                 && REAL_VALUES_EQUAL (c, dconsthalf))
+               {
+                 tree sqrtfn;
+
+                 if (fcode == BUILT_IN_POW)
+                   sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
+                 else if (fcode == BUILT_IN_POWF)
+                   sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTF];
+                 else if (fcode == BUILT_IN_POWL)
+                   sqrtfn = implicit_built_in_decls[BUILT_IN_SQRTL];
+                 else
+                   sqrtfn = NULL_TREE;
+
+                 if (sqrtfn != NULL_TREE)
+                   {
+                     tree arglist = build_tree_list (NULL_TREE, arg0);
+                     return build_function_call_expr (sqrtfn, arglist);
+                   }
+               }
+           }
        }
       break;
 
index ad30637ee0a705a66d716a6429d28c243cfc3e1d..4aab67494d4104b22c10263a338aa5da75a8d663 100644 (file)
@@ -111,6 +111,8 @@ REAL_VALUE_TYPE dconst0;
 REAL_VALUE_TYPE dconst1;
 REAL_VALUE_TYPE dconst2;
 REAL_VALUE_TYPE dconstm1;
+REAL_VALUE_TYPE dconstm2;
+REAL_VALUE_TYPE dconsthalf;
 
 /* All references to the following fixed hard registers go through
    these unique rtl objects.  On machines where the frame-pointer and
@@ -5552,6 +5554,10 @@ init_emit_once (line_numbers)
   REAL_VALUE_FROM_INT (dconst1,   1,  0, double_mode);
   REAL_VALUE_FROM_INT (dconst2,   2,  0, double_mode);
   REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);
+  REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);
+
+  dconsthalf = dconst1;
+  dconsthalf.exp--;
 
   for (i = 0; i <= 2; i++)
     {
index f6074f99639242b9abf6ef49fb2fa2b71d4d8b40..04bf718a74343ce15284c506a85c9082888f79bf 100644 (file)
@@ -4423,7 +4423,6 @@ real_sqrt (r, mode, x)
      const REAL_VALUE_TYPE *x;
 {
   static REAL_VALUE_TYPE halfthree;
-  static REAL_VALUE_TYPE half;
   static bool init = false;
   REAL_VALUE_TYPE h, t, i;
   int iter, exp;
@@ -4452,8 +4451,7 @@ real_sqrt (r, mode, x)
 
   if (!init)
     {
-      real_arithmetic (&half, RDIV_EXPR, &dconst1, &dconst2);
-      real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &half);
+      real_arithmetic (&halfthree, PLUS_EXPR, &dconst1, &dconsthalf);
       init = true;
     }
 
@@ -4467,7 +4465,7 @@ real_sqrt (r, mode, x)
       /* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x).  */
       real_arithmetic (&t, MULT_EXPR, x, &i);
       real_arithmetic (&h, MULT_EXPR, &t, &i);
-      real_arithmetic (&t, MULT_EXPR, &h, &half);
+      real_arithmetic (&t, MULT_EXPR, &h, &dconsthalf);
       real_arithmetic (&h, MINUS_EXPR, &halfthree, &t);
       real_arithmetic (&t, MULT_EXPR, &i, &h);
 
@@ -4484,7 +4482,7 @@ real_sqrt (r, mode, x)
   real_arithmetic (&h, MULT_EXPR, &t, &i);
   real_arithmetic (&i, MINUS_EXPR, &dconst1, &h);
   real_arithmetic (&h, MULT_EXPR, &t, &i);
-  real_arithmetic (&i, MULT_EXPR, &half, &h);
+  real_arithmetic (&i, MULT_EXPR, &dconsthalf, &h);
   real_arithmetic (&h, PLUS_EXPR, &t, &i);
 
   /* ??? We need a Tuckerman test to get the last bit.  */
index d16231acae88ac35b81536ed0af389811d4cfff9..9507af2270d84ef742e8c9de224f9655053b0a76 100644 (file)
@@ -322,12 +322,14 @@ extern void real_ldexp            PARAMS ((REAL_VALUE_TYPE *,
 
 /* **** End of software floating point emulator interface macros **** */
 \f
-/* Constant real values 0, 1, 2, and -1.  */
+/* Constant real values 0, 1, 2, -1, -2 and 0.5.  */
 
 extern REAL_VALUE_TYPE dconst0;
 extern REAL_VALUE_TYPE dconst1;
 extern REAL_VALUE_TYPE dconst2;
 extern REAL_VALUE_TYPE dconstm1;
+extern REAL_VALUE_TYPE dconstm2;
+extern REAL_VALUE_TYPE dconsthalf;
 
 /* Function to return a real value (not a tree node)
    from a given integer constant.  */
index 2469ea4ed73e9cd3f6b123b6fb721f860877155a..fdc97e104e2af0ce8da520e6b735037f2e1afff5 100644 (file)
@@ -1,3 +1,9 @@
+2003-03-31  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/builtins-3.c: Add new tests for sin and cos.
+       * gcc.dg/builtins-7.c: New test case.
+       * gcc.dg/builtins-8.c: New test case.
+
 2003-03-31  Richard Sandiford  <rsandifo@redhat.com>
 
        * gcc.c-torture/execute/ieee/20030331-1.c: New test.
index 49bea5e126e90ee65f970ebf4f82b92a4efaab1c..3c2dbfd7f52fdce6eb743b68a1fd4b04114b1819 100644 (file)
@@ -1,7 +1,7 @@
-/* Copyright (C) 2002  Free Software Foundation.
+/* Copyright (C) 2002, 2003  Free Software Foundation.
 
    Verify that built-in math function constant folding of constant
-   arguments is correctly performed by the by the compiler.
+   arguments is correctly performed by the compiler.
 
    Written by Roger Sayle, 16th August 2002.  */
 
@@ -24,6 +24,12 @@ int main()
   if (log (1.0) != 0.0)
     link_error ();
 
+  if (sin (0.0) != 0.0)
+    link_error ();
+
+  if (cos (0.0) != 1.0)
+    link_error ();
+
 
   if (sqrtf (0.0f) != 0.0f)
     link_error ();
@@ -37,6 +43,12 @@ int main()
   if (logf (1.0f) != 0.0f)
     link_error ();
 
+  if (sinf (0.0f) != 0.0f)
+    link_error ();
+
+  if (cosf (0.0f) != 1.0f)
+    link_error ();
+
 
   if (sqrtl (0.0l) != 0.0l)
     link_error ();
@@ -50,6 +62,12 @@ int main()
   if (logl (1.0l) != 0.0l)
     link_error ();
 
+  if (sinl (0.0l) != 0.0l)
+    link_error ();
+
+  if (cosl (0.0l) != 1.0l)
+    link_error ();
+
   return 0;
 }
 
diff --git a/gcc/testsuite/gcc.dg/builtins-7.c b/gcc/testsuite/gcc.dg/builtins-7.c
new file mode 100644 (file)
index 0000000..84c0e15
--- /dev/null
@@ -0,0 +1,39 @@
+/* Copyright (C) 2003  Free Software Foundation.
+
+   Verify that built-in math function constant folding of constant
+   arguments is correctly performed by the by the compiler.
+
+   Written by Roger Sayle, 30th March 2003.  */
+
+/* { dg-do link } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern void link_error(void);
+
+void test(double x)
+{
+  if (pow (x, 1.0) != x)
+    link_error ();
+}
+
+void testf(float x)
+{
+  if (powf (x, 1.0f) != x)
+    link_error ();
+}
+
+void testl(long double x)
+{
+  if (powl (x, 1.0l) != x)
+    link_error ();
+}
+
+int main()
+{
+  test (2.0);
+  testf (2.0f);
+  testl (2.0l);
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/builtins-8.c b/gcc/testsuite/gcc.dg/builtins-8.c
new file mode 100644 (file)
index 0000000..99d1a70
--- /dev/null
@@ -0,0 +1,34 @@
+/* Copyright (C) 2003  Free Software Foundation.
+
+   Verify that built-in math function constant folding of functions
+   with one constant argument is correctly performed by the compiler.
+
+   Written by Roger Sayle, 30th March 2003.  */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern void abort(void);
+
+void test(double x)
+{
+  if (pow(x,-1.0) != 1.0/x)
+    abort ();
+
+  if (pow(x,2.0) != x*x)
+    abort ();
+
+  if (pow(x,-2.0) != 1.0/(x*x))
+    abort ();
+
+  if (pow(x,0.5) != sqrt(x))
+    abort ();
+}
+
+int main()
+{
+  test (1.0);
+  test (2.0);
+  return 0;
+}
+