https://gcc.gnu.org/g:0abb5fa523bcc72ec0891813d778b6b47c305f97

commit r15-5494-g0abb5fa523bcc72ec0891813d778b6b47c305f97
Author: Richard Sandiford <richard.sandif...@arm.com>
Date:   Wed Nov 20 10:04:45 2024 +0000

    Use can_implement_p in the vectoriser
    
    This patch goes through the tree-vect-* code and mechanically replaces
    all tests of optab_handler against CODE_FOR_nothing with calls to the
    new helper functions.
    
    gcc/
            * tree-vect-data-refs.cc (vect_supportable_dr_alignment): Use
            can_implement_p instead of optab_handler.
            * tree-vect-generic.cc (add_rshift, expand_vector_divmod): Likewise.
            (optimize_vector_constructor, type_for_widest_vector_mode): 
Likewise.
            (lower_vec_perm, expand_vector_operations_1): Likewise.
            * tree-vect-loop.cc (have_whole_vector_shift): Likewise.
            * tree-vect-patterns.cc (vect_recog_rotate_pattern): Likewise.
            (target_has_vecop_for_code, vect_recog_mult_pattern): Likewise.
            (vect_recog_divmod_pattern): Likewise.
            * tree-vect-stmts.cc (vect_supportable_shift, vectorizable_shift)
            (scan_store_can_perm_p, check_scan_store, vectorizable_store)
            (vectorizable_load, vectorizable_condition): Likewise.
            (vectorizable_comparison_1): Likewise.

Diff:
---
 gcc/tree-vect-data-refs.cc |  2 +-
 gcc/tree-vect-generic.cc   | 49 ++++++++++++++++++++--------------------------
 gcc/tree-vect-loop.cc      |  2 +-
 gcc/tree-vect-patterns.cc  | 34 ++++++++++++--------------------
 gcc/tree-vect-stmts.cc     | 44 +++++++++++++++--------------------------
 5 files changed, 52 insertions(+), 79 deletions(-)

diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index 3ea5fb883b1a..a32343c0022b 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -7209,7 +7209,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, 
dr_vec_info *dr_info,
 
   if (DR_IS_READ (dr))
     {
-      if (optab_handler (vec_realign_load_optab, mode) != CODE_FOR_nothing
+      if (can_implement_p (vec_realign_load_optab, mode)
          && (!targetm.vectorize.builtin_mask_for_load
              || targetm.vectorize.builtin_mask_for_load ()))
        {
diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
index b68355ed8b96..b40e3d745790 100644
--- a/gcc/tree-vect-generic.cc
+++ b/gcc/tree-vect-generic.cc
@@ -479,14 +479,14 @@ add_rshift (gimple_stmt_iterator *gsi, tree type, tree 
op0, int *shiftcnts)
     {
       op = optab_for_tree_code (RSHIFT_EXPR, type, optab_scalar);
       if (op != unknown_optab
-         && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
+         && can_implement_p (op, TYPE_MODE (type)))
        return gimplify_build2 (gsi, RSHIFT_EXPR, type, op0,
                                build_int_cst (NULL_TREE, shiftcnts[0]));
     }
 
   op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
   if (op != unknown_optab
-      && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
+      && can_implement_p (op, TYPE_MODE (type)))
     {
       tree_vector_builder vec (type, nunits, 1);
       for (i = 0; i < nunits; i++)
@@ -526,7 +526,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
 
   op = optab_for_tree_code (RSHIFT_EXPR, type, optab_vector);
   if (op == unknown_optab
-      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+      || !can_implement_p (op, TYPE_MODE (type)))
     has_vector_shift = false;
 
   /* Analysis phase.  Determine if all op1 elements are either power
@@ -758,7 +758,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
                 q = t1 >> shift;  */
              op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
              if (op != unknown_optab
-                 && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
+                 && can_implement_p (op, TYPE_MODE (type)))
                {
                  cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0, addend);
                  cur_op = add_rshift (gsi, type, cur_op, shifts);
@@ -778,7 +778,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
          mask = vec.build ();
          op = optab_for_tree_code (BIT_AND_EXPR, type, optab_default);
          if (op != unknown_optab
-             && optab_handler (op, TYPE_MODE (type)) != CODE_FOR_nothing)
+             && can_implement_p (op, TYPE_MODE (type)))
            {
              if (sign_p == UNSIGNED)
                /* r = op0 & mask;  */
@@ -790,8 +790,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
                     r = t2 - addend;  */
                  op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
                  if (op != unknown_optab
-                     && optab_handler (op, TYPE_MODE (type))
-                        != CODE_FOR_nothing)
+                     && can_implement_p (op, TYPE_MODE (type)))
                    {
                      cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, op0,
                                                addend);
@@ -800,8 +799,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
                      op = optab_for_tree_code (MINUS_EXPR, type,
                                                optab_default);
                      if (op != unknown_optab
-                         && optab_handler (op, TYPE_MODE (type))
-                            != CODE_FOR_nothing)
+                         && can_implement_p (op, TYPE_MODE (type)))
                        return gimplify_build2 (gsi, MINUS_EXPR, type,
                                                cur_op, addend);
                    }
@@ -872,13 +870,13 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree 
type, tree op0,
         q = t4 >> (post_shift - 1);  */
       op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
       if (op == unknown_optab
-         || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+         || !can_implement_p (op, TYPE_MODE (type)))
        return NULL_TREE;
       tem = gimplify_build2 (gsi, MINUS_EXPR, type, op0, cur_op);
       tem = add_rshift (gsi, type, tem, shift_temps);
       op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
       if (op == unknown_optab
-         || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+         || !can_implement_p (op, TYPE_MODE (type)))
        return NULL_TREE;
       tem = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, tem);
       cur_op = add_rshift (gsi, type, tem, post_shifts);
