diff options
author | Richard Guenther <rguenther@suse.de> | 2009-08-18 13:40:18 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2009-08-18 13:40:18 +0000 |
commit | 776e7174167360fdf2ba990e7c7c22536fe9227a (patch) | |
tree | 352c74ccff21f703c3493cc20f89542a38b26f32 /gcc | |
parent | f3252b3c18e688f43df708d0003f0b6e0f89cc17 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/builtins.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/builtins-10.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/builtin-power-1.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr41094.c | 19 |
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; +} |