https://gcc.gnu.org/g:8afde8eab36eb74ceecfbcc20322693358feba94
commit r17-5454-g8afde8eab36eb74ceecfbcc20322693358feba94 Author: Roger Sayle <[email protected]> Date: Wed Oct 21 13:21:47 2026 +0100 PR tree-optimization/126562: vectorizer vs. pow (x, 0.5) -> sqrt This patch fixes the vectorizer aspects of PR tree-optimization/126562, where GCC is inappropriately converting pow(x, 0.5) into sqrt(x). The scalar aspects were fixed in my patch for PR tree-optimization/127544. Unfortunately, this correctness patch required tweaking two existing testcases as the vectorizer no longer recognizes opportunities that match.pd missed, though these loops are still vectorized with the appropriate flags, for example with -Ofast. 2026-10-21 Roger Sayle <[email protected]> gcc/ChangeLog PR tree-optimization/126562 * tree-vect-patterns.cc (vect_recog_pow_pattern): Update square root case to check for signed zero or negative infinity. gcc/testsuite/ChangeLog PR tree-optimization/126562 * gcc.dg/vect/no-math-errno-slp-32.c: Update test case. * gcc.dg/vect/no-math-errno-vect-pow-1.c: Likewise. * gcc.dg/vect/pr126562-1.c: New execution test. * gcc.dg/vect/pr126562-2.c: Likewise. Diff: --- gcc/testsuite/gcc.dg/vect/no-math-errno-slp-32.c | 3 +- .../gcc.dg/vect/no-math-errno-vect-pow-1.c | 3 +- gcc/testsuite/gcc.dg/vect/pr126562-1.c | 33 +++++++++++++++++++++ gcc/testsuite/gcc.dg/vect/pr126562-2.c | 34 ++++++++++++++++++++++ gcc/tree-vect-patterns.cc | 10 +++++-- 5 files changed, 77 insertions(+), 6 deletions(-) diff --git a/gcc/testsuite/gcc.dg/vect/no-math-errno-slp-32.c b/gcc/testsuite/gcc.dg/vect/no-math-errno-slp-32.c index 0b16a1395e4a..1c79fcfe4b9e 100644 --- a/gcc/testsuite/gcc.dg/vect/no-math-errno-slp-32.c +++ b/gcc/testsuite/gcc.dg/vect/no-math-errno-slp-32.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target vect_double } */ -/* { dg-additional-options "-fno-math-errno" } */ +/* { dg-additional-options "-fno-math-errno -ffinite-math-only -fno-signed-zeros" } */ double x[256]; @@ -14,4 +14,3 @@ void foo(void) } } -/* { dg-final { scan-tree-dump "pattern recognized" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-math-errno-vect-pow-1.c b/gcc/testsuite/gcc.dg/vect/no-math-errno-vect-pow-1.c index 9794de78f2b9..25e29014f704 100644 --- a/gcc/testsuite/gcc.dg/vect/no-math-errno-vect-pow-1.c +++ b/gcc/testsuite/gcc.dg/vect/no-math-errno-vect-pow-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target vect_double } */ -/* { dg-additional-options "-fno-math-errno" } */ +/* { dg-additional-options "-fno-math-errno -ffinite-math-only -fno-signed-zeros" } */ double x[256]; @@ -11,4 +11,3 @@ void foo(void) x[i] = __builtin_pow (x[i], 0.5); } -/* { dg-final { scan-tree-dump "pattern recognized" "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr126562-1.c b/gcc/testsuite/gcc.dg/vect/pr126562-1.c new file mode 100644 index 000000000000..294a6442fc14 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr126562-1.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-math-errno" } */ +/* { dg-add-options ieee } */ + +/* 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. */ + +#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; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr126562-2.c b/gcc/testsuite/gcc.dg/vect/pr126562-2.c new file mode 100644 index 000000000000..411884be11b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr126562-2.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-math-errno" } */ +/* { dg-add-options ieee } */ + +/* 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. */ + +#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; +} + diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 6b6ff94cf0aa..49c85c703033 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -2540,9 +2540,15 @@ vect_recog_pow_pattern (vec_info *vinfo, return stmt; } - /* Catch square root. */ + /* Catch square root. Transforming pow(x,0.5) to sqrt(x) is unsafe + for signed zeroes and negative infinity. + pow(-0,0.5) = +0, while sqrt(-0) = -0. + pow(-Inf,0.5) = +Inf, while sqrt(-Inf) is NaN. */ if (TREE_CODE (exp) == REAL_CST - && real_equal (&TREE_REAL_CST (exp), &dconsthalf)) + && real_equal (&TREE_REAL_CST (exp), &dconsthalf) + && !tree_expr_maybe_real_minus_zero_p (base) + && (!tree_expr_maybe_infinite_p (base) + || tree_expr_nonnegative_p (base))) { *type_out = get_vectype_for_scalar_type (vinfo, TREE_TYPE (base)); if (*type_out
