Fix PR43419: pow->sqrt not honoring signed zeros
Richard Guenther
richard.guenther@gmail.com
Thu Mar 18 16:42:00 GMT 2010
On Thu, Mar 18, 2010 at 3:51 PM, Michael Matz <matz@suse.de> wrote:
> Hello,
>
> On Thu, 18 Mar 2010, Michael Matz wrote:
>
>> > According to 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).
>>
>> But unfortunately you are right, this expansion can only be done for
>> -fno-signed-zeros.
>
> Like so.
>
> Regstrapping on x86_64-linux in progress, it's not a regression from 4.4
> but fairly low risk, so okay for trunk if that passes?
Ok.
Thanks,
Richard.
>
> Ciao,
> Michael.
> --
> 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.
>
> Index: builtins.c
> ===================================================================
> --- builtins.c (revision 157518)
> +++ builtins.c (working copy)
> @@ -2980,7 +2980,10 @@ expand_builtin_pow (tree exp, rtx target
> && ((flag_unsafe_math_optimizations
> && optimize_insn_for_speed_p ()
> && powi_cost (n/2) <= POWI_MAX_MULTS)
> - || n == 1))
> + /* Even the c==0.5 case can not be done unconditionally
> + when we need to preserve signed zeros, as
> + pow (-0, 0.5) is +0, while sqrt(-0) is -0. */
> + || (!HONOR_SIGNED_ZEROS (mode) && n == 1)))
> {
> tree call_expr = build_call_nofold (fn, 1, narg0);
> /* Use expand_expr in case the newly built call expression
> Index: testsuite/gcc.dg/pr43419.c
> ===================================================================
> --- testsuite/gcc.dg/pr43419.c (revision 0)
> +++ testsuite/gcc.dg/pr43419.c (revision 0)
> @@ -0,0 +1,19 @@
> +/* { dg-do run } */
> +/* { dg-options "-O1" } */
> +/* { dg-add-options ieee } */
> +#include <math.h>
> +
> +extern void abort (void);
> +void __attribute__((noinline)) f (double x)
> +{
> + double pluszero = pow (x, 0.5);
> + double minuszero = sqrt (x);
> + if (signbit (pluszero) == signbit (minuszero))
> + abort ();
> +}
> +
> +int main(void)
> +{
> + f (-0.0);
> + return 0;
> +}
More information about the Gcc-patches
mailing list