Commit 3bab6342 by Andrey Turetskiy Committed by Kirill Yukhin

tm.texi.in (TARGET_VECTORIZE_BUILTIN_SCATTER): New.


gcc/
	* doc/tm.texi.in (TARGET_VECTORIZE_BUILTIN_SCATTER): New.
	* doc/tm.texi: Regenerate.
	* target.def: Add scatter builtin.
	* tree-vectorizer.h: Rename gather_p to gather_scatter_p and use it
	for loads/stores in case of gather/scatter accordingly.
	(STMT_VINFO_GATHER_SCATTER_P(S)): Use it instead of STMT_VINFO_GATHER_P(S).
	(vect_check_gather): Rename to ...
	(vect_check_gather_scatter): this.
	* tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Use
	STMT_VINFO_GATHER_SCATTER_P instead of STMT_VINFO_SCATTER_P.
	(vect_check_gather_scatter): Use it instead of vect_check_gather.
	(vect_analyze_data_refs): Add gatherscatter enum and maybe_scatter variable
	and new checkings for it accordingly.
	* tree-vect-stmts.c
	(STMT_VINFO_GATHER_SCATTER_P(S)): Use it instead of STMT_VINFO_GATHER_P(S).
	(vect_check_gather_scatter): Use it instead of vect_check_gather.
	(vectorizable_store): Add checkings for STMT_VINFO_GATHER_SCATTER_P.

Co-Authored-By: Kirill Yukhin <kirill.yukhin@intel.com>
Co-Authored-By: Petr Murzin <petr.murzin@intel.com>

