OSDN Git Service

* builtins.c (fold_builtin): Constant fold expressions as x*0.5
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 Apr 2003 23:24:38 +0000 (23:24 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 8 Apr 2003 23:24:38 +0000 (23:24 +0000)
instead of x/2.0.  Optimize sqrt(pow(x,y)) as pow(x,y*0.5),
log(pow(x,y)) as y*log(x), pow(exp(x),y) as exp(x*y),
pow(sqrt(x),y) as pow(x,y*0.5) and pow(pow(x,y),z) as pow(x,y*z).
Delete function scope "fcode" variable to avoid shadowing.

* gcc.dg/builtins-9.c: New test case.
* gcc.dg/builtins-10.c: New test case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@65386 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtins-9.c [new file with mode: 0644]

index dfd7630..2013469 100644 (file)
@@ -1,3 +1,11 @@
+2003-04-08  Roger Sayle  <roger@eyesopen.com>
+
+       * builtins.c (fold_builtin):  Constant fold expressions as x*0.5
+       instead of x/2.0.  Optimize sqrt(pow(x,y)) as pow(x,y*0.5),
+       log(pow(x,y)) as y*log(x), pow(exp(x),y) as exp(x*y),
+       pow(sqrt(x),y) as pow(x,y*0.5) and pow(pow(x,y),z) as pow(x,y*z).
+       Delete function scope "fcode" variable to avoid shadowing.
+
 2003-04-08  Kevin Buettner  <kevinb@redhat.com>
 
        * dwarf2out.c (DWARF_ARANGES_HEADER_SIZE, DWARF_ARANGES_PAD_SIZE):
index d446185..ee2d579 100644 (file)
@@ -4686,12 +4686,11 @@ fold_builtin (exp)
   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
   tree arglist = TREE_OPERAND (exp, 1);
   tree type = TREE_TYPE (TREE_TYPE (fndecl));
-  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
 
   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
     return 0;
 
-  switch (fcode)
+  switch (DECL_FUNCTION_CODE (fndecl))
     {
     case BUILT_IN_CONSTANT_P:
       return fold_builtin_constant_p (arglist);
@@ -4735,7 +4734,7 @@ fold_builtin (exp)
                return build_real (type, r);
            }
 
-         /* Optimize sqrt(exp(x)) = exp(x/2.0).  */
+         /* Optimize sqrt(exp(x)) = exp(x*0.5).  */
          fcode = builtin_mathfn_code (arg);
          if (flag_unsafe_math_optimizations
              && (fcode == BUILT_IN_EXP
@@ -4743,12 +4742,28 @@ fold_builtin (exp)
                  || fcode == BUILT_IN_EXPL))
            {
              tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
-             arg = fold (build (RDIV_EXPR, type,
+             arg = fold (build (MULT_EXPR, type,
                                 TREE_VALUE (TREE_OPERAND (arg, 1)),
-                                build_real (type, dconst2)));
+                                build_real (type, dconsthalf)));
              arglist = build_tree_list (NULL_TREE, arg);
              return build_function_call_expr (expfn, arglist);
            }
+
+         /* Optimize sqrt(pow(x,y)) = pow(x,y*0.5).  */
+         if (flag_unsafe_math_optimizations
+             && (fcode == BUILT_IN_POW
+                 || fcode == BUILT_IN_POWF
+                 || fcode == BUILT_IN_POWL))
+           {
+             tree powfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
+             tree arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
+             tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
+             tree narg1 = fold (build (MULT_EXPR, type, arg1,
+                                       build_real (type, dconsthalf)));
+             arglist = tree_cons (NULL_TREE, arg0,
+                                  build_tree_list (NULL_TREE, narg1));
+             return build_function_call_expr (powfn, arglist);
+           }
        }
       break;
 
@@ -4820,7 +4835,7 @@ fold_builtin (exp)
                  || fcode == BUILT_IN_EXPL))
            return TREE_VALUE (TREE_OPERAND (arg, 1));
 
