[gcc r16-5902] Move even/odd validity check from supportable_widening_operation to caller

Richard Biener rguenth@gcc.gnu.org
Fri Dec 5 11:34:02 GMT 2025


https://gcc.gnu.org/g:1da0e5c1405e87e9f2a11ed358b40dff21085657

commit r16-5902-g1da0e5c1405e87e9f2a11ed358b40dff21085657
Author: Richard Biener <rguenther@suse.de>
Date:   Thu Aug 21 13:46:06 2025 +0200

    Move even/odd validity check from supportable_widening_operation to caller
    
    The following moves the incomplete validity check to use
    WIDEN_MULT_{EVEN,ODD} to the caller of supportable_widening_operation
    where we have access to more (but not enough) information.  I have
    made the test conservative enough I hope.  For the testcase what was
    broken is that it uses a SLP reduction where lane-swizzling isn't
    valid.
    
            PR tree-optimization/123002
            * tree-vectorizer.h (supportable_widening_operation): Remove
            vinfo and stmt_info parameters, add flag to indicate whether
            the context would allow OP_{EVEN,ODD}.
            * tree-vect-patterns.cc (vect_recog_abd_pattern): Adjust
            and pass false.
            (vect_recog_widen_op_pattern): Likewise.
            (vect_recog_widen_abd_pattern): Likewise.
            * tree-vect-stmts.cc (vectorizable_conversion): Move
            even/odd validity check here, from supportable_widening_operation.
            Adjust it to be conservative.
            (supportable_widening_operation): Get flag whether even/odd
            is OK to use and remove then unused parameters and code.
    
            * gcc.dg/vect/vect-pr123002.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/vect/vect-pr123002.c | 39 +++++++++++++++++
 gcc/tree-vect-patterns.cc                 | 12 +++---
 gcc/tree-vect-stmts.cc                    | 70 ++++++++++++++++---------------
 gcc/tree-vectorizer.h                     |  3 +-
 4 files changed, 82 insertions(+), 42 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr123002.c b/gcc/testsuite/gcc.dg/vect/vect-pr123002.c
