]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/41094 (Erroneous optimization of pow() with -ffast-math)
authorRichard Guenther <rguenther@suse.de>
Mon, 24 Aug 2009 09:56:30 +0000 (09:56 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 24 Aug 2009 09:56:30 +0000 (09:56 +0000)
2009-08-24  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: r151052

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 ee1b3f6a5923322d1dcaed935a78bdabddc67104..9ececb23744e377243058ccf7b034e971c0ceade 100644 (file)
@@ -1,3 +1,9 @@
+2009-08-24  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-23  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/40718
index 82bc24f84ba3f002d8e2c8586a196a90866c6928..1185b429d81e0f6c47485ad027efeeb3f22c2ceb 100644 (file)
@@ -8459,15 +8459,18 @@ fold_builtin_pow (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 (MULT_EXPR, type, arg01, arg1);
-         return build_call_expr (fndecl, 2, arg00, narg1);
+         if (tree_expr_nonnegative_p (arg00))
+           {
+             tree arg01 = CALL_EXPR_ARG (arg0, 1);
+             tree narg1 = fold_build2 (MULT_EXPR, type, arg01, arg1);
+             return build_call_expr (fndecl, 2, arg00, narg1);
+           }
        }
     }
 
index c9b42c586580495b713ec95590fc647d8c13678a..cc883d55e9ee7b1a10a5540cbd48368ee4da1d5a 100644 (file)
@@ -1,3 +1,10 @@
+2009-08-24  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-23  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/40851
index d90e61ab32633db67e2ed02c6c7b496ab4fa4006..1b141fda25200a94c9be8833b531729d53506c5e 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 a63ebf554238c8a56fda1093e8ad8ae2e27bd58e..d1403c46c942358a82dfb4014cdf95cf2868e038 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;
+}