From-SVN: r227481
parent 301c092c
2015-09-04 Andrey Turetskiy <andrey.turetskiy@intel.com>
Petr Murzin <petr.murzin@intel.com>
Kirill Yukhin <kirill.yukhin@intel.com>
* doc/tm.texi.in (TARGET_VECTORIZE_BUILTIN_SCATTER): New.
* doc/tm.texi: Regenerate.
* target.def: Add scatter builtin.
* tree-vectorizer.h: Rename gather_p to gather_scatter_p and use it
for loads/stores in case of gather/scatter accordingly.
(STMT_VINFO_GATHER_SCATTER_P(S)): Use it instead of STMT_VINFO_GATHER_P(S).
(vect_check_gather): Rename to ...
(vect_check_gather_scatter): this.
* tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Use
STMT_VINFO_GATHER_SCATTER_P instead of STMT_VINFO_SCATTER_P.
(vect_check_gather_scatter): Use it instead of vect_check_gather.
(vect_analyze_data_refs): Add gatherscatter enum and maybe_scatter variable
and new checkings for it accordingly.
* tree-vect-stmts.c
(STMT_VINFO_GATHER_SCATTER_P(S)): Use it instead of STMT_VINFO_GATHER_P(S).
(vect_check_gather_scatter): Use it instead of vect_check_gather.
(vectorizable_store): Add checkings for STMT_VINFO_GATHER_SCATTER_P.
2015-09-03 Bill Schmidt <wschmidt@vnet.linux.ibm.com> 2015-09-03 Bill Schmidt <wschmidt@vnet.linux.ibm.com>
* config/rs6000/altivec.md (altivec_vperm_v8hiv16qi): New * config/rs6000/altivec.md (altivec_vperm_v8hiv16qi): New
......
...@@ -5720,6 +5720,14 @@ The default is @code{NULL_TREE} which means to not vectorize gather ...@@ -5720,6 +5720,14 @@ The default is @code{NULL_TREE} which means to not vectorize gather
loads. loads.
@end deftypefn @end deftypefn
@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_SCATTER (const_tree @var{vectype}, const_tree @var{index_type}, int @var{scale})
Target builtin that implements vector scatter operation. @var{vectype}
is the vector type of the store and @var{index_type} is scalar type of
the index, scaled by @var{scale}.
The default is @code{NULL_TREE} which means to not vectorize scatter
stores.
@end deftypefn
@deftypefn {Target Hook} int TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN (struct cgraph_node *@var{}, struct cgraph_simd_clone *@var{}, @var{tree}, @var{int}) @deftypefn {Target Hook} int TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN (struct cgraph_node *@var{}, struct cgraph_simd_clone *@var{}, @var{tree}, @var{int})
This hook should set @var{vecsize_mangle}, @var{vecsize_int}, @var{vecsize_float} This hook should set @var{vecsize_mangle}, @var{vecsize_int}, @var{vecsize_float}
fields in @var{simd_clone} structure pointed by @var{clone_info} argument and also fields in @var{simd_clone} structure pointed by @var{clone_info} argument and also
......
...@@ -4239,6 +4239,8 @@ address; but often a machine-dependent strategy can generate better code. ...@@ -4239,6 +4239,8 @@ address; but often a machine-dependent strategy can generate better code.
@hook TARGET_VECTORIZE_BUILTIN_GATHER @hook TARGET_VECTORIZE_BUILTIN_GATHER
@hook TARGET_VECTORIZE_BUILTIN_SCATTER
@hook TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN @hook TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN
@hook TARGET_SIMD_CLONE_ADJUST @hook TARGET_SIMD_CLONE_ADJUST
......
...@@ -1801,6 +1801,18 @@ loads.", ...@@ -1801,6 +1801,18 @@ loads.",
(const_tree mem_vectype, const_tree index_type, int scale), (const_tree mem_vectype, const_tree index_type, int scale),
NULL) NULL)
/* Target builtin that implements vector scatter operation. */
DEFHOOK
(builtin_scatter,
"Target builtin that implements vector scatter operation. @var{vectype}\n\
is the vector type of the store and @var{index_type} is scalar type of\n\
the index, scaled by @var{scale}.\n\
The default is @code{NULL_TREE} which means to not vectorize scatter\n\
stores.",
tree,
(const_tree vectype, const_tree index_type, int scale),
NULL)
/* Target function to initialize the cost model for a loop or block. */ /* Target function to initialize the cost model for a loop or block. */
DEFHOOK DEFHOOK
(init_cost, (init_cost,
......
...@@ -267,8 +267,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, ...@@ -267,8 +267,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
return false; return false;
} }
if (STMT_VINFO_GATHER_P (stmtinfo_a) if (STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a)
|| STMT_VINFO_GATHER_P (stmtinfo_b)) || STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b))
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {
...@@ -315,8 +315,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, ...@@ -315,8 +315,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
return false; return false;
} }
if (STMT_VINFO_GATHER_P (stmtinfo_a) if (STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a)
|| STMT_VINFO_GATHER_P (stmtinfo_b)) || STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b))
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {
...@@ -2344,10 +2344,7 @@ vect_analyze_data_ref_access (struct data_reference *dr) ...@@ -2344,10 +2344,7 @@ vect_analyze_data_ref_access (struct data_reference *dr)
if (dump_enabled_p ()) if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, dump_printf_loc (MSG_NOTE, vect_location,
"zero step in outer loop.\n"); "zero step in outer loop.\n");
if (DR_IS_READ (dr)) return DR_IS_READ (dr);
return true;
else
return false;
} }
} }
...@@ -2997,12 +2994,12 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) ...@@ -2997,12 +2994,12 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
return true; return true;
} }
/* Check whether a non-affine read in stmt is suitable for gather load /* Check whether a non-affine read or write in stmt is suitable for gather load
and if so, return a builtin decl for that operation. */ or scatter store and if so, return a builtin decl for that operation. */
tree tree
vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep, vect_check_gather_scatter (gimple stmt, loop_vec_info loop_vinfo, tree *basep,
tree *offp, int *scalep) tree *offp, int *scalep)
{ {
HOST_WIDE_INT scale = 1, pbitpos, pbitsize; HOST_WIDE_INT scale = 1, pbitpos, pbitsize;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
...@@ -3031,7 +3028,7 @@ vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep, ...@@ -3031,7 +3028,7 @@ vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep,
base = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0); base = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0);
} }
/* The gather builtins need address of the form /* The gather and scatter builtins need address of the form
loop_invariant + vector * {1, 2, 4, 8} loop_invariant + vector * {1, 2, 4, 8}
or or
loop_invariant + sign_extend (vector) * { 1, 2, 4, 8 }. loop_invariant + sign_extend (vector) * { 1, 2, 4, 8 }.
...@@ -3194,8 +3191,13 @@ vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep, ...@@ -3194,8 +3191,13 @@ vect_check_gather (gimple stmt, loop_vec_info loop_vinfo, tree *basep,
if (offtype == NULL_TREE) if (offtype == NULL_TREE)
offtype = TREE_TYPE (off); offtype = TREE_TYPE (off);
decl = targetm.vectorize.builtin_gather (STMT_VINFO_VECTYPE (stmt_info), if (DR_IS_READ (dr))
offtype, scale); decl = targetm.vectorize.builtin_gather (STMT_VINFO_VECTYPE (stmt_info),
offtype, scale);
else
decl = targetm.vectorize.builtin_scatter (STMT_VINFO_VECTYPE (stmt_info),
offtype, scale);
if (decl == NULL_TREE) if (decl == NULL_TREE)
return NULL_TREE; return NULL_TREE;
...@@ -3344,7 +3346,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo, ...@@ -3344,7 +3346,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
gimple stmt; gimple stmt;
stmt_vec_info stmt_info; stmt_vec_info stmt_info;
tree base, offset, init; tree base, offset, init;
bool gather = false; enum { SG_NONE, GATHER, SCATTER } gatherscatter = SG_NONE;
bool simd_lane_access = false; bool simd_lane_access = false;
int vf; int vf;
...@@ -3383,18 +3385,22 @@ again: ...@@ -3383,18 +3385,22 @@ again:
= DR_IS_READ (dr) = DR_IS_READ (dr)
&& !TREE_THIS_VOLATILE (DR_REF (dr)) && !TREE_THIS_VOLATILE (DR_REF (dr))
&& targetm.vectorize.builtin_gather != NULL; && targetm.vectorize.builtin_gather != NULL;
bool maybe_scatter
= DR_IS_WRITE (dr)
&& !TREE_THIS_VOLATILE (DR_REF (dr))
&& targetm.vectorize.builtin_scatter != NULL;
bool maybe_simd_lane_access bool maybe_simd_lane_access
= loop_vinfo && loop->simduid; = loop_vinfo && loop->simduid;
/* If target supports vector gather loads, or if this might be /* If target supports vector gather loads or scatter stores, or if
a SIMD lane access, see if they can't be used. */ this might be a SIMD lane access, see if they can't be used. */
if (loop_vinfo if (loop_vinfo
&& (maybe_gather || maybe_simd_lane_access) && (maybe_gather || maybe_scatter || maybe_simd_lane_access)
&& !nested_in_vect_loop_p (loop, stmt)) && !nested_in_vect_loop_p (loop, stmt))
{ {
struct data_reference *newdr struct data_reference *newdr
= create_data_ref (NULL, loop_containing_stmt (stmt), = create_data_ref (NULL, loop_containing_stmt (stmt),
DR_REF (dr), stmt, true); DR_REF (dr), stmt, maybe_scatter ? false : true);
gcc_assert (newdr != NULL && DR_REF (newdr)); gcc_assert (newdr != NULL && DR_REF (newdr));
if (DR_BASE_ADDRESS (newdr) if (DR_BASE_ADDRESS (newdr)
&& DR_OFFSET (newdr) && DR_OFFSET (newdr)
...@@ -3447,17 +3453,20 @@ again: ...@@ -3447,17 +3453,20 @@ again:
} }
} }
} }
if (!simd_lane_access && maybe_gather) if (!simd_lane_access && (maybe_gather || maybe_scatter))
{ {
dr = newdr; dr = newdr;
gather = true; if (maybe_gather)
gatherscatter = GATHER;
else
gatherscatter = SCATTER;
} }
} }
if (!gather && !simd_lane_access) if (gatherscatter == SG_NONE && !simd_lane_access)
free_data_ref (newdr); free_data_ref (newdr);
} }
if (!gather && !simd_lane_access) if (gatherscatter == SG_NONE && !simd_lane_access)
{ {
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {
...@@ -3485,7 +3494,7 @@ again: ...@@ -3485,7 +3494,7 @@ again:
if (bb_vinfo) if (bb_vinfo)
break; break;
if (gather || simd_lane_access) if (gatherscatter != SG_NONE || simd_lane_access)
free_data_ref (dr); free_data_ref (dr);
return false; return false;
} }
...@@ -3520,7 +3529,7 @@ again: ...@@ -3520,7 +3529,7 @@ again:
if (bb_vinfo) if (bb_vinfo)
break; break;
if (gather || simd_lane_access) if (gatherscatter != SG_NONE || simd_lane_access)
free_data_ref (dr); free_data_ref (dr);
return false; return false;
} }
...@@ -3540,7 +3549,7 @@ again: ...@@ -3540,7 +3549,7 @@ again:
if (bb_vinfo) if (bb_vinfo)
break; break;
if (gather || simd_lane_access) if (gatherscatter != SG_NONE || simd_lane_access)
free_data_ref (dr); free_data_ref (dr);
return false; return false;
} }
...@@ -3565,7 +3574,7 @@ again: ...@@ -3565,7 +3574,7 @@ again:
if (bb_vinfo) if (bb_vinfo)
break; break;
if (gather || simd_lane_access) if (gatherscatter != SG_NONE || simd_lane_access)
free_data_ref (dr); free_data_ref (dr);
return false; return false;
} }
...@@ -3703,7 +3712,7 @@ again: ...@@ -3703,7 +3712,7 @@ again:
if (bb_vinfo) if (bb_vinfo)
break; break;
if (gather || simd_lane_access) if (gatherscatter != SG_NONE || simd_lane_access)
free_data_ref (dr); free_data_ref (dr);
return false; return false;
} }
...@@ -3736,10 +3745,10 @@ again: ...@@ -3736,10 +3745,10 @@ again:
if (bb_vinfo) if (bb_vinfo)
break; break;
if (gather || simd_lane_access) if (gatherscatter != SG_NONE || simd_lane_access)
{ {
STMT_VINFO_DATA_REF (stmt_info) = NULL; STMT_VINFO_DATA_REF (stmt_info) = NULL;
if (gather) if (gatherscatter != SG_NONE)
free_data_ref (dr); free_data_ref (dr);
} }
return false; return false;
...@@ -3763,23 +3772,22 @@ again: ...@@ -3763,23 +3772,22 @@ again:
if (vf > *min_vf) if (vf > *min_vf)
*min_vf = vf; *min_vf = vf;
if (gather) if (gatherscatter != SG_NONE)
{ {
tree off; tree off;
if (!vect_check_gather_scatter (stmt, loop_vinfo, NULL, &off, NULL)
gather = 0 != vect_check_gather (stmt, loop_vinfo, NULL, &off, NULL); || get_vectype_for_scalar_type (TREE_TYPE (off)) == NULL_TREE)
if (gather
&& get_vectype_for_scalar_type (TREE_TYPE (off)) == NULL_TREE)
gather = false;
if (!gather)
{ {
STMT_VINFO_DATA_REF (stmt_info) = NULL; STMT_VINFO_DATA_REF (stmt_info) = NULL;
free_data_ref (dr); free_data_ref (dr);
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"not vectorized: not suitable for gather " (gatherscatter == GATHER) ?
"load "); "not vectorized: not suitable for gather "
"load " :
"not vectorized: not suitable for scatter "
"store ");
dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0); dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); dump_printf (MSG_MISSED_OPTIMIZATION, "\n");
} }
...@@ -3787,8 +3795,9 @@ again: ...@@ -3787,8 +3795,9 @@ again:
} }
datarefs[i] = dr; datarefs[i] = dr;
STMT_VINFO_GATHER_P (stmt_info) = true; STMT_VINFO_GATHER_SCATTER_P (stmt_info) = gatherscatter;
} }
else if (loop_vinfo else if (loop_vinfo
&& TREE_CODE (DR_STEP (dr)) != INTEGER_CST) && TREE_CODE (DR_STEP (dr)) != INTEGER_CST)
{ {
......
...@@ -810,10 +810,10 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) ...@@ -810,10 +810,10 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
return false; return false;
} }
if (STMT_VINFO_GATHER_P (stmt_vinfo)) if (STMT_VINFO_GATHER_SCATTER_P (stmt_vinfo))
{ {
tree off; tree off;
tree decl = vect_check_gather (stmt, loop_vinfo, NULL, &off, NULL); tree decl = vect_check_gather_scatter (stmt, loop_vinfo, NULL, &off, NULL);
gcc_assert (decl); gcc_assert (decl);
if (!process_use (stmt, off, loop_vinfo, live_p, relevant, if (!process_use (stmt, off, loop_vinfo, live_p, relevant,
&worklist, true)) &worklist, true))
...@@ -1815,11 +1815,11 @@ vectorizable_mask_load_store (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -1815,11 +1815,11 @@ vectorizable_mask_load_store (gimple stmt, gimple_stmt_iterator *gsi,
if (STMT_VINFO_STRIDED_P (stmt_info)) if (STMT_VINFO_STRIDED_P (stmt_info))
return false; return false;
if (STMT_VINFO_GATHER_P (stmt_info)) if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{ {
gimple def_stmt; gimple def_stmt;
tree def; tree def;
gather_decl = vect_check_gather (stmt, loop_vinfo, &gather_base, gather_decl = vect_check_gather_scatter (stmt, loop_vinfo, &gather_base,
&gather_off, &gather_scale); &gather_off, &gather_scale);
gcc_assert (gather_decl); gcc_assert (gather_decl);
if (!vect_is_simple_use_1 (gather_off, NULL, loop_vinfo, NULL, if (!vect_is_simple_use_1 (gather_off, NULL, loop_vinfo, NULL,
...@@ -1879,7 +1879,7 @@ vectorizable_mask_load_store (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -1879,7 +1879,7 @@ vectorizable_mask_load_store (gimple stmt, gimple_stmt_iterator *gsi,
/** Transform. **/ /** Transform. **/
if (STMT_VINFO_GATHER_P (stmt_info)) if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{ {
tree vec_oprnd0 = NULL_TREE, op; tree vec_oprnd0 = NULL_TREE, op;
tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gather_decl)); tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gather_decl));
...@@ -5140,6 +5140,12 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -5140,6 +5140,12 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
unsigned int vec_num; unsigned int vec_num;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info); bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
tree aggr_type; tree aggr_type;
tree scatter_base = NULL_TREE, scatter_off = NULL_TREE;
tree scatter_off_vectype = NULL_TREE, scatter_decl = NULL_TREE;
int scatter_scale = 1;
enum vect_def_type scatter_idx_dt = vect_unknown_def_type;
enum vect_def_type scatter_src_dt = vect_unknown_def_type;
gimple new_stmt;
if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo) if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false; return false;
...@@ -5297,6 +5303,24 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -5297,6 +5303,24 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
} }
} }
if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
gimple def_stmt;
tree def;
scatter_decl = vect_check_gather_scatter (stmt, loop_vinfo, &scatter_base,
&scatter_off, &scatter_scale);
gcc_assert (scatter_decl);
if (!vect_is_simple_use_1 (scatter_off, NULL, loop_vinfo, bb_vinfo,
&def_stmt, &def, &scatter_idx_dt,
&scatter_off_vectype))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"scatter index use not simple.");
return false;
}
}
if (!vec_stmt) /* transformation not required. */ if (!vec_stmt) /* transformation not required. */
{ {
STMT_VINFO_TYPE (stmt_info) = store_vec_info_type; STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
...@@ -5311,6 +5335,146 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -5311,6 +5335,146 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
ensure_base_align (stmt_info, dr); ensure_base_align (stmt_info, dr);
if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
tree vec_oprnd0 = NULL_TREE, vec_oprnd1 = NULL_TREE, op, src;
tree arglist = TYPE_ARG_TYPES (TREE_TYPE (scatter_decl));
tree rettype, srctype, ptrtype, idxtype, masktype, scaletype;
tree ptr, mask, var, scale, perm_mask = NULL_TREE;
edge pe = loop_preheader_edge (loop);
gimple_seq seq;
basic_block new_bb;
enum { NARROW, NONE, WIDEN } modifier;
int scatter_off_nunits = TYPE_VECTOR_SUBPARTS (scatter_off_vectype);
if (nunits == (unsigned int) scatter_off_nunits)
modifier = NONE;
else if (nunits == (unsigned int) scatter_off_nunits / 2)
{
unsigned char *sel = XALLOCAVEC (unsigned char, scatter_off_nunits);
modifier = WIDEN;
for (i = 0; i < (unsigned int) scatter_off_nunits; ++i)
sel[i] = i | nunits;
perm_mask = vect_gen_perm_mask_checked (scatter_off_vectype, sel);
gcc_assert (perm_mask != NULL_TREE);
}
else if (nunits == (unsigned int) scatter_off_nunits * 2)
{
unsigned char *sel = XALLOCAVEC (unsigned char, nunits);
modifier = NARROW;
for (i = 0; i < (unsigned int) nunits; ++i)
sel[i] = i | scatter_off_nunits;
perm_mask = vect_gen_perm_mask_checked (vectype, sel);
gcc_assert (perm_mask != NULL_TREE);
ncopies *= 2;
}
else
gcc_unreachable ();
rettype = TREE_TYPE (TREE_TYPE (scatter_decl));
ptrtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
masktype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
idxtype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
srctype = TREE_VALUE (arglist); arglist = TREE_CHAIN (arglist);
scaletype = TREE_VALUE (arglist);
gcc_checking_assert (TREE_CODE (masktype) == INTEGER_TYPE
&& TREE_CODE (rettype) == VOID_TYPE);
ptr = fold_convert (ptrtype, scatter_base);
if (!is_gimple_min_invariant (ptr))
{
ptr = force_gimple_operand (ptr, &seq, true, NULL_TREE);
new_bb = gsi_insert_seq_on_edge_immediate (pe, seq);
gcc_assert (!new_bb);
}
/* Currently we support only unconditional scatter stores,
so mask should be all ones. */
mask = build_int_cst (masktype, -1);
mask = vect_init_vector (stmt, mask, masktype, NULL);
scale = build_int_cst (scaletype, scatter_scale);
prev_stmt_info = NULL;
for (j = 0; j < ncopies; ++j)
{
if (j == 0)
{
src = vec_oprnd1
= vect_get_vec_def_for_operand (gimple_assign_rhs1 (stmt), stmt, NULL);
op = vec_oprnd0
= vect_get_vec_def_for_operand (scatter_off, stmt, NULL);
}
else if (modifier != NONE && (j & 1))
{
if (modifier == WIDEN)
{
src = vec_oprnd1
= vect_get_vec_def_for_stmt_copy (scatter_src_dt, vec_oprnd1);
op = permute_vec_elements (vec_oprnd0, vec_oprnd0, perm_mask,
stmt, gsi);
}
else if (modifier == NARROW)
{
src = permute_vec_elements (vec_oprnd1, vec_oprnd1, perm_mask,
stmt, gsi);
op = vec_oprnd0
= vect_get_vec_def_for_stmt_copy (scatter_idx_dt, vec_oprnd0);
}
else
gcc_unreachable ();
}
else
{
src = vec_oprnd1
= vect_get_vec_def_for_stmt_copy (scatter_src_dt, vec_oprnd1);
op = vec_oprnd0
= vect_get_vec_def_for_stmt_copy (scatter_idx_dt, vec_oprnd0);
}
if (!useless_type_conversion_p (srctype, TREE_TYPE (src)))
{
gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (src))
== TYPE_VECTOR_SUBPARTS (srctype));
var = vect_get_new_vect_var (srctype, vect_simple_var, NULL);
var = make_ssa_name (var);
src = build1 (VIEW_CONVERT_EXPR, srctype, src);
new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, src);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
src = var;
}
if (!useless_type_conversion_p (idxtype, TREE_TYPE (op)))
{
gcc_assert (TYPE_VECTOR_SUBPARTS (TREE_TYPE (op))
== TYPE_VECTOR_SUBPARTS (idxtype));
var = vect_get_new_vect_var (idxtype, vect_simple_var, NULL);
var = make_ssa_name (var);
op = build1 (VIEW_CONVERT_EXPR, idxtype, op);
new_stmt = gimple_build_assign (var, VIEW_CONVERT_EXPR, op);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
op = var;
}
new_stmt
= gimple_build_call (scatter_decl, 5, ptr, mask, op, src, scale);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
if (prev_stmt_info == NULL)
STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
else
STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
prev_stmt_info = vinfo_for_stmt (new_stmt);
}
return true;
}
if (grouped_store) if (grouped_store)
{ {
first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt)); first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
...@@ -5584,7 +5748,6 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -5584,7 +5748,6 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
prev_stmt_info = NULL; prev_stmt_info = NULL;
for (j = 0; j < ncopies; j++) for (j = 0; j < ncopies; j++)
{ {
gimple new_stmt;
if (j == 0) if (j == 0)
{ {
...@@ -6071,7 +6234,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -6071,7 +6234,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
{ {
grouped_load = true; grouped_load = true;
/* FORNOW */ /* FORNOW */
gcc_assert (! nested_in_vect_loop && !STMT_VINFO_GATHER_P (stmt_info)); gcc_assert (!nested_in_vect_loop && !STMT_VINFO_GATHER_SCATTER_P (stmt_info));
first_stmt = GROUP_FIRST_ELEMENT (stmt_info); first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
...@@ -6134,12 +6297,12 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -6134,12 +6297,12 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
} }
if (STMT_VINFO_GATHER_P (stmt_info)) if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{ {
gimple def_stmt; gimple def_stmt;
tree def; tree def;
gather_decl = vect_check_gather (stmt, loop_vinfo, &gather_base, gather_decl = vect_check_gather_scatter (stmt, loop_vinfo, &gather_base,
&gather_off, &gather_scale); &gather_off, &gather_scale);
gcc_assert (gather_decl); gcc_assert (gather_decl);
if (!vect_is_simple_use_1 (gather_off, NULL, loop_vinfo, bb_vinfo, if (!vect_is_simple_use_1 (gather_off, NULL, loop_vinfo, bb_vinfo,
&def_stmt, &def, &gather_dt, &def_stmt, &def, &gather_dt,
...@@ -6225,7 +6388,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -6225,7 +6388,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
ensure_base_align (stmt_info, dr); ensure_base_align (stmt_info, dr);
if (STMT_VINFO_GATHER_P (stmt_info)) if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{ {
tree vec_oprnd0 = NULL_TREE, op; tree vec_oprnd0 = NULL_TREE, op;
tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gather_decl)); tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gather_decl));
......
...@@ -646,8 +646,8 @@ typedef struct _stmt_vec_info { ...@@ -646,8 +646,8 @@ typedef struct _stmt_vec_info {
vectorization. */ vectorization. */
bool vectorizable; bool vectorizable;
/* For loads only, true if this is a gather load. */ /* For loads if this is a gather, for stores if this is a scatter. */
bool gather_p; bool gather_scatter_p;
/* True if this is an access with loop-invariant stride. */ /* True if this is an access with loop-invariant stride. */
bool strided_p; bool strided_p;
...@@ -667,7 +667,7 @@ typedef struct _stmt_vec_info { ...@@ -667,7 +667,7 @@ typedef struct _stmt_vec_info {
#define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt #define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt
#define STMT_VINFO_VECTORIZABLE(S) (S)->vectorizable #define STMT_VINFO_VECTORIZABLE(S) (S)->vectorizable
#define STMT_VINFO_DATA_REF(S) (S)->data_ref_info #define STMT_VINFO_DATA_REF(S) (S)->data_ref_info
#define STMT_VINFO_GATHER_P(S) (S)->gather_p #define STMT_VINFO_GATHER_SCATTER_P(S) (S)->gather_scatter_p
#define STMT_VINFO_STRIDED_P(S) (S)->strided_p #define STMT_VINFO_STRIDED_P(S) (S)->strided_p
#define STMT_VINFO_SIMD_LANE_ACCESS_P(S) (S)->simd_lane_access_p #define STMT_VINFO_SIMD_LANE_ACCESS_P(S) (S)->simd_lane_access_p
...@@ -1063,8 +1063,8 @@ extern bool vect_analyze_data_refs_alignment (loop_vec_info, bb_vec_info); ...@@ -1063,8 +1063,8 @@ extern bool vect_analyze_data_refs_alignment (loop_vec_info, bb_vec_info);
extern bool vect_verify_datarefs_alignment (loop_vec_info, bb_vec_info); extern bool vect_verify_datarefs_alignment (loop_vec_info, bb_vec_info);
extern bool vect_analyze_data_ref_accesses (loop_vec_info, bb_vec_info); extern bool vect_analyze_data_ref_accesses (loop_vec_info, bb_vec_info);
extern bool vect_prune_runtime_alias_test_list (loop_vec_info); extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
extern tree vect_check_gather (gimple, loop_vec_info, tree *, tree *, extern tree vect_check_gather_scatter (gimple, loop_vec_info, tree *, tree *,
int *); int *);
extern bool vect_analyze_data_refs (loop_vec_info, bb_vec_info, int *, extern bool vect_analyze_data_refs (loop_vec_info, bb_vec_info, int *,
unsigned *); unsigned *);
extern tree vect_create_data_ref_ptr (gimple, tree, struct loop *, tree, extern tree vect_create_data_ref_ptr (gimple, tree, struct loop *, tree,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment