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

Reply via email to