https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126562

            Bug ID: 126562
           Summary: Invalid pow (x, 0.5) -> sqrt transformation when
                    signed zeros or infinities are required
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---

I guess these are two separate bugs but they are related:

/* pow (x, 0.5) must not become sqrt (x) while signed zeros are honoured:
   C99 Annex F.10.4.4 gives pow (-0.0, 0.5) == +0.0, while F.10.4.5 gives
   sqrt (-0.0) == -0.0.

   Two independent sites did this rewrite with an insufficient guard:
     tree-vect-patterns.cc vect_recog_pow_pattern, no guard at all
     tree-ssa-math-opts.cc gimple_expand_builtin_pow, no !HONOR_INFINITIES */

#include <math.h>

void __attribute__((noinline, noipa))
f (double *restrict d, const double *restrict s, int n)
{
  for (int i = 0; i < n; i++)
    d[i] = pow (s[i], 0.5);
}

int
main (void)
{
  double s[8], d[8];

  for (int i = 0; i < 8; i++)
    s[i] = -0.0;

  f (d, s, 8);

  for (int i = 0; i < 8; i++)
    if (__builtin_signbit (d[i]) != 0)
      __builtin_abort ();

  return 0;
}

/* pow (x, 0.5) must not become sqrt (x) while infinities are honoured:
   C99 Annex F.10.4.4 gives pow (-Inf, 0.5) == +Inf, while F.10.4.5 gives
   sqrt (-Inf) == NaN, with the invalid exception raised.

   The comment on the scalar fold in tree-ssa-math-opts.cc claims the
   rewrite is "always safe unless signed zeros must be maintained", which
   misses this case entirely. */

#include <math.h>

void __attribute__((noinline, noipa))
f (double *restrict d, const double *restrict s, int n)
{
  for (int i = 0; i < n; i++)
    d[i] = pow (s[i], 0.5);
}

int
main (void)
{
  double s[8], d[8];

  for (int i = 0; i < 8; i++)
    s[i] = 4.0;
  s[3] = -__builtin_inf ();

  f (d, s, 8);

  if (d[3] != __builtin_inf ())
    __builtin_abort ();

  return 0;
}

Both abort at -O3 -fno-math-errno on aarch64

Reply via email to