The following removes the STMT_VINFO_VECTYPE usage from vect_check_gather_scatter and instead gets the vector type passed in from the caller. For the two early callers, the one from dataref analysis and the one from vect_mark_stmts_to_be_vectorized we add a mode that works with a NULL vector type - this mode is intended to look for a base/offset pair that's suitable for processing, meaning an invariant base and a SSA offset, but without influencing this discovery by target capabilities (as if forced to do emulation). This is to allow, in the next step, to elide setting STMT_VINFO_VECTYPE during dataref analysis.
* tree-vectorizer.h (vect_check_gather_scatter): Add vectype argument. * tree-vect-data-refs.cc (vect_check_gather_scatter): Get vectype as argument, do early processing when NULL. (vect_describe_gather_scatter_call): Likewise. (vect_analyze_data_refs): Do not perform vectype specific analysis on gather/scatter refs. * tree-vect-patterns.cc (vect_recog_gather_scatter_pattern): Use the data element vector type to perform gather/scatter analysis. * tree-vect-slp.cc (vect_get_and_check_slp_defs): Get the vector type as argument and pass it along. (vect_build_slp_tree_2): Adjust. (vect_detect_hybrid_slp): Use the basic analysis from vect_check_gather_scatter. * tree-vect-stmts.cc (vect_mark_stmts_to_be_vectorized): Likewise. (vect_use_strided_gather_scatters_p): Get vectype and pass along. (get_group_load_store_type): Pass down vectype. --- gcc/tree-vect-data-refs.cc | 46 ++++++++++++++++++++++---------------- gcc/tree-vect-patterns.cc | 9 +++++--- gcc/tree-vect-slp.cc | 8 +++---- gcc/tree-vect-stmts.cc | 12 +++++----- gcc/tree-vectorizer.h | 2 +- 5 files changed, 45 insertions(+), 32 deletions(-) diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc index 0601d592ca3..b62498b34bd 100644 --- a/gcc/tree-vect-data-refs.cc +++ b/gcc/tree-vect-data-refs.cc @@ -4535,10 +4535,10 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p, static void vect_describe_gather_scatter_call (stmt_vec_info stmt_info, + tree vectype, gather_scatter_info *info) { gcall *call = as_a <gcall *> (stmt_info->stmt); - tree vectype = STMT_VINFO_VECTYPE (stmt_info); data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); info->ifn = gimple_call_internal_fn (call); @@ -4548,17 +4548,20 @@ vect_describe_gather_scatter_call (stmt_vec_info stmt_info, info->offset_dt = vect_unknown_def_type; info->offset_vectype = NULL_TREE; info->scale = TREE_INT_CST_LOW (gimple_call_arg (call, 2)); - info->element_type = TREE_TYPE (vectype); + info->element_type = vectype ? TREE_TYPE (vectype) : NULL_TREE; info->memory_type = TREE_TYPE (DR_REF (dr)); } /* Return true if a non-affine read or write in STMT_INFO is suitable for a - gather load or scatter store. Describe the operation in *INFO if so. + gather load or scatter store. Describe the operation in *INFO if so, + when INFO is NULL only ensure there's a loop invariant base and a loop + variant offset. If it is suitable and ELSVALS is nonzero store the supported else values in the vector it points to. */ bool -vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, +vect_check_gather_scatter (stmt_vec_info stmt_info, tree vectype, + loop_vec_info loop_vinfo, gather_scatter_info *info, vec<int> *elsvals) { HOST_WIDE_INT scale = 1; @@ -4567,7 +4570,6 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info); tree offtype = NULL_TREE; tree decl = NULL_TREE, base, off; - tree vectype = STMT_VINFO_VECTYPE (stmt_info); tree memory_type = TREE_TYPE (DR_REF (dr)); machine_mode pmode; int punsignedp, reversep, pvolatilep = 0; @@ -4583,7 +4585,7 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, ifn = gimple_call_internal_fn (call); if (internal_gather_scatter_fn_p (ifn)) { - vect_describe_gather_scatter_call (stmt_info, info); + vect_describe_gather_scatter_call (stmt_info, vectype, info); /* In pattern recog we simply used a ZERO else value that we need to correct here. To that end just re-use the @@ -4605,10 +4607,11 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, /* True if we should aim to use internal functions rather than built-in functions. */ - bool use_ifn_p = (DR_IS_READ (dr) - ? supports_vec_gather_load_p (TYPE_MODE (vectype), - elsvals) - : supports_vec_scatter_store_p (TYPE_MODE (vectype))); + bool use_ifn_p = false; + if (vectype) + use_ifn_p = (DR_IS_READ (dr) + ? supports_vec_gather_load_p (TYPE_MODE (vectype), elsvals) + : supports_vec_scatter_store_p (TYPE_MODE (vectype))); base = DR_REF (dr); /* For masked loads/stores, DR_REF (dr) is an artificial MEM_REF, @@ -4708,7 +4711,7 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, if (expr_invariant_in_loop_p (loop, off)) return false; - if (gimple_code (def_stmt) != GIMPLE_ASSIGN) + if (!vectype || gimple_code (def_stmt) != GIMPLE_ASSIGN) break; op0 = gimple_assign_rhs1 (def_stmt); @@ -4759,7 +4762,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, int new_scale = tree_to_shwi (op1); /* Only treat this as a scaling operation if the target supports it for at least some offset type. */ - if (use_ifn_p + if (TREE_CODE (op0) == SSA_NAME + && use_ifn_p && !vect_gather_scatter_fn_p (loop_vinfo, DR_IS_READ (dr), masked_p, vectype, memory_type, signed_char_type_node, @@ -4810,7 +4814,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, data vector element size. */ if ((TYPE_PRECISION (TREE_TYPE (op0)) < TYPE_PRECISION (TREE_TYPE (off))) - && (use_ifn_p + && (TREE_CODE (off) != SSA_NAME + || use_ifn_p || (DR_IS_READ (dr) ? (targetm.vectorize.builtin_gather && targetm.vectorize.builtin_gather (vectype, @@ -4844,7 +4849,12 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, if (offtype == NULL_TREE) offtype = TREE_TYPE (off); - if (use_ifn_p) + if (! vectype) + { + ifn = IFN_LAST; + decl = NULL_TREE; + } + else if (use_ifn_p) { if (!vect_gather_scatter_fn_p (loop_vinfo, DR_IS_READ (dr), masked_p, vectype, memory_type, offtype, scale, @@ -4876,7 +4886,7 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo, info->offset_dt = vect_unknown_def_type; info->offset_vectype = offset_vectype; info->scale = scale; - info->element_type = TREE_TYPE (vectype); + info->element_type = vectype ? TREE_TYPE (vectype) : NULL_TREE; info->memory_type = memory_type; return true; } @@ -5279,11 +5289,9 @@ vect_analyze_data_refs (vec_info *vinfo, bool *fatal) if (gatherscatter != SG_NONE) { gather_scatter_info gs_info; - if (!vect_check_gather_scatter (stmt_info, + if (!vect_check_gather_scatter (stmt_info, NULL, as_a <loop_vec_info> (vinfo), - &gs_info) - || !get_vectype_for_scalar_type (vinfo, - TREE_TYPE (gs_info.offset))) + &gs_info)) { if (fatal) *fatal = false; diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 0f6d6b77ea1..340c36c73f2 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -6003,16 +6003,19 @@ vect_recog_gather_scatter_pattern (vec_info *vinfo, This is null if the operation is unconditional. */ tree mask = vect_get_load_store_mask (stmt_info); + tree gs_vectype = get_vectype_for_scalar_type (loop_vinfo, + TREE_TYPE (DR_REF (dr))); + /* Make sure that the target supports an appropriate internal function for the gather/scatter operation. */ gather_scatter_info gs_info; - if (!vect_check_gather_scatter (stmt_info, loop_vinfo, &gs_info) + if (!gs_vectype + || !vect_check_gather_scatter (stmt_info, gs_vectype, loop_vinfo, + &gs_info) || gs_info.ifn == IFN_LAST) return NULL; /* Convert the mask to the right form. */ - tree gs_vectype = get_vectype_for_scalar_type (loop_vinfo, - gs_info.element_type); if (mask) mask = vect_convert_mask_for_vectype (mask, gs_vectype, stmt_info, loop_vinfo); diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index 5f414790354..826b0f341dc 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -636,7 +636,7 @@ vect_slp_child_index_for_operand (const gimple *stmt, int op, swapping operands of father node of this one, return 1; if everything is ok return 0. */ static int -vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap, +vect_get_and_check_slp_defs (vec_info *vinfo, tree vectype, unsigned char swap, bool *skip_args, vec<stmt_vec_info> stmts, unsigned stmt_num, vec<slp_oprnd_info> *oprnds_info) @@ -697,7 +697,7 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap, { gcc_assert (STMT_VINFO_GATHER_SCATTER_P (stmt_info)); if (!is_a <loop_vec_info> (vinfo) - || !vect_check_gather_scatter (stmt_info, + || !vect_check_gather_scatter (stmt_info, vectype, as_a <loop_vec_info> (vinfo), first ? &oprnd_info->first_gs_info : &gs_info)) @@ -2604,7 +2604,7 @@ out: slp_oprnd_info oprnd_info; FOR_EACH_VEC_ELT (stmts, i, stmt_info) { - int res = vect_get_and_check_slp_defs (vinfo, swap[i], skip_args, + int res = vect_get_and_check_slp_defs (vinfo, vectype, swap[i], skip_args, stmts, i, &oprnds_info); if (res != 0) matches[(res == -1) ? 0 : i] = false; @@ -7817,7 +7817,7 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo) can be a scaling and conversion away. */ gather_scatter_info gs_info; if (STMT_VINFO_GATHER_SCATTER_P (stmt_info) - && vect_check_gather_scatter (stmt_info, loop_vinfo, &gs_info)) + && vect_check_gather_scatter (stmt_info, NULL, loop_vinfo, &gs_info)) { int dummy; vect_detect_hybrid_slp (&gs_info.offset, &dummy, &wi); diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index 26913481e25..0b5e5af7992 100644 --- a/gcc/tree-vect-stmts.cc +++ b/gcc/tree-vect-stmts.cc @@ -884,7 +884,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo, bool *fatal) if (STMT_VINFO_GATHER_SCATTER_P (stmt_vinfo)) { gather_scatter_info gs_info; - if (!vect_check_gather_scatter (stmt_vinfo, loop_vinfo, &gs_info)) + if (!vect_check_gather_scatter (stmt_vinfo, NULL, + loop_vinfo, &gs_info)) gcc_unreachable (); opt_result res = process_use (stmt_vinfo, gs_info.offset, loop_vinfo, relevant, @@ -1831,12 +1832,13 @@ vect_truncate_gather_scatter_offset (stmt_vec_info stmt_info, else values will be stored in the vector ELSVALS points to. */ static bool -vect_use_strided_gather_scatters_p (stmt_vec_info stmt_info, +vect_use_strided_gather_scatters_p (stmt_vec_info stmt_info, tree vectype, loop_vec_info loop_vinfo, bool masked_p, gather_scatter_info *gs_info, vec<int> *elsvals) { - if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info, elsvals) + if (!vect_check_gather_scatter (stmt_info, vectype, loop_vinfo, + gs_info, elsvals) || gs_info->ifn == IFN_LAST) return vect_truncate_gather_scatter_offset (stmt_info, loop_vinfo, masked_p, gs_info, elsvals); @@ -2354,7 +2356,7 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, && single_element_p && SLP_TREE_LANES (slp_node) == 1 && loop_vinfo - && vect_use_strided_gather_scatters_p (stmt_info, loop_vinfo, + && vect_use_strided_gather_scatters_p (stmt_info, vectype, loop_vinfo, masked_p, gs_info, elsvals)) *memory_access_type = VMAT_GATHER_SCATTER; @@ -2448,7 +2450,7 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info, if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)) { *memory_access_type = VMAT_GATHER_SCATTER; - if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info, + if (!vect_check_gather_scatter (stmt_info, vectype, loop_vinfo, gs_info, elsvals)) gcc_unreachable (); /* When using internal functions, we rely on pattern recognition diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index e15b0492791..ddf31e7b0ee 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -2541,7 +2541,7 @@ extern opt_result vect_prune_runtime_alias_test_list (loop_vec_info); extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree, tree, int, internal_fn *, tree *, vec<int> * = nullptr); -extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info, +extern bool vect_check_gather_scatter (stmt_vec_info, tree, loop_vec_info, gather_scatter_info *, vec<int> * = nullptr); extern opt_result vect_find_stmt_data_reference (loop_p, gimple *, -- 2.43.0