[gcc r17-3258] Add vector integer support to double-conversion patterns

Richard Biener via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:4c136e1d333bc4cf142adbb17d644d5ded5afe63

commit r17-3258-g4c136e1d333bc4cf142adbb17d644d5ded5afe63
Author: Richard Biener <[email protected]>
Date:   Thu Aug 13 09:24:09 2026 +0200

    Add vector integer support to double-conversion patterns
    
    The following expands the double-conversion match patterns to also
    cover integer vectors (it already supports float vectors), adding
    required guards for supportability.  I have simplified
    supportable_convert_operation by eliding the useless output code
    argument (it's always the same as the input code).
    
            * match.pd ((convert (convert @0))): Allow integer vector
            types, unify {inside,intrer,final}_vec, guard patterns that
            are not correct for vectors and those that are with
            checks the resulting conversion is supported by the target.
            * optabs-tree.h (supportable_convert_operation): Remove
            useless last argument.
            * optabs-tree.cc (supportable_convert_operation): Likewise.
            (supportable_half_widening_operation): Adjust.
            * tree-vect-stmts.cc (vectorizable_conversion): Likewise.
            (supportable_indirect_convert_operation): Likewise.
            * tree-vect-generic.cc (expand_vector_conversion): Likewise.
            * tree-vect-data-refs.cc (vect_gather_scatter_fn_p): Likewise.
            * tree-ssa-forwprop.cc (simplify_vector_constructor): Likewise.
    
    Co-Authored-By: H.J. Lu <[email protected]>

Diff:
---
 gcc/match.pd               | 38 ++++++++++++++++++++++++--------------
 gcc/optabs-tree.cc         | 28 ++++++----------------------
 gcc/optabs-tree.h          |  8 +++-----
 gcc/tree-ssa-forwprop.cc   |  6 ++----
 gcc/tree-vect-data-refs.cc |  5 ++---
 gcc/tree-vect-generic.cc   |  5 ++---
 gcc/tree-vect-stmts.cc     | 32 ++++++++++++++------------------
 7 files changed, 53 insertions(+), 69 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 3f476cc4baad..5fc89426880d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -5839,24 +5839,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     {
       tree inside_type = TREE_TYPE (@0);
       tree inter_type = TREE_TYPE (@1);
-      int inside_int = INTEGRAL_TYPE_P (inside_type);
+      int inside_int = ANY_INTEGRAL_TYPE_P (inside_type);
       int inside_ptr = POINTER_TYPE_P (inside_type);
       int inside_float = FLOAT_TYPE_P (inside_type);
-      int inside_vec = VECTOR_TYPE_P (inside_type);
       unsigned int inside_prec = element_precision (inside_type);
       int inside_unsignedp = TYPE_UNSIGNED (inside_type);
-      int inter_int = INTEGRAL_TYPE_P (inter_type);
+      int inter_int = ANY_INTEGRAL_TYPE_P (inter_type);
       int inter_ptr = POINTER_TYPE_P (inter_type);
       int inter_float = FLOAT_TYPE_P (inter_type);
-      int inter_vec = VECTOR_TYPE_P (inter_type);
       unsigned int inter_prec = element_precision (inter_type);
       int inter_unsignedp = TYPE_UNSIGNED (inter_type);
-      int final_int = INTEGRAL_TYPE_P (type);
+      int final_int = ANY_INTEGRAL_TYPE_P (type);
       int final_ptr = POINTER_TYPE_P (type);
       int final_float = FLOAT_TYPE_P (type);
-      int final_vec = VECTOR_TYPE_P (type);
       unsigned int final_prec = element_precision (type);
       int final_unsignedp = TYPE_UNSIGNED (type);
+      int is_vec = VECTOR_TYPE_P (type);
+      gcc_checking_assert (is_vec == VECTOR_TYPE_P (inside_type)
+			   && is_vec == VECTOR_TYPE_P (inter_type));
     }
    (switch
     /* In addition to the cases of two conversions in a row
@@ -5868,7 +5868,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	      && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
 	 && (((inter_int || inter_ptr) && final_int)
 	     || (inter_float && final_float))
-	 && inter_prec >= final_prec)
+	 && inter_prec >= final_prec
+	 && (! is_vec
+	     || supportable_convert_operation (ocvt, type, TREE_TYPE (@0))))
      (ocvt @0))
 
     /* Likewise, if the intermediate and initial types are either both
@@ -5879,7 +5881,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (((inter_int && inside_int) || (inter_float && inside_float))
 	 && (final_int || final_float)
 	 && inter_prec >= inside_prec
-	 && (inter_float || inter_unsignedp == inside_unsignedp))
+	 && (inter_float || inter_unsignedp == inside_unsignedp)
+	 && (! is_vec
+	     || supportable_convert_operation (ocvt, type, TREE_TYPE (@0))))
      (ocvt @0))
 
     /* If we have a sign-extension of a zero-extended value, we can
@@ -5892,7 +5896,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	      && inside_unsignedp && !inter_unsignedp)
 	     || final_prec == inter_prec
 	     || (inside_prec < inter_prec && inter_prec > final_prec
-		 && !inside_unsignedp && inter_unsignedp)))
+		 && !inside_unsignedp && inter_unsignedp))
+	 && (! is_vec
+	     || supportable_convert_operation (ocvt, type, TREE_TYPE (@0))))
      (ocvt @0))
 
     /* Two conversions in a row are not needed unless:
@@ -5907,7 +5913,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	- the final type is a pointer type and the precisions of the
 	  initial and intermediate types differ.  */
     (if (! inside_float && ! inter_float && ! final_float
-	 && ! inside_vec && ! inter_vec && ! final_vec
+	 && ! is_vec
 	 && (inter_prec >= inside_prec || inter_prec >= final_prec)
 	 && ! (inside_int && inter_int
 	       && inter_unsignedp != inside_unsignedp
@@ -5925,13 +5931,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
       a sign change of the type. */
    (if (inside_int && inter_int && final_int
         && final_prec <= inside_prec
-	&& inter_prec >= inside_prec)
+	&& inter_prec >= inside_prec
+	&& (! is_vec
+	    || supportable_convert_operation (ocvt, type, TREE_TYPE (@0))))
     (convert @0))
 
     /* A truncation to an unsigned type (a zero-extension) should be
        canonicalized as bitwise and of a mask.  */
     (if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion.  */
 	 && final_int && inter_int && inside_int
+	 && ! is_vec
 	 && final_prec >= inside_prec
 	 && inside_prec > inter_prec
 	 && inter_unsignedp)
@@ -5944,9 +5953,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        represent it exactly and back to an integer, we can skip the
        floating-point conversion.  */
     (if (GIMPLE /* PR66211 */
-	 && inside_int && inter_float && final_int &&
-	 (unsigned) significand_size (TYPE_MODE (inter_type))
-	 >= inside_prec - !inside_unsignedp)
+	 && inside_int && inter_float && final_int
+	 && ! is_vec
+	 && ((unsigned) significand_size (TYPE_MODE (inter_type))
+	     >= inside_prec - !inside_unsignedp))
      (convert @0)))))))
 
 /* (float_type)(integer_type) x -> trunc (x) if the type of x matches
diff --git a/gcc/optabs-tree.cc b/gcc/optabs-tree.cc
index b7a1cf1f7d8b..5fbdcd3a730d 100644
--- a/gcc/optabs-tree.cc
+++ b/gcc/optabs-tree.cc
@@ -316,7 +316,6 @@ supportable_half_widening_operation (enum tree_code code, tree vectype_out,
 				     tree vectype_in, enum tree_code *code1)
 {
   machine_mode m1,m2;
-  enum tree_code dummy_code;
   optab op;
 
   gcc_assert (VECTOR_TYPE_P (vectype_out) && VECTOR_TYPE_P (vectype_in));
@@ -343,8 +342,7 @@ supportable_half_widening_operation (enum tree_code code, tree vectype_out,
       return false;
     }
 
-  if (!supportable_convert_operation (NOP_EXPR, vectype_out, vectype_in,
-				     &dummy_code))
+  if (!supportable_convert_operation (NOP_EXPR, vectype_out, vectype_in))
     return false;
 
   op = optab_for_tree_code (*code1, vectype_out, optab_vector);
@@ -360,16 +358,11 @@ supportable_half_widening_operation (enum tree_code code, tree vectype_out,
 
    Convert operations we currently support directly are FIX_TRUNC and FLOAT.
    This function checks if these operations are supported
-   by the target platform directly (via vector tree-codes).
-
-   Output:
-   - CODE1 is code of vector operation to be used when
-   vectorizing the operation, if available.  */
+   by the target platform directly (via vector tree-codes).  */
 
 bool
 supportable_convert_operation (enum tree_code code,
-			       tree vectype_out, tree vectype_in,
-			       enum tree_code *code1)
+			       tree vectype_out, tree vectype_in)
 {
   machine_mode m1,m2;
   bool truncp;
@@ -389,24 +382,15 @@ supportable_convert_operation (enum tree_code code,
       || (code == FLOAT_EXPR
 	  && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
 	     != CODE_FOR_nothing))
-    {
-      *code1 = code;
-      return true;
-    }
+    return true;
 
   if (GET_MODE_UNIT_PRECISION (m1) > GET_MODE_UNIT_PRECISION (m2)
       && can_extend_p (m1, m2, TYPE_UNSIGNED (vectype_in)))
-    {
-      *code1 = code;
-      return true;
-    }
+    return true;
 
   if (GET_MODE_UNIT_PRECISION (m1) < GET_MODE_UNIT_PRECISION (m2)
       && convert_optab_handler (trunc_optab, m1, m2) != CODE_FOR_nothing)
-    {
-      *code1 = code;
-      return true;
-    }
+    return true;
 
   return false;
 }