@@ -900,7 +898,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
        {
          op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
          if (op == unknown_optab
-             || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+             || !can_implement_p (op, TYPE_MODE (type)))
            return NULL_TREE;
          cur_op = gimplify_build2 (gsi, PLUS_EXPR, type, cur_op, op0);
        }
@@ -912,7 +910,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
        return NULL_TREE;
       op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
       if (op == unknown_optab
-         || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+         || !can_implement_p (op, TYPE_MODE (type)))
        return NULL_TREE;
       if ((mode & 1) == 0)
        cur_op = gimplify_build2 (gsi, MINUS_EXPR, type, cur_op, tem);
@@ -931,7 +929,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
      r = oprnd0 - t1;  */
   op = optab_for_tree_code (MULT_EXPR, type, optab_default);
   if (op == unknown_optab
-      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+      || !can_implement_p (op, TYPE_MODE (type)))
     return NULL_TREE;
   if (use_abs_op1)
     {
@@ -953,7 +951,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, 
tree op0,
   tem = gimplify_build2 (gsi, MULT_EXPR, type, cur_op, op1);
   op = optab_for_tree_code (MINUS_EXPR, type, optab_default);
   if (op == unknown_optab
-      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+      || !can_implement_p (op, TYPE_MODE (type)))
     return NULL_TREE;
   return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem);
 }
@@ -1192,7 +1190,7 @@ optimize_vector_constructor (gimple_stmt_iterator *gsi)
     return;
   op = optab_for_tree_code (PLUS_EXPR, type, optab_default);
   if (op == unknown_optab
-      || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+      || !can_implement_p (op, TYPE_MODE (type)))
     return;
   FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
     if (TREE_CODE (elt->value) != SSA_NAME
@@ -1281,7 +1279,7 @@ type_for_widest_vector_mode (tree original_vector_type, 
optab op)
   FOR_EACH_MODE_FROM (mode, mode)
     if (GET_MODE_INNER (mode) == inner_mode
        && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
-       && optab_handler (op, mode) != CODE_FOR_nothing
+       && can_implement_p (op, mode)
        && known_le (GET_MODE_NUNITS (mode),
                     TYPE_VECTOR_SUBPARTS (original_vector_type)))
       best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
@@ -1445,8 +1443,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
        }
       /* Also detect vec_shr pattern - VEC_PERM_EXPR with zero
         vector as VEC1 and a right element shift MASK.  */
