From 0abb5fa523bcc72ec0891813d778b6b47c305f97 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 20 Nov 2024 10:04:45 +0000 Subject: [PATCH] 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. --- 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 3ea5fb883b1..a32343c0022 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 b68355ed8b9..b40e3d74579 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 ce728143469..bf4e35e5661 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 eb0e5808f7f..b3b16ea2389 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 (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 8ff6f30a2d8..5f7e1e622a8 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 [(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; } }