[PATCH] Add vector integer support to double-conversion patterns

Richard Biener <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
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).

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

	* 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]>
---
 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 beea45357e2..0a324bef62e 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -5816,24 +5816,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
@@ -5845,7 +5845,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
@@ -5856,7 +5858,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
@@ -5869,7 +5873,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:
@@ -5884,7 +5890,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
@@ -5902,13 +5908,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)
@@ -5921,9 +5930,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 1b80cac85c7..3c9329a2f71 100644
--- a/gcc/optabs-tree.cc
+++ b/gcc/optabs-tree.cc
@@ -315,7 +315,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));
@@ -342,8 +341,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);
@@ -359,16 +357,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;
@@ -388,24 +381,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 dad9ed9b0ba..fb9469aaece 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 75f06c6ba41..0531311444b 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 92aecc656e1..1aa0303d266 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 a8c31974973..b1491bd39ad 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 50fa0e4bc42..a023977bc51 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;
 	}
     }
-- 
2.51.0
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.