-         /* Optimize log(sqrt(x)) = log(x)/2.0.  */
+         /* Optimize log(sqrt(x)) = log(x)*0.5.  */
          if (flag_unsafe_math_optimizations
              && (fcode == BUILT_IN_SQRT
                  || fcode == BUILT_IN_SQRTF
@@ -4828,8 +4843,23 @@ fold_builtin (exp)
            {
              tree logfn = build_function_call_expr (fndecl,
                                                     TREE_OPERAND (arg, 1));
-             return fold (build (RDIV_EXPR, type, logfn,
-                                 build_real (type, dconst2)));
+             return fold (build (MULT_EXPR, type, logfn,
+                                 build_real (type, dconsthalf)));
+           }
+
+         /* Optimize log(pow(x,y)) = y*log(x).  */
+          if (flag_unsafe_math_optimizations
+             && (fcode == BUILT_IN_POW
+                 || fcode == BUILT_IN_POWF
+                 || fcode == BUILT_IN_POWL))
+           {
+             tree arg0, arg1, logfn;
+
+             arg0 = TREE_VALUE (TREE_OPERAND (arg, 1));
+             arg1 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg, 1)));
+             arglist = build_tree_list (NULL_TREE, arg0);
+             logfn = build_function_call_expr (fndecl, arglist);
+             return fold (build (MULT_EXPR, type, arg1, logfn));
            }
        }
       break;
@@ -4839,6 +4869,7 @@ fold_builtin (exp)
     case BUILT_IN_POWL:
       if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
        {
+         enum built_in_function fcode;
          tree arg0 = TREE_VALUE (arglist);
          tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
 
@@ -4895,6 +4926,7 @@ fold_builtin (exp)
                {
                  tree sqrtfn;
 
+                 fcode = DECL_FUNCTION_CODE (fndecl);
                  if (fcode == BUILT_IN_POW)
                    sqrtfn = implicit_built_in_decls[BUILT_IN_SQRT];
                  else if (fcode == BUILT_IN_POWF)
@@ -4911,6 +4943,49 @@ fold_builtin (exp)
                    }
                }
            }
+
+         /* Optimize pow(exp(x),y) = exp(x*y).  */
+         fcode = builtin_mathfn_code (arg0);
+         if (flag_unsafe_math_optimizations
+             && (fcode == BUILT_IN_EXP
+                 || fcode == BUILT_IN_EXPF
+                 || fcode == BUILT_IN_EXPL))
+           {
+             tree expfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+             tree arg = TREE_VALUE (TREE_OPERAND (arg0, 1));
+             arg = fold (build (MULT_EXPR, type, arg, arg1));
+             arglist = build_tree_list (NULL_TREE, arg);
+             return build_function_call_expr (expfn, arglist);
+           }
+
+         /* Optimize pow(sqrt(x),y) = pow(x,y*0.5).  */
+         if (flag_unsafe_math_optimizations
+             && (fcode == BUILT_IN_SQRT
+                 || fcode == BUILT_IN_SQRTF
+                 || fcode == BUILT_IN_SQRTL))
+           {
+             tree narg0 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+             tree narg1 = fold (build (MULT_EXPR, type, arg1,
+                                       build_real (type, dconsthalf)));
+
+             arglist = tree_cons (NULL_TREE, narg0,
+                                  build_tree_list (NULL_TREE, narg1));
+             return build_function_call_expr (fndecl, arglist);
+           }
+
+         /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
+         if (flag_unsafe_math_optimizations
+             && (fcode == BUILT_IN_POW
+                 || fcode == BUILT_IN_POWF
+                 || fcode == BUILT_IN_POWL))
+           {
+             tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+             tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0, 1)));
+             tree narg1 = fold (build (MULT_EXPR, type, arg01, arg1));
+             arglist = tree_cons (NULL_TREE, arg00,
+                                  build_tree_list (NULL_TREE, narg1));
+             return build_function_call_expr (fndecl, arglist);
+           }
        }
       break;
 