-      if (optab_handler (vec_shr_optab, TYPE_MODE (vect_type))
-         != CODE_FOR_nothing
+      if (can_implement_p (vec_shr_optab, TYPE_MODE (vect_type))
          && TREE_CODE (vec1) == VECTOR_CST
          && initializer_zerop (vec1)
          && maybe_ne (indices[0], 0)
@@ -1475,8 +1472,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
            }
        }
       /* And similarly vec_shl pattern.  */
-      if (optab_handler (vec_shl_optab, TYPE_MODE (vect_type))
-         != CODE_FOR_nothing
+      if (can_implement_p (vec_shl_optab, TYPE_MODE (vect_type))
          && TREE_CODE (vec0) == VECTOR_CST
          && initializer_zerop (vec0))
        {
@@ -2078,7 +2074,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
     {
       op = optab_for_tree_code (code, TREE_TYPE (type), optab_scalar);
       if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
-         && optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != 
CODE_FOR_nothing)
+         && can_implement_p (op, TYPE_MODE (TREE_TYPE (type))))
        {
          tree stype = TREE_TYPE (TREE_TYPE (lhs));
          tree slhs = (rhs2 != NULL_TREE)
@@ -2220,12 +2216,9 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
              /* Verify all 3 operations can be performed in that type.  */
              if (compute_type != TREE_TYPE (type))
                {
-                 if (optab_handler (opl, TYPE_MODE (compute_type))
-                     == CODE_FOR_nothing
-                     || optab_handler (opr, TYPE_MODE (compute_type))
-                        == CODE_FOR_nothing
-                     || optab_handler (opo, TYPE_MODE (compute_type))
-                        == CODE_FOR_nothing)
+                 if (!can_implement_p (opl, TYPE_MODE (compute_type))
+                     || !can_implement_p (opr, TYPE_MODE (compute_type))
+                     || !can_implement_p (opo, TYPE_MODE (compute_type)))
                    compute_type = TREE_TYPE (type);
                }
            }
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index ce728143469d..bf4e35e56619 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -5286,7 +5286,7 @@ calc_vec_perm_mask_for_shift (unsigned int offset, 
unsigned int nelt,
 static bool
 have_whole_vector_shift (machine_mode mode)
 {
-  if (optab_handler (vec_shr_optab, mode) != CODE_FOR_nothing)
+  if (can_implement_p (vec_shr_optab, mode))
     return true;
 
   /* Variable-length vectors should be handled via the optab.  */
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index eb0e5808f7f9..b3b16ea23898 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -3830,7 +3830,7 @@ vect_recog_rotate_pattern (vec_info *vinfo,
      don't do anything here.  */
   optab1 = optab_for_tree_code (rhs_code, vectype, optab_vector);
   if (optab1
-      && optab_handler (optab1, TYPE_MODE (vectype)) != CODE_FOR_nothing)
+      && can_implement_p (optab1, TYPE_MODE (vectype)))
     {
      use_rotate:
       if (bswap16_p)
@@ -3862,7 +3862,7 @@ vect_recog_rotate_pattern (vec_info *vinfo,
     {
       optab2 = optab_for_tree_code (rhs_code, vectype, optab_scalar);
       if (optab2
-         && optab_handler (optab2, TYPE_MODE (vectype)) != CODE_FOR_nothing)
+         && can_implement_p (optab2, TYPE_MODE (vectype)))
        goto use_rotate;
     }
 
@@ -3876,18 +3876,18 @@ vect_recog_rotate_pattern (vec_info *vinfo,
   optab1 = optab_for_tree_code (LSHIFT_EXPR, uvectype, optab_vector);
   optab2 = optab_for_tree_code (RSHIFT_EXPR, uvectype, optab_vector);
   if (!optab1
-      || optab_handler (optab1, TYPE_MODE (uvectype)) == CODE_FOR_nothing
+      || !can_implement_p (optab1, TYPE_MODE (uvectype))
       || !optab2
-      || optab_handler (optab2, TYPE_MODE (uvectype)) == CODE_FOR_nothing)
+      || !can_implement_p (optab2, TYPE_MODE (uvectype)))
     {
       if (! is_a <bb_vec_info> (vinfo) && dt == vect_internal_def)
        return NULL;
       optab1 = optab_for_tree_code (LSHIFT_EXPR, uvectype, optab_scalar);
       optab2 = optab_for_tree_code (RSHIFT_EXPR, uvectype, optab_scalar);
       if (!optab1
-         || optab_handler (optab1, TYPE_MODE (uvectype)) == CODE_FOR_nothing
+         || !can_implement_p (optab1, TYPE_MODE (uvectype))
          || !optab2
-         || optab_handler (optab2, TYPE_MODE (uvectype)) == CODE_FOR_nothing)
+         || !can_implement_p (optab2, TYPE_MODE (uvectype)))
        return NULL;
     }
 
@@ -4127,7 +4127,7 @@ target_has_vecop_for_code (tree_code code, tree vectype)
 {
   optab voptab = optab_for_tree_code (code, vectype, optab_vector);
   return voptab
-        && optab_handler (voptab, TYPE_MODE (vectype)) != CODE_FOR_nothing;
+        && can_implement_p (voptab, TYPE_MODE (vectype));
 }
 
 /* Verify that the target has optabs of VECTYPE to perform all the steps
@@ -4466,13 +4466,9 @@ vect_recog_mult_pattern (vec_info *vinfo,
   /* If the target can handle vectorized multiplication natively,
      don't attempt to optimize this.  */
   optab mul_optab = optab_for_tree_code (MULT_EXPR, vectype, optab_default);
-  if (mul_optab != unknown_optab)
-    {
-      machine_mode vec_mode = TYPE_MODE (vectype);
-      int icode = (int) optab_handler (mul_optab, vec_mode);
-      if (icode != CODE_FOR_nothing)
-       return NULL;
-    }
+  if (mul_optab != unknown_optab
+      && can_implement_p (mul_optab, TYPE_MODE (vectype)))
+    return NULL;
 
   pattern_stmt = vect_synth_mult_by_constant (vinfo,
                                              oprnd0, oprnd1, stmt_vinfo);
@@ -4838,13 +4834,9 @@ vect_recog_divmod_pattern (vec_info *vinfo,
         don't attempt to optimize this, since native division is likely
         to give smaller code.  */
       optab = optab_for_tree_code (rhs_code, vectype, optab_default);
-      if (optab != unknown_optab)
-       {
-         machine_mode vec_mode = TYPE_MODE (vectype);
-         int icode = (int) optab_handler (optab, vec_mode);
-         if (icode != CODE_FOR_nothing)
-           return NULL;
-       }
+      if (optab != unknown_optab
+         && can_implement_p (optab, TYPE_MODE (vectype)))
+       return NULL;
     }
 
   prec = TYPE_PRECISION (itype);
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 8ff6f30a2d89..5f7e1e622a86 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -6213,10 +6213,7 @@ vectorizable_assignment (vec_info *vinfo,
 bool
 vect_supportable_shift (vec_info *vinfo, enum tree_code code, tree scalar_type)
 {
-
-  machine_mode vec_mode;
   optab optab;
-  int icode;
   tree vectype;
 
   vectype = get_vectype_for_scalar_type (vinfo, scalar_type);
@@ -6224,22 +6221,14 @@ vect_supportable_shift (vec_info *vinfo, enum tree_code 
code, tree scalar_type)
     return false;
 
   optab = optab_for_tree_code (code, vectype, optab_scalar);
-  if (!optab
-      || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing)
-    {
-      optab = optab_for_tree_code (code, vectype, optab_vector);
-      if (!optab
-          || (optab_handler (optab, TYPE_MODE (vectype))
-                      == CODE_FOR_nothing))
-        return false;
-    }
+  if (optab && can_implement_p (optab, TYPE_MODE (vectype)))
+    return true;
 
-  vec_mode = TYPE_MODE (vectype);
-  icode = (int) optab_handler (optab, vec_mode);
-  if (icode == CODE_FOR_nothing)
-    return false;
+  optab = optab_for_tree_code (code, vectype, optab_vector);
+  if (optab && can_implement_p (optab, TYPE_MODE (vectype)))
+    return true;
 
-  return true;
+  return false;
 }
 
 
@@ -6453,7 +6442,7 @@ vectorizable_shift (vec_info *vinfo,
     {
       optab = optab_for_tree_code (code, vectype, optab_scalar);
       if (optab
-          && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing)
+          && can_implement_p (optab, TYPE_MODE (vectype)))
         {
           if (dump_enabled_p ())
             dump_printf_loc (MSG_NOTE, vect_location,
@@ -6463,8 +6452,7 @@ vectorizable_shift (vec_info *vinfo,
         {
           optab = optab_for_tree_code (code, vectype, optab_vector);
           if (optab
-               && (optab_handler (optab, TYPE_MODE (vectype))
-                      != CODE_FOR_nothing))
+             && can_implement_p (optab, TYPE_MODE (vectype)))
             {
              scalar_shift_arg = false;
 
@@ -7545,7 +7533,7 @@ scan_store_can_perm_p (tree vectype, tree init,
 
          if (whole_vector_shift_kind == scan_store_kind_perm)
            {
-             if (optab_handler (vec_shl_optab, vec_mode) == CODE_FOR_nothing)
+             if (!can_implement_p (vec_shl_optab, vec_mode))
                return -1;
              whole_vector_shift_kind = scan_store_kind_lshift_zero;
              /* Whole vector shifts shift in zeros, so if init is all zero
@@ -7967,7 +7955,7 @@ check_scan_store (vec_info *vinfo, stmt_vec_info 
stmt_info, tree vectype,
        MEM <vector(8) int> [(int *)&D.2042] = _51;  */
   enum machine_mode vec_mode = TYPE_MODE (vectype);
   optab optab = optab_for_tree_code (code, vectype, optab_default);
-  if (!optab || optab_handler (optab, vec_mode) == CODE_FOR_nothing)
+  if (!optab || !can_implement_p (optab, vec_mode))
     goto fail;
 
   int units_log2 = scan_store_can_perm_p (vectype, *init);
@@ -8452,7 +8440,7 @@ vectorizable_store (vec_info *vinfo,
     {
       /* FORNOW. In some cases can vectorize even if data-type not supported
         (e.g. - array initialization with 0).  */
-      if (optab_handler (mov_optab, vec_mode) == CODE_FOR_nothing)
+      if (!can_implement_p (mov_optab, vec_mode))
        return false;
     }
 
@@ -10232,7 +10220,7 @@ vectorizable_load (vec_info *vinfo,
 
   /* FORNOW. In some cases can vectorize even if data-type not supported
     (e.g. - data copies).  */
-  if (optab_handler (mov_optab, mode) == CODE_FOR_nothing)
+  if (!can_implement_p (mov_optab, mode))
     {
       if (dump_enabled_p ())
         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -12694,14 +12682,14 @@ vectorizable_condition (vec_info *vinfo,
          optab optab;
 
          optab = optab_for_tree_code (bitop1, comp_vectype, optab_default);
-         if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
+         if (!optab || !can_implement_p (optab, mode))
            return false;
 
          if (bitop2 != NOP_EXPR)
            {
              optab = optab_for_tree_code (bitop2, comp_vectype,
                                           optab_default);
-             if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
+             if (!optab || !can_implement_p (optab, mode))
                return false;
            }
        }
@@ -13169,13 +13157,13 @@ vectorizable_comparison_1 (vec_info *vinfo, tree 
vectype,
          optab optab;
 
          optab = optab_for_tree_code (bitop1, vectype, optab_default);
-         if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
+         if (!optab || !can_implement_p (optab, mode))
            return false;
 
          if (bitop2 != NOP_EXPR)
            {
              optab = optab_for_tree_code (bitop2, vectype, optab_default);
-             if (!optab || optab_handler (optab, mode) == CODE_FOR_nothing)
+             if (!optab || !can_implement_p (optab, mode))
                return false;
            }
        }

Reply via email to