aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-08-18 13:40:18 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-08-18 13:40:18 +0000
commit776e7174167360fdf2ba990e7c7c22536fe9227a (patch)
tree352c74ccff21f703c3493cc20f89542a38b26f32 /gcc
parentf3252b3c18e688f43df708d0003f0b6e0f89cc17 (diff)
downloadgcc-776e7174167360fdf2ba990e7c7c22536fe9227a.zip
gcc-776e7174167360fdf2ba990e7c7c22536fe9227a.tar.gz
gcc-776e7174167360fdf2ba990e7c7c22536fe9227a.tar.bz2
re PR middle-end/41094 (Erroneous optimization of pow() with -ffast-math)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/builtins.c11
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/builtins-10.c4
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-power-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr41094.c19
6 files changed, 44 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index adbf70f..764d4d1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 025c169..1a9e966 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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);
+ }
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e1c0885..464e14c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/builtins-10.c b/gcc/testsuite/gcc.dg/builtins-10.c
index d90e61a..1b141fd 100644
--- a/gcc/testsuite/gcc.dg/builtins-10.c
+++ b/gcc/testsuite/gcc.dg/builtins-10.c
@@ -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 ();
}
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-power-1.c b/gcc/testsuite/gcc.dg/torture/builtin-power-1.c
index a63ebf5..d1403c4 100644
--- a/gcc/testsuite/gcc.dg/torture/builtin-power-1.c
+++ b/gcc/testsuite/gcc.dg/torture/builtin-power-1.c
@@ -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
index 0000000..2a4e961
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr41094.c
@@ -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;
+}