]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
fold-const.c (fold <MULT_EXPR>): Optimize (C1/X)*C2 into (C1*C2)/X when unsafe math...
authorRoger Sayle <roger@eyesopen.com>
Tue, 26 Aug 2003 13:26:31 +0000 (13:26 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Tue, 26 Aug 2003 13:26:31 +0000 (13:26 +0000)
* fold-const.c (fold <MULT_EXPR>): Optimize (C1/X)*C2 into
(C1*C2)/X when unsafe math optimizations are allowed.
(fold <RDIV_EXPR>): Optimize C1/(X*C2) into (C1/C2)/X with unsafe
math optimizations.  Minor code clean-ups.  Recursively call
fold when constructing sub-expressions.

* gcc.dg/20030826-1.c: New test case.

From-SVN: r70807

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

index 6c195ba1f4ea0ecb004b49f9bae8ae6e22899dd1..1b7d9708fa6be2706fa27e674062283f6a441d6c 100644 (file)
@@ -1,3 +1,11 @@
+2003-08-26  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold <MULT_EXPR>): Optimize (C1/X)*C2 into
+       (C1*C2)/X when unsafe math optimizations are allowed.
+       (fold <RDIV_EXPR>): Optimize C1/(X*C2) into (C1/C2)/X with unsafe
+       math optimizations.  Minor code clean-ups.  Recursively call
+       fold when constructing sub-expressions.
+
 2003-08-26  Roger Sayle  <roger@eyesopen.com>
 
        * builtins.c (fold_builtin_bitop): New function to perform constant
index 27a4724cabe240f95122ae8614cb3987e814ca42..efa2db966373309896db2dcedaef9cfe7e7e2db8 100644 (file)
@@ -6060,6 +6060,19 @@ fold (tree expr)
              && real_minus_onep (arg1))
            return fold (build1 (NEGATE_EXPR, type, arg0));
 
+         /* Convert (C1/X)*C2 into (C1*C2)/X.  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg0) == RDIV_EXPR
+             && TREE_CODE (arg1) == REAL_CST
+             && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
+           {
+             tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
+                                     arg1, 0);
+             if (tem)
+               return fold (build (RDIV_EXPR, type, tem,
+                                   TREE_OPERAND (arg0, 1)));
+           }
+
          if (flag_unsafe_math_optimizations)
            {
              enum built_in_function fcode0 = builtin_mathfn_code (arg0);
@@ -6393,7 +6406,7 @@ fold (tree expr)
                                          arg1, 0)))
            return fold (build (MULT_EXPR, type, arg0, tem));
          /* Find the reciprocal if optimizing and the result is exact.  */
-         else if (optimize)
+         if (optimize)
            {
              REAL_VALUE_TYPE r;
              r = TREE_REAL_CST (arg1);
@@ -6407,19 +6420,29 @@ fold (tree expr)
       /* Convert A/B/C to A/(B*C).  */
       if (flag_unsafe_math_optimizations
          && TREE_CODE (arg0) == RDIV_EXPR)
-       {
-         return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
-                             build (MULT_EXPR, type, TREE_OPERAND (arg0, 1),
-                                    arg1)));
-       }
+       return fold (build (RDIV_EXPR, type, TREE_OPERAND (arg0, 0),
+                           fold (build (MULT_EXPR, type,
+                                        TREE_OPERAND (arg0, 1), arg1))));
+
       /* Convert A/(B/C) to (A/B)*C.  */
       if (flag_unsafe_math_optimizations
          && TREE_CODE (arg1) == RDIV_EXPR)
+       return fold (build (MULT_EXPR, type,
+                           fold (build (RDIV_EXPR, type, arg0,
+                                        TREE_OPERAND (arg1, 0))),
+                           TREE_OPERAND (arg1, 1)));
+
+      /* Convert C1/(X*C2) into (C1/C2)/X.  */
+      if (flag_unsafe_math_optimizations
+         && TREE_CODE (arg1) == MULT_EXPR
+         && TREE_CODE (arg0) == REAL_CST
+         && TREE_CODE (TREE_OPERAND (arg1, 1)) == REAL_CST)
        {
-         return fold (build (MULT_EXPR, type,
-                             build (RDIV_EXPR, type, arg0,
-                                    TREE_OPERAND (arg1, 0)),
-                             TREE_OPERAND (arg1, 1)));
+         tree tem = const_binop (RDIV_EXPR, arg0,
+                                 TREE_OPERAND (arg1, 1), 0);
+         if (tem)
+           return fold (build (RDIV_EXPR, type, tem,
+                               TREE_OPERAND (arg1, 0)));
        }
 
       if (flag_unsafe_math_optimizations)
index 1543516bedf289ca53617b1bfd7723973fba63d3..ba803a16550bf1f0b9301470e0dde2f5b2ad47b7 100644 (file)
@@ -1,3 +1,7 @@
+2003-08-26  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/20030826-1.c: New test case.
+
 2003-08-26  Matt Kraai  <kraai@alumni.cmu.edu>
 
        * gcc.dg/noncompile/20030818-1.c: Expect second line of error.
diff --git a/gcc/testsuite/gcc.dg/20030826-1.c b/gcc/testsuite/gcc.dg/20030826-1.c
new file mode 100644 (file)
index 0000000..b344ad2
--- /dev/null
@@ -0,0 +1,33 @@
+/* Copyright (C) 2003 Free Software Foundation.
+
+   Check that constant folding of mathematical expressions doesn't
+   break anything.
+
+   Written by Roger Sayle, 24th August 2003.  */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math" } */
+
+void abort(void);
+
+double foo(double x)
+{
+  return 12.0/(x*3.0);
+}
+
+double bar(double x)
+{
+  return (3.0/x)*4.0;
+}
+
+int main()
+{
+  if (foo(2.0) != 2.0)
+    abort ();
+
+  if (bar(2.0) != 6.0)
+    abort ();
+
+  return 0;
+}
+