OSDN Git Service

* fold-const.c (fold <MULT_EXPR>): Optimize (C1/X)*C2 into
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Aug 2003 13:26:31 +0000 (13:26 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 26 Aug 2003 13:26:31 +0000 (13:26 +0000)
(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.

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

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

index 6c195ba..1b7d970 100644 (file)
@@ -1,5 +1,13 @@
 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
        folding of ffs, clz, ctz, popcount and parity builtin functions
        and their long and long long variants (such as ffsl and ffsll).
index 27a4724..efa2db9 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 1543516..ba803a1 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;
+}
+