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)
}
}
+/* 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
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);
--- /dev/null
+/* { 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;
+}
+
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