https://gcc.gnu.org/g:185a8bae0f2ce46c65ec6a541c2fe7299df6d7f4
commit r15-10001-g185a8bae0f2ce46c65ec6a541c2fe7299df6d7f4 Author: Richard Biener <rguent...@suse.de> Date: Wed Jul 16 15:07:58 2025 +0200 tree-optimization/121049 - avoid loop masking with even/odd reduction The following disables loop masking when we are using an even/odd widening operation in a reduction because the loop mask then aligns to the wrong elements. PR tree-optimization/121049 * internal-fn.h (widening_evenodd_fn_p): Declare. * internal-fn.cc (widening_evenodd_fn_p): New function. * tree-vect-stmts.cc (vectorizable_conversion): When using an even/odd widening function disable loop masking. * gcc.dg/vect/pr121049.c: New testcase. (cherry picked from commit bc5570f7ef796fa7f5ab89b34ed9de2be5299f0e) Diff: --- gcc/internal-fn.cc | 27 +++++++++++++++++++++++++++ gcc/internal-fn.h | 1 + gcc/testsuite/gcc.dg/vect/pr121049.c | 25 +++++++++++++++++++++++++ gcc/tree-vect-stmts.cc | 14 ++++++++++++++ 4 files changed, 67 insertions(+) diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc index 9b96cb2325d4..044f66830b35 100644 --- a/gcc/internal-fn.cc +++ b/gcc/internal-fn.cc @@ -4542,6 +4542,33 @@ widening_fn_p (code_helper code) } } +/* Return true if this CODE describes an internal_fn that returns a vector with + elements twice as wide as the element size of the input vectors and operates + on even/odd parts of the input. */ + +bool +widening_evenodd_fn_p (code_helper code) +{ + if (!code.is_fn_code ()) + return false; + + if (!internal_fn_p ((combined_fn) code)) + return false; + + internal_fn fn = as_internal_fn ((combined_fn) code); + switch (fn) + { + #define DEF_INTERNAL_WIDENING_OPTAB_FN(NAME, F, S, SO, UO, T) \ + case IFN_##NAME##_EVEN: \ + case IFN_##NAME##_ODD: \ + return true; + #include "internal-fn.def" + + default: + return false; + } +} + /* Return true if IFN_SET_EDOM is supported. */ bool diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h index afd4f8e64c7b..02731ea03aeb 100644 --- a/gcc/internal-fn.h +++ b/gcc/internal-fn.h @@ -219,6 +219,7 @@ extern bool commutative_ternary_fn_p (internal_fn); extern int first_commutative_argument (internal_fn); extern bool associative_binary_fn_p (internal_fn); extern bool widening_fn_p (code_helper); +extern bool widening_evenodd_fn_p (code_helper); extern bool set_edom_supported_p (void); diff --git a/gcc/testsuite/gcc.dg/vect/pr121049.c b/gcc/testsuite/gcc.dg/vect/pr121049.c new file mode 100644 index 000000000000..558c92ab884d --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr121049.c @@ -0,0 +1,25 @@ +/* { dg-additional-options "--param vect-partial-vector-usage=1" } */ +/* { dg-additional-options "-march=x86-64-v4" { target avx512f_runtime } } */ + +#include "tree-vect.h" + +int mon_lengths[12] = { 1, 10, 100 }; + +__attribute__ ((noipa)) long +transtime (int mon) +{ + long value = 0; + for (int i = 0; i < mon; ++i) + value += mon_lengths[i] * 2l; + return value; +} + +int +main () +{ + check_vect (); + if (transtime (3) != 222) + __builtin_abort (); + return 0; +} + diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 89ac5f611276..cba69ebadf0d 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -5920,6 +5920,20 @@ vectorizable_conversion (vec_info *vinfo, gcc_unreachable (); } + if (modifier == WIDEN + && loop_vinfo + && LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) + && (code1 == VEC_WIDEN_MULT_EVEN_EXPR + || widening_evenodd_fn_p (code1))) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "can't use a fully-masked loop because" + " widening operation on even/odd elements" + " mixes up lanes.\n"); + LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false; + } + if (!vec_stmt) /* transformation not required. */ { if (slp_node