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.
This commit is contained in:
Richard Sandiford 2024-11-20 10:04:45 +00:00
parent 485ab50c20
commit 0abb5fa523
5 changed files with 52 additions and 79 deletions

View File

@ -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 ()))
{

View File

@ -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);
}
}

View File

@ -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. */

View File

@ -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);

View File

@ -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;
}
}