diff --git a/gcc/optabs-tree.h b/gcc/optabs-tree.h
index dad9ed9b0bae..fb9469aaece8 100644
--- a/gcc/optabs-tree.h
+++ b/gcc/optabs-tree.h
@@ -37,11 +37,9 @@ enum optab_subtype
    the second argument.  The third argument distinguishes between the types of
    vector shifts and rotates.  */
 optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
-bool
-supportable_half_widening_operation (enum tree_code, tree, tree,
-				    enum tree_code *);
-bool supportable_convert_operation (enum tree_code, tree, tree,
-				    enum tree_code *);
+bool supportable_half_widening_operation (enum tree_code, tree, tree,
+					  enum tree_code *);
+bool supportable_convert_operation (enum tree_code, tree, tree);
 bool expand_vec_cmp_expr_p (tree, tree, enum tree_code);
 bool expand_vec_cond_expr_p (tree, tree);
 void init_tree_optimization_optabs (tree);
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index 75f06c6ba410..0531311444b9 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -4112,8 +4112,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
       if (conv_code == ERROR_MARK && nelts != refnelts)
 	conv_src_type = type;
       if (conv_code != ERROR_MARK
-	  && !supportable_convert_operation (conv_code, type, conv_src_type,
-					     &conv_code))
+	  && !supportable_convert_operation (conv_code, type, conv_src_type))
 	{
 	  /* Only few targets implement direct conversion patterns so try
 	     some simple special cases via VEC_[UN]PACK[_FLOAT]_LO_EXPR.  */
@@ -4275,8 +4274,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
       tree mask_type, perm_type;
       perm_type = TREE_TYPE (orig[0]);
       if (conv_code != ERROR_MARK
-	  && !supportable_convert_operation (conv_code, type, conv_src_type,
-					     &conv_code))
+	  && !supportable_convert_operation (conv_code, type, conv_src_type))
 	return false;
 
       /* Now that we know the number of elements of the source build the
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index 92aecc656e13..1aa0303d2660 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -4726,7 +4726,6 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
 
   /* Second pass: No direct match.  This means we try to find a sign-swapped
      offset vectype.  */
