https://gcc.gnu.org/g:195bc16864c5f75a03e631049f22a3fd0d1d7367

commit r17-5195-g195bc16864c5f75a03e631049f22a3fd0d1d7367
Author: Richard Biener <[email protected]>
Date:   Wed Oct 14 07:46:17 2026 +0200

    tree-optimization/127876 - wrong code with conditional float reduction
    
    When vectorizing a reduction r = <cond> ? r : CST we reduce a
    vector mixed with the initial constant value and the constant
    and perform a final MAX or MIN reduction dependent on the
    relation of the intiial value and the constant reduction value.
    That only works if they do not compare equal.  Use explicit
    LT/GT checks to cover -0.0 vs 0.0 but also NaNs.
    
            PR tree-optimization/127876
            * tree-vect-loop.cc (vectorizable_reduction): For
            conditional reduction assign then CONST_COND_REDUCTION mode
            with explicit LT/GT checks.
    
            * gcc.dg/vect/vect-pr127876-1.c: New testcase.
            * gcc.dg/vect/vect-pr127876-2.c: Likewise.

Diff:
---
 gcc/testsuite/gcc.dg/vect/vect-pr127876-1.c | 30 +++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/vect/vect-pr127876-2.c | 30 +++++++++++++++++++++++++++++
 gcc/tree-vect-loop.cc                       | 17 +++++++++++-----
 3 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr127876-1.c 
b/gcc/testsuite/gcc.dg/vect/vect-pr127876-1.c
new file mode 100644
index 000000000000..5fd783383e32
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-pr127876-1.c
@@ -0,0 +1,30 @@
+/* { dg-additional-options "-fsigned-zeros" } */
+
+#include "tree-vect.h"
+
+__attribute__((noipa))
+double f (double *a, int n)
+{
+  double r = 0.0;
+  for (int i = 0; i < n; i++)
+    if (a[i] > 100.0)
+      r = -0.0;
+  return r;
+}
+
+int main (void)
+{
+  double a[32];
+
+  check_vect ();
+
+#pragma GCC novector
+  for (int i = 0; i < 32; i++)
+    a[i] = 1.0;
+  a[7] = 200.0;
+
+  double r = f (a, 32);
+  if (__builtin_copysign (1., r) != -1.)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr127876-2.c 
b/gcc/testsuite/gcc.dg/vect/vect-pr127876-2.c
new file mode 100644
index 000000000000..9df1957f985f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-pr127876-2.c
@@ -0,0 +1,30 @@
+/* { dg-additional-options "-fno-trapping-math" } */
+
+#include "tree-vect.h"
+
+__attribute__((noipa))
+double f (double *a, int n)
+{
+  double r = __builtin_nan ("");
+  for (int i = 0; i < n; i++)
+    if (a[i] > 100.0)
+      r = -0.0;
+  return r;
+}
+
+int main (void)
+{
+  double a[32];
+
+  check_vect ();
+
+#pragma GCC novector
+  for (int i = 0; i < 32; i++)
+    a[i] = 1.0;
+  a[7] = 200.0;
+
+  double r = f (a, 32);
+  if (__builtin_copysign (1., r) != -1.)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index b2639444ebdb..1b76358ec11b 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -7384,17 +7384,24 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
              && types_compatible_p (TREE_TYPE (cond_initial_val),
                                     TREE_TYPE (cond_reduc_val)))
            {
-             tree e = fold_binary (LE_EXPR, boolean_type_node,
-                                   cond_initial_val, cond_reduc_val);
-             if (e && (integer_onep (e) || integer_zerop (e)))
+             tree lt, gt;
+             enum tree_code cond_reduc_code = ERROR_MARK;
+             if ((lt = fold_binary (LT_EXPR, boolean_type_node,
+                                    cond_initial_val, cond_reduc_val))
+                 && integer_onep (lt))
+               cond_reduc_code = MAX_EXPR;
+             else if ((gt = fold_binary (GT_EXPR, boolean_type_node,
+                                         cond_initial_val, cond_reduc_val))
+                      && integer_onep (gt))
+               cond_reduc_code = MIN_EXPR;
+             if (cond_reduc_code != ERROR_MARK)
                {
                  if (dump_enabled_p ())
                    dump_printf_loc (MSG_NOTE, vect_location,
                                     "condition expression based on "
                                     "compile time constant.\n");
                  /* Record reduction code at analysis stage.  */
-                 VECT_REDUC_INFO_CODE (reduc_info)
-                   = integer_onep (e) ? MAX_EXPR : MIN_EXPR;
+                 VECT_REDUC_INFO_CODE (reduc_info) = cond_reduc_code;
                  VECT_REDUC_INFO_TYPE (reduc_info) = CONST_COND_REDUCTION;
                }
            }

Reply via email to