re PR middle-end/41094 (Erroneous optimization of pow() with -ffast-math)
authorRichard Guenther <rguenther@suse.de>
Tue, 18 Aug 2009 13:40:18 +0000 (13:40 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 18 Aug 2009 13:40:18 +0000 (13:40 +0000)
2009-08-18  Richard Guenther  <rguenther@suse.de>

PR middle-end/41094
* builtins.c (fold_builtin_pow): Fold pow(pow(x,y),z) to
pow(x,y*z) only if x is nonnegative.

* gcc.dg/torture/pr41094.c: New testcase.
* gcc.dg/torture/builtin-power-1.c: Adjust.
* gcc.dg/builtins-10.c: Likewise.

From-SVN: r150874

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/builtins-10.c
gcc/testsuite/gcc.dg/torture/builtin-power-1.c
gcc/testsuite/gcc.dg/torture/pr41094.c [new file with mode: 0644]

index adbf70f..764d4d1 100644 (file)
@@ -1,3 +1,9 @@
+2009-08-18  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/41094
+       * builtins.c (fold_builtin_pow): Fold pow(pow(x,y),z) to
+       pow(x,y*z) only if x is nonnegative.
+
 2009-08-18  Jakub Jelinek  <jakub@redhat.com>
 
        * bb-reorder.c (fix_up_fall_thru_edges): Only call invert_jump
index 025c169..1a9e966 100644 (file)
@@ -8737,15 +8737,18 @@ fold_builtin_pow (location_t loc, tree fndecl, tree arg0, tree arg1, tree type)
            }
        }
 
-      /* Optimize pow(pow(x,y),z) = pow(x,y*z).  */
+      /* Optimize pow(pow(x,y),z) = pow(x,y*z) iff x is nonnegative.  */
       if (fcode == BUILT_IN_POW
          || fcode == BUILT_IN_POWF
          || fcode == BUILT_IN_POWL)
        {
          tree arg00 = CALL_EXPR_ARG (arg0, 0);
-         tree arg01 = CALL_EXPR_ARG (arg0, 1);
-         tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
-         return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
+         if (tree_expr_nonnegative_p (arg00))
+           {
+             tree arg01 = CALL_EXPR_ARG (arg0, 1);
+             tree narg1 = fold_build2_loc (loc, MULT_EXPR, type, arg01, arg1);
+             return build_call_expr_loc (loc, fndecl, 2, arg00, narg1);
+           }
        }
     }
 
index e1c0885..464e14c 100644 (file)
@@ -1,3 +1,10 @@
+2009-08-18  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/41094
+       * gcc.dg/torture/pr41094.c: New testcase.
+       * gcc.dg/torture/builtin-power-1.c: Adjust.
+       * gcc.dg/builtins-10.c: Likewise.
+
 2009-08-18  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/40971
index d90e61a..1b141fd 100644 (file)
@@ -25,7 +25,7 @@ void test(double x)
     link_error ();
 
   if (pow(pow(x,4.0),0.25) != x)
-    link_error ();
+    /* XFAIL.  PR41098.  */;
 }
 
 void test2(double x, double y, double z)
@@ -42,7 +42,7 @@ void test2(double x, double y, double z)
   if (pow(sqrt(x),y) != pow(x,y*0.5))
     link_error ();
 
-  if (pow(pow(x,y),z) != pow(x,y*z))
+  if (pow(pow(fabs(x),y),z) != pow(fabs(x),y*z))
     link_error ();
 }
 
index a63ebf5..d1403c4 100644 (file)
@@ -77,9 +77,9 @@ void test(double d1, double d2, double d3,
   /* Test pow(pow(x,y),z) -> pow(x,y*z).  */
 #define POW_POW \
  extern void link_failure_pow_pow(void); \
- if (pow(pow(d1, d2), d3) != pow(d1,d2*d3) \
-     || powf(powf(f1,f2),f3) != powf(f1,f2*f3) \
-     || powl(powl(ld1,ld2),ld3) != powl(ld1,ld2*ld3)) \
+ if (pow(pow(fabs(d1), d2), d3) != pow(fabs(d1),d2*d3) \
+     || powf(powf(fabs(f1),f2),f3) != powf(fabs(f1),f2*f3) \
+     || powl(powl(fabs(ld1),ld2),ld3) != powl(fabs(ld1),ld2*ld3)) \
     link_failure_pow_pow()
 
   POW_POW;
diff --git a/gcc/testsuite/gcc.dg/torture/pr41094.c b/gcc/testsuite/gcc.dg/torture/pr41094.c
new file mode 100644 (file)
index 0000000..2a4e961
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-ffast-math" } */
+
+#include <math.h>
+
+extern void abort (void);
+
+double foo(void)
+{
+  double x = -4.0;
+  return pow (x * x, 0.25);
+}
+
+int main()
+{
+  if (foo() != 2.0)
+    abort ();
+  return 0;
+}