Bug 43419

Summary: gcc replaces pow(x, 0.5) by sqrt(x), invalid when x is -0
Product: gcc Reporter: Vincent Lefèvre <vincent-gcc>
Component: middle-endAssignee: Michael Matz <matz>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs
Priority: P3 Keywords: wrong-code
Version: 4.5.0   
Target Milestone: 4.5.0   
Host: Target:
Build: Known to work: 4.4.4 4.5.0
Known to fail: 4.3.4 Last reconfirmed: 2010-03-18 14:35:38

Description Vincent Lefèvre 2010-03-18 14:08:34 UTC
gcc replaces pow(x, 0.5) by sqrt(x). This is invalid when x is -0. Indeed, according to ISO C99 (N1256), F.9.4.4:

  pow(±0, y) returns +0 for y > 0 and not an odd integer.

So, pow(-0.0, 0.5) should return +0. But sqrt(-0.0) should return -0 according to the IEEE 754 standard (and F.9.4.5 from ISO C99).

Testcase:

#include <stdio.h>
#include <math.h>

int main (void)
{
  volatile double x = -0.0;

  printf ("sqrt(-0)    = %g\n", sqrt (x));
  printf ("pow(-0,0.5) = %g\n", pow (x, 0.5));
  return 0;
}
Comment 1 Vincent Lefèvre 2010-03-18 14:33:11 UTC
If I understand correctly, the bug appears with:

r119248 | rguenth | 2006-11-27 12:38:42 +0100 (Mon, 27 Nov 2006) | 10 lines

2006-11-27  Richard Guenther  <rguenther@suse.de>

        PR middle-end/25620
        * builtins.c (expand_builtin_pow): Optimize non integer valued
        constant exponents using sqrt or cbrt if possible.  Always fall back
        to expanding via optabs.

        * gcc.target/i386/pow-1.c: New testcase.
        * gcc.dg/builtins-58.c: Likewise.
Comment 2 Michael Matz 2010-03-18 14:35:38 UTC
Mine.
Comment 3 Dominique d'Humieres 2010-03-18 14:41:45 UTC
While you are looking at this part, you may have to check that a similar problem does not exist when converting x*sqrt(x) to pow(w,1.5) and so on.
Comment 4 Michael Matz 2010-03-18 14:48:54 UTC
I checked, and these and similar transformations are always guarded by
flag_unsafe_math_optimizations, so we should be fine, unless I missed a case
of course.  If you notice one, please create a bug report.
Comment 5 Richard Biener 2010-03-18 15:31:44 UTC
Looks like we need to guard this with HONOR_SIGNED_ZEROS.
Comment 6 Michael Matz 2010-03-18 16:08:16 UTC
Subject: Bug 43419

Author: matz
Date: Thu Mar 18 16:07:53 2010
New Revision: 157543

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=157543
Log:
	PR middle-end/43419
	* builtins.c (expand_builtin_pow): Don't transform pow(x, 0.5)
	into sqrt(x) if we need to preserve signed zeros.

testsuite/
	* gcc.dg/pr43419.c: New testcase.

Added:
    trunk/gcc/testsuite/gcc.dg/pr43419.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/builtins.c
    trunk/gcc/testsuite/ChangeLog

Comment 7 Michael Matz 2010-03-18 16:47:50 UTC
Fixed.
Comment 8 Jakub Jelinek 2010-03-22 14:58:26 UTC
Subject: Bug 43419

Author: jakub
Date: Mon Mar 22 14:58:00 2010
New Revision: 157631

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=157631
Log:
	Backport from mainline:
	2010-03-18  Michael Matz  <matz@suse.de>

	PR middle-end/43419
	* builtins.c (expand_builtin_pow): Don't transform pow(x, 0.5)
	into sqrt(x) if we need to preserve signed zeros.

	* gcc.dg/pr43419.c: New testcase.

Added:
    branches/gcc-4_4-branch/gcc/testsuite/gcc.dg/pr43419.c
Modified:
    branches/gcc-4_4-branch/gcc/ChangeLog
    branches/gcc-4_4-branch/gcc/builtins.c
    branches/gcc-4_4-branch/gcc/testsuite/ChangeLog

Comment 9 Mikael Pettersson 2010-03-22 16:02:25 UTC
This bug also affects 4.3 branch. The upstream patch applies Ok and fixes it.
Comment 10 Jackie Rosen 2014-02-16 13:17:23 UTC Comment hidden (spam)