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; } }