index 256bfc5..09890c7 100644 (file)
@@ -1,3 +1,8 @@
+2003-04-08  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/builtins-9.c: New test case.
+       * gcc.dg/builtins-10.c: New test case.
+
 2003-04-07  J"orn Rennecke <joern.rennecke@superh.com>
 
        * gcc.dg/noncompile/init-4.c.c: New test.
diff --git a/gcc/testsuite/gcc.dg/builtins-10.c b/gcc/testsuite/gcc.dg/builtins-10.c
new file mode 100644 (file)
index 0000000..9e5a458
--- /dev/null
@@ -0,0 +1,54 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+   Check that constant folding of built-in math functions doesn't
+   break anything and produces the expected results.
+
+   Written by Roger Sayle, 2nd April 2003.  */
+
+/* { dg-do link } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern void link_error(void);
+
+extern double exp(double);
+extern double log(double);
+extern double sqrt(double);
+extern double pow(double,double);
+
+void test(double x)
+{
+  if (sqrt(pow(x,4.0)) != x*x)
+    link_error ();
+
+  if (pow(sqrt(x),4.0) != x*x)
+    link_error ();
+
+  if (pow(pow(x,4.0),0.25) != x)
+    link_error ();
+}
+
+void test2(double x, double y, double z)
+{
+  if (sqrt(pow(x,y)) != pow(x,y*0.5))
+    link_error ();
+
+  if (log(pow(x,y)) != y*log(x))
+    link_error ();
+
+  if (pow(exp(x),y) != exp(x*y))
+    link_error ();
+
+  if (pow(sqrt(x),y) != pow(x,y*0.5))
+    link_error ();
+
+  if (pow(pow(x,y),z) != pow(x,y*z))
+    link_error ();
+}
+
+int main()
+{
+  test (2.0);
+  test2 (2.0, 3.0, 4.0);
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/builtins-9.c b/gcc/testsuite/gcc.dg/builtins-9.c
new file mode 100644 (file)
index 0000000..108e0d2
--- /dev/null
@@ -0,0 +1,103 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+   Check that constant folding of built-in math functions doesn't
+   break anything.
+
+   Written by Roger Sayle, 2nd April 2003.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern double log(double);
+extern double exp(double);
+extern double sqrt(double);
+extern double pow(double,double);
+
+extern float logf(float);
+extern float expf(float);
+extern float sqrtf(float);
+extern float powf(float,float);
+
+extern long double logl(long double);
+extern long double expl(long double);
+extern long double sqrtl(long double);
+extern long double powl(long double,long double);
+
+
+double test1(double x, double y)
+{
+  return log(pow(x,y));
+}
+
+double test2(double x, double y)
+{
+  return sqrt(pow(x,y));
+}
+
+double test3(double x, double y)
+{
+  return pow(exp(x),y);
+}
+
+double test4(double x, double y)
+{
+  return pow(sqrt(x),y);
+}
+
+double test5(double x, double y, double z)
+{
+  return pow(pow(x,y),z);
+}
+
+
+float test1f(float x, float y)
+{
+  return logf(powf(x,y));
+}
+
+float test2f(float x, float y)
+{
+  return sqrtf(powf(x,y));
+}
+
+float test3f(float x, float y)
+{
+  return powf(expf(x),y);
+}
+
+float test4f(float x, float y)
+{
+  return powf(sqrtf(x),y);
+}
+
+float test5f(float x, float y, float z)
+{
+  return powf(powf(x,y),z);
+}
+
+
+long double test1l(long double x, long double y)
+{
+  return logl(powl(x,y));
+}
+
+long double test2l(long double x, long double y)
+{
+  return sqrtl(powl(x,y));
+}
+
+long double test3l(long double x, long double y)
+{
+  return powl(expl(x),y);
+}
+
+long double test4l(long double x, long double y)
+{
+  return powl(sqrtl(x),y);
+}
+
+long double test5l(long double x, long double y, long double z)
+{
+  return powl(powl(x,y),z);
+}
+