]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/121049 - avoid loop masking with even/odd reduction
authorRichard Biener <rguenther@suse.de>
Wed, 16 Jul 2025 13:07:58 +0000 (15:07 +0200)
committerRichard Biener <rguenther@suse.de>
Wed, 16 Jul 2025 17:44:21 +0000 (19:44 +0200)
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.

gcc/internal-fn.cc
gcc/internal-fn.h
gcc/testsuite/gcc.dg/vect/pr121049.c [new file with mode: 0644]
gcc/tree-vect-stmts.cc

index 044bdc22481f93f6bc81d7b1961ccdee21b8ff86..114f5a9da18d04172faa8ea6d90d6c40b9724c00 100644 (file)
@@ -4548,6 +4548,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
index afd4f8e64c7b373fb0897b9fd93c002a2353e543..02731ea03aeb6c9b01ce375549bc89021458beb7 100644 (file)
@@ -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 (file)
index 0000000..558c92a
--- /dev/null
@@ -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;
+}
+
index e2dcfaa7a1fc252756d445ca276e1978ec6e6f40..f0d31058372365225b91644074143faefdce2064 100644 (file)
@@ -5460,6 +5460,7 @@ vectorizable_conversion (vec_info *vinfo,
   vec<tree> vec_oprnds1 = vNULL;
   tree vop0;
   bb_vec_info bb_vinfo = dyn_cast <bb_vec_info> (vinfo);
+  loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
   int multi_step_cvt = 0;
   vec<tree> interm_types = vNULL;
   tree intermediate_type, cvt_type = NULL_TREE;
@@ -5802,6 +5803,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 (!vect_maybe_update_slp_op_vectype (slp_op0, vectype_in)