-  enum tree_code tmp;
   for (unsigned int i = 0; i < configs.length (); i++)
     {
       unsigned int precision
@@ -4735,7 +4734,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
 	  && precision >= needed_precision
 	  && (supportable_convert_operation (CONVERT_EXPR,
 					     configs[i].offset_vectype,
-					     offset_vectype, &tmp)
+					     offset_vectype)
 	      || (needed_precision == offset_precision
 		  && tree_nop_conversion_p (configs[i].offset_vectype,
 					    offset_vectype))))
@@ -4789,7 +4788,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
 	  && precision >= needed_precision
 	  && (supportable_convert_operation (CONVERT_EXPR,
 					     configs[i].offset_vectype,
-					     offset_vectype, &tmp)
+					     offset_vectype)
 	      || (needed_precision == offset_precision
 		  && tree_nop_conversion_p (configs[i].offset_vectype,
 					    offset_vectype))))
diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
index a8c319749733..b1491bd39adf 100644
--- a/gcc/tree-vect-generic.cc
+++ b/gcc/tree-vect-generic.cc
@@ -1929,12 +1929,11 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
 	    {
 	      tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
 	      tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
-	      if (supportable_convert_operation (code, ret1_type, arg1_type,
-						 &code1))
+	      if (supportable_convert_operation (code, ret1_type, arg1_type))
 		{
 		  new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
 						     ret_type, arg1_type, arg,
-						     NULL_TREE, code1, false);
+						     NULL_TREE, code, false);
 		  g = gimple_build_assign (lhs, new_rhs);
 		  gsi_replace (gsi, g, false);
 		  return;
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 50fa0e4bc422..a023977bc51f 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -5554,12 +5554,11 @@ vectorizable_conversion (vec_info *vinfo,
 
 	  if (GET_MODE_SIZE (rhs_mode) == fltsz)
 	    {
-	      tc1 = ERROR_MARK;
 	      gcc_assert (code.is_tree_code ());
 	      if (!supportable_convert_operation ((tree_code) code, vectype_out,
-						  cvt_type, &tc1))
+						  cvt_type))
 		goto unsupported;
-	      codecvt1 = tc1;
+	      codecvt1 = code;
 	    }
 	  else if (!supportable_widening_operation (code, vectype_out,
 						    cvt_type, evenodd_ok,
@@ -5610,9 +5609,9 @@ vectorizable_conversion (vec_info *vinfo,
 	  cvt_type = get_same_sized_vectype (cvt_type, vectype_in);
 	  if (cvt_type == NULL_TREE)
 	    goto unsupported;
-	  if (supportable_convert_operation ((tree_code) code, cvt_type, vectype_in,
-					      &tc1))
-	    codecvt1 = tc1;
+	  if (supportable_convert_operation ((tree_code) code, cvt_type,
+					     vectype_in))
+	    codecvt1 = code;
 	  else
 	    goto unsupported;
 	  if (supportable_narrowing_operation (NOP_EXPR, vectype_out, cvt_type,
@@ -5652,9 +5651,9 @@ vectorizable_conversion (vec_info *vinfo,
 						&interm_types))
 	    goto unsupported;
 	  if (supportable_convert_operation ((tree_code) code, vectype_out,
-					     cvt_type, &tc1))
+					     cvt_type))
 	    {
-	      codecvt1 = tc1;
+	      codecvt1 = code;
 	      modifier = NARROW_SRC;
 	      break;
 	    }
@@ -14300,17 +14299,16 @@ supportable_indirect_convert_operation (code_helper code,
   bool found_mode = false;
   scalar_mode lhs_mode = GET_MODE_INNER (TYPE_MODE (vectype_out));
   scalar_mode rhs_mode = GET_MODE_INNER (TYPE_MODE (vectype_in));
-  tree_code tc1, tc2, code1, code2;
+  tree_code code1, code2;
 
   tree cvt_type = NULL_TREE;
   poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (vectype_in);
 
   if (supportable_convert_operation ((tree_code) code,
 				     vectype_out,
-				     vectype_in,
-				     &tc1))
+				     vectype_in))
     {
-      converts.safe_push (std::make_pair (vectype_out, tc1));
+      converts.safe_push (std::make_pair (vectype_out, (tree_code) code));
       return true;
     }
 
@@ -14412,11 +14410,9 @@ supportable_indirect_convert_operation (code_helper code,
 	  if (cvt_type == NULL_TREE
 	      || maybe_ne (TYPE_VECTOR_SUBPARTS (cvt_type), nelts)
 	      || !supportable_convert_operation ((tree_code) code1,
-						 vectype_out,
-						 cvt_type, &tc1)
+						 vectype_out, cvt_type)
 	      || !supportable_convert_operation ((tree_code) code2,
-						 cvt_type,
-						 vectype_in, &tc2))
+						 cvt_type, vectype_in))
 	    continue;
 
 	  found_mode = true;
@@ -14425,9 +14421,9 @@ supportable_indirect_convert_operation (code_helper code,
 
       if (found_mode)
 	{
-	  converts.safe_push (std::make_pair (cvt_type, tc2));
+	  converts.safe_push (std::make_pair (cvt_type, code2));
 	  if (TYPE_MODE (cvt_type) != TYPE_MODE (vectype_out))
-	    converts.safe_push (std::make_pair (vectype_out, tc1));
+	    converts.safe_push (std::make_pair (vectype_out, code1));
 	  return true;
 	}
     }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.