fold-const.c (fold): Use "fold" following build in more places.
authorRoger Sayle <roger@eyesopen.com>
Tue, 8 Apr 2003 23:28:28 +0000 (23:28 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Tue, 8 Apr 2003 23:28:28 +0000 (23:28 +0000)
* fold-const.c (fold):  Use "fold" following build in more places.
Optimize sqrt(x)*sqrt(x) as x, pow(x,y)*pow(z,y) as pow(x*z,y),
pow(x,y)*pow(x,z) as pow(x,y+z) and x/pow(y,z) as x*pow(y,-z).

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

From-SVN: r65387

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-11.c [new file with mode: 0644]

index 20134695c3bc54f80c92d925e7baed571b4af0b0..58700fba6503c072aaf26c6cdda681991930b423 100644 (file)
@@ -1,3 +1,9 @@
+2003-04-08  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold):  Use "fold" following build in more places.
+       Optimize sqrt(x)*sqrt(x) as x, pow(x,y)*pow(z,y) as pow(x*z,y),
+       pow(x,y)*pow(x,z) as pow(x,y+z) and x/pow(y,z) as x*pow(y,-z).
+
 2003-04-08  Roger Sayle  <roger@eyesopen.com>
 
        * builtins.c (fold_builtin):  Constant fold expressions as x*0.5
index 6e17e00340ed1a473d86c6ec6e30c04bbe4111da..ebb87e27a5ea5533a08dec77770c8a222b65b8a4 100644 (file)
@@ -5849,7 +5849,7 @@ fold (expr)
              && ! contains_placeholder_p (arg0))
            {
              tree arg = save_expr (arg0);
-             return build (PLUS_EXPR, type, arg, arg);
+             return fold (build (PLUS_EXPR, type, arg, arg));
            }
 
          if (flag_unsafe_math_optimizations)
@@ -5857,17 +5857,25 @@ fold (expr)
              enum built_in_function fcode0 = builtin_mathfn_code (arg0);
              enum built_in_function fcode1 = builtin_mathfn_code (arg1);
 
-             /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y).  */
+             /* Optimizations of sqrt(...)*sqrt(...).  */
              if ((fcode0 == BUILT_IN_SQRT && fcode1 == BUILT_IN_SQRT)
                  || (fcode0 == BUILT_IN_SQRTF && fcode1 == BUILT_IN_SQRTF)
                  || (fcode0 == BUILT_IN_SQRTL && fcode1 == BUILT_IN_SQRTL))
                {
-                 tree sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
-                 tree arg = build (MULT_EXPR, type,
-                                   TREE_VALUE (TREE_OPERAND (arg0, 1)),
-                                   TREE_VALUE (TREE_OPERAND (arg1, 1)));
-                 tree arglist = build_tree_list (NULL_TREE, arg);
-                 return fold (build_function_call_expr (sqrtfn, arglist));
+                 tree sqrtfn, arg, arglist;
+                 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+                 tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+
+                 /* Optimize sqrt(x)*sqrt(x) as x.  */
+                 if (operand_equal_p (arg00, arg10, 0)
+                     && ! HONOR_SNANS (TYPE_MODE (type)))
+                   return arg00;
+
+                 /* Optimize sqrt(x)*sqrt(y) as sqrt(x*y).  */
+                 sqrtfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                 arg = fold (build (MULT_EXPR, type, arg00, arg10));
+                 arglist = build_tree_list (NULL_TREE, arg);
+                 return build_function_call_expr (sqrtfn, arglist);
                }
 
              /* Optimize exp(x)*exp(y) as exp(x+y).  */
@@ -5879,8 +5887,43 @@ fold (expr)
                  tree arg = build (PLUS_EXPR, type,
                                    TREE_VALUE (TREE_OPERAND (arg0, 1)),
                                    TREE_VALUE (TREE_OPERAND (arg1, 1)));
