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

Reply via email to