new file mode 100644
index 000000000000..9d9da280800d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-pr123002.c
@@ -0,0 +1,39 @@
+/* { dg-additional-options "-mavx2" { target avx2 } } */
+
+#include "tree-vect.h"
+
+static unsigned int const enc_table_32[8][3] = {
+    {513735U, 77223048U, 437087610U },
+    {0U,      78508U,    646269101U },
+    {0U,      0U,        11997U,    },
+    {0U,      0U,        0U,        },
+    {0U,      0U,        0U,        },
+    {0U,      0U,        0U,        },
+    {0U,      0U,        0U,        },
+    {0U,      0U,        0U,        }};
+
+int __attribute__((noipa)) foo()
+{
+  unsigned long intermediate[3] = {0};
+
+  for (unsigned long i = 0UL; i < 8; i++) {
+      intermediate[0] += 2 * (unsigned long)(enc_table_32)[i][0];
+      intermediate[1] += 2 * (unsigned long)(enc_table_32)[i][1];
+      intermediate[2] += 2 * (unsigned long)(enc_table_32)[i][2];
+  }
+
+  if (intermediate[0] == 0xfad8e &&
+      intermediate[1] == 0x9370e68 && intermediate[2] == 0x8125ca08) {
+      return 0;
+  } else {
+      return 1;
+  }
+}
+
+int main()
+{
+  check_vect ();
+  if (foo ())
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index db510e5f9b96..555986b4fec5 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -1539,9 +1539,8 @@ vect_recog_abd_pattern (vec_info *vinfo,
       int dummy_int;
       auto_vec<tree> dummy_vec;
       if (mid_vectype
-	  && supportable_widening_operation (vinfo, IFN_VEC_WIDEN_ABD,
-					     stmt_vinfo, mid_vectype,
-					     vectype_in,
+	  && supportable_widening_operation (IFN_VEC_WIDEN_ABD,
+					     mid_vectype, vectype_in, false,
 					     &dummy_code, &dummy_code,
 					     &dummy_int, &dummy_vec))
 	{
@@ -1661,8 +1660,7 @@ vect_recog_widen_op_pattern (vec_info *vinfo,
   if (!vectype
       || !vecitype
       || !vecctype
-      || !supportable_widening_operation (vinfo, wide_code, last_stmt_info,
-					  vecitype, vectype,
+      || !supportable_widening_operation (wide_code, vecitype, vectype, true,
 					  &dummy_code, &dummy_code,
 					  &dummy_int, &dummy_vec))
     return NULL;
@@ -1762,8 +1760,8 @@ vect_recog_widen_abd_pattern (vec_info *vinfo, stmt_vec_info stmt_vinfo,
   code_helper dummy_code;
   int dummy_int;
   auto_vec<tree> dummy_vec;
-  if (!supportable_widening_operation (vinfo, IFN_VEC_WIDEN_ABD, stmt_vinfo,
-				       vectype_out, vectype_in,
+  if (!supportable_widening_operation (IFN_VEC_WIDEN_ABD, vectype_out,
+				       vectype_in, false,
 				       &dummy_code, &dummy_code,
 				       &dummy_int, &dummy_vec))
     return NULL;
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 12eb5ea5b5e3..dc155dcc7fee 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -5424,6 +5424,7 @@ vectorizable_conversion (vec_info *vinfo,
   scalar_mode rhs_mode = SCALAR_TYPE_MODE (rhs_type);
   opt_scalar_mode rhs_mode_iter;
   auto_vec<std::pair<tree, tree_code>, 2> converts;
+  bool evenodd_ok = false;
 
   /* Supportable by target?  */
   switch (modifier)
@@ -5471,10 +5472,28 @@ vectorizable_conversion (vec_info *vinfo,
 	  gcc_assert (!(multi_step_cvt && op_type == binary_op));
 	  break;
 	}
-      if (supportable_widening_operation (vinfo, code, stmt_info,
-					       vectype_out, vectype_in, &code1,
-					       &code2, &multi_step_cvt,
-					       &interm_types))
+      /* Elements in a vector can only be reordered if used in a reduction
+	 operation only.  */
+      if (code == WIDEN_MULT_EXPR
+	  && loop_vinfo
+	  && !nested_in_vect_loop_p (LOOP_VINFO_LOOP (loop_vinfo), stmt_info)
+	  /* For a SLP reduction we cannot swizzle lanes, detecting a
+	     reduction chain isn't possible here.  */
+	  && SLP_TREE_LANES (slp_node) == 1)
+	{
+	  /* ???  There is no way to look for SLP uses, so work on
+	     the stmt and what the stmt-based cycle detection gives us.  */
+	  tree lhs = gimple_get_lhs (vect_orig_stmt (stmt_info)->stmt);
+	  stmt_vec_info use_stmt_info
+	    = lhs ? loop_vinfo->lookup_single_use (lhs) : NULL;
+	  if (use_stmt_info
+	      && STMT_VINFO_REDUC_DEF (use_stmt_info))
+	    evenodd_ok = true;
+	}
+      if (supportable_widening_operation (code, vectype_out, vectype_in,
+					  evenodd_ok, &code1,
+					  &code2, &multi_step_cvt,
+					  &interm_types))
 	{
 	  /* Binary widening operation can only be supported directly by the
 	     architecture.  */
@@ -5508,18 +5527,17 @@ vectorizable_conversion (vec_info *vinfo,
 		goto unsupported;
 	      codecvt1 = tc1;
 	    }
-	  else if (!supportable_widening_operation (vinfo, code,
-						    stmt_info, vectype_out,
-						    cvt_type, &codecvt1,
+	  else if (!supportable_widening_operation (code, vectype_out,
+						    cvt_type, evenodd_ok,
+						    &codecvt1,
 						    &codecvt2, &multi_step_cvt,
 						    &interm_types))
 	    continue;
 	  else
 	    gcc_assert (multi_step_cvt == 0);
 
-	  if (supportable_widening_operation (vinfo, NOP_EXPR, stmt_info,
-					      cvt_type,
-					      vectype_in, &code1,
+	  if (supportable_widening_operation (NOP_EXPR, cvt_type,
+					      vectype_in, evenodd_ok, &code1,
 					      &code2, &multi_step_cvt,
 					      &interm_types))
 	    {
@@ -13829,6 +13847,8 @@ vect_maybe_update_slp_op_vectype (slp_tree op, tree vectype)
    are supported by the target platform either directly (via vector
    tree-codes), or via target builtins.
 
+   When EVENODD_OK then also lane-swizzling operations are considered.
+
    Output:
    - CODE1 and CODE2 are codes of vector operations to be used when
    vectorizing the operation, if available.
@@ -13839,17 +13859,14 @@ vect_maybe_update_slp_op_vectype (slp_tree op, tree vectype)
    widening operation (short in the above example).  */
 
 bool
-supportable_widening_operation (vec_info *vinfo,
-				code_helper code,
-				stmt_vec_info stmt_info,
+supportable_widening_operation (code_helper code,
 				tree vectype_out, tree vectype_in,
+				bool evenodd_ok,
 				code_helper *code1,
 				code_helper *code2,
                                 int *multi_step_cvt,
                                 vec<tree> *interm_types)
 {
-  loop_vec_info loop_info = dyn_cast <loop_vec_info> (vinfo);
-  class loop *vect_loop = NULL;
   machine_mode vec_mode;
   enum insn_code icode1, icode2;
   optab optab1 = unknown_optab, optab2 = unknown_optab;
@@ -13862,8 +13879,6 @@ supportable_widening_operation (vec_info *vinfo,
   optab optab3, optab4;
 
   *multi_step_cvt = 0;
-  if (loop_info)
-    vect_loop = LOOP_VINFO_LOOP (loop_info);
 
   switch (code.safe_as_tree_code ())
     {
@@ -13905,24 +13920,13 @@ supportable_widening_operation (vec_info *vinfo,
 	 on VEC_WIDEN_MULT_EVEN_EXPR.  If it succeeds, all the return values
 	 are properly set up for the caller.  If we fail, we'll continue with
 	 a VEC_WIDEN_MULT_LO/HI_EXPR check.  */
-      if (vect_loop
-	  && !nested_in_vect_loop_p (vect_loop, stmt_info)
-	  && supportable_widening_operation (vinfo, VEC_WIDEN_MULT_EVEN_EXPR,
-					     stmt_info, vectype_out,
-					     vectype_in, code1,
+      if (evenodd_ok
+	  && supportable_widening_operation (VEC_WIDEN_MULT_EVEN_EXPR,
+					     vectype_out, vectype_in,
+					     evenodd_ok, code1,
 					     code2, multi_step_cvt,
 					     interm_types))
-        {
-          /* Elements in a vector with vect_used_by_reduction property cannot
-             be reordered if the use chain with this property does not have the
-             same operation.  One such an example is s += a * b, where elements
-             in a and b cannot be reordered.  Here we check if the vector defined
-             by STMT is only directly used in the reduction statement.  */
-	  tree lhs = gimple_assign_lhs (vect_orig_stmt (stmt_info)->stmt);
-	  stmt_vec_info use_stmt_info = loop_info->lookup_single_use (lhs);
-	  if (use_stmt_info && STMT_VINFO_REDUC_DEF (use_stmt_info))
-	    return true;
-        }
+	return true;
       c1 = VEC_WIDEN_MULT_LO_EXPR;
       c2 = VEC_WIDEN_MULT_HI_EXPR;
       break;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 606133f9172e..563a69ffd93b 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -2496,8 +2496,7 @@ extern bool vect_is_simple_use (vec_info *, slp_tree,
 				tree *, stmt_vec_info * = NULL);
 extern bool vect_maybe_update_slp_op_vectype (slp_tree, tree);
 extern tree perm_mask_for_reverse (tree);
-extern bool supportable_widening_operation (vec_info*, code_helper,
-					    stmt_vec_info, tree, tree,
+extern bool supportable_widening_operation (code_helper, tree, tree, bool,
 					    code_helper*, code_helper*,
 					    int*, vec<tree> *);
 extern bool supportable_narrowing_operation (code_helper, tree, tree,


More information about the Gcc-cvs mailing list