-                 tree arglist = build_tree_list (NULL_TREE, arg);
-                 return fold (build_function_call_expr (expfn, arglist));
+                 tree arglist = build_tree_list (NULL_TREE, fold (arg));
+                 return build_function_call_expr (expfn, arglist);
+               }
+
+             /* Optimizations of pow(...)*pow(...).  */
+             if ((fcode0 == BUILT_IN_POW && fcode1 == BUILT_IN_POW)
+                 || (fcode0 == BUILT_IN_POWF && fcode1 == BUILT_IN_POWF)
+                 || (fcode0 == BUILT_IN_POWL && fcode1 == BUILT_IN_POWL))
+               {
+                 tree arg00 = TREE_VALUE (TREE_OPERAND (arg0, 1));
+                 tree arg01 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg0,
+                                                                    1)));
+                 tree arg10 = TREE_VALUE (TREE_OPERAND (arg1, 1));
+                 tree arg11 = TREE_VALUE (TREE_CHAIN (TREE_OPERAND (arg1,
+                                                                    1)));
+
+                 /* Optimize pow(x,y)*pow(z,y) as pow(x*z,y).  */
+                 if (operand_equal_p (arg01, arg11, 0))
+                   {
+                     tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                     tree arg = build (MULT_EXPR, type, arg00, arg10);
+                     tree arglist = tree_cons (NULL_TREE, fold (arg),
+                                               build_tree_list (NULL_TREE,
+                                                                arg01));
+                     return build_function_call_expr (powfn, arglist);
+                   }
+
+                 /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z).  */
+                 if (operand_equal_p (arg00, arg10, 0))
+                   {
+                     tree powfn = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+                     tree arg = fold (build (PLUS_EXPR, type, arg01, arg11));
+                     tree arglist = tree_cons (NULL_TREE, arg00,
+                                               build_tree_list (NULL_TREE,
+                                                                arg));
+                     return build_function_call_expr (powfn, arglist);
+                   }
                }
            }
        }
@@ -6052,10 +6095,10 @@ fold (expr)
                              TREE_OPERAND (arg1, 1)));
        }
 
-      /* Optimize x/exp(y) into x*exp(-y).  */
       if (flag_unsafe_math_optimizations)
        {
          enum built_in_function fcode = builtin_mathfn_code (arg1);
+         /* Optimize x/exp(y) into x*exp(-y).  */
          if (fcode == BUILT_IN_EXP
              || fcode == BUILT_IN_EXPF
              || fcode == BUILT_IN_EXPL)
@@ -6063,10 +6106,25 @@ fold (expr)
              tree expfn = TREE_OPERAND (TREE_OPERAND (arg1, 0), 0);
              tree arg = build1 (NEGATE_EXPR, type,
                                 TREE_VALUE (TREE_OPERAND (arg1, 1)));
-             tree arglist = build_tree_list (NULL_TREE, arg);
+             tree arglist = build_tree_list (NULL_TREE, fold (arg));
              arg1 = build_function_call_expr (expfn, arglist);
              return fold (build (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 (build1 (NEGATE_EXPR, type, arg11));
+             tree arglist = tree_cons(NULL_TREE, arg10,
+                                      build_tree_list (NULL_TREE, neg11));
+             arg1 = build_function_call_expr (powfn, arglist);
+             return fold (build (MULT_EXPR, type, arg0, arg1));
+           }
        }
       goto binary;
 
index 09890c71bead42157d4c4134d3c4a3a5d6d1ebaf..857d1e54638df0c9c336297f15caa01a32ec7ef1 100644 (file)
@@ -1,3 +1,7 @@
+2003-04-08  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/builtins-11.c: New test case.
+
 2003-04-08  Roger Sayle  <roger@eyesopen.com>
 
        * gcc.dg/builtins-9.c: New test case.
diff --git a/gcc/testsuite/gcc.dg/builtins-11.c b/gcc/testsuite/gcc.dg/builtins-11.c
new file mode 100644 (file)
index 0000000..a2ff257
--- /dev/null
@@ -0,0 +1,46 @@
+/* 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, 5th April 2003.  */
+
+/* { dg-do link } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern void link_error(void);
+
+extern double exp(double);
+extern double sqrt(double);
+extern double pow(double,double);
+
+void test(double x, double y, double z)
+{
+  if (sqrt(x)*sqrt(x) != x)
+    link_error ();
+
+  if (sqrt(x)*sqrt(y) != sqrt(x*y))
+    link_error ();
+
+  if (exp(x)*exp(y) != exp(x+y))
+    link_error ();
+
+  if (pow(x,y)*pow(z,y) != pow(z*x,y))
+    link_error ();
+
+  if (pow(x,y)*pow(x,z) != pow(x,y+z))
+    link_error ();
+
+  if (x/exp(y) != x*exp(-y))
+    link_error ();
+
+  if (x/pow(y,z) != x*pow(y,-z))
+    link_error ();
+}
+
+int main()
+{
+  test (2.0, 3.0, 4.0);
+  return 0;
+}
+