summaryrefslogtreecommitdiff
path: root/gcc/tree-vect-data-refs.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vect-data-refs.c')
-rw-r--r--gcc/tree-vect-data-refs.c100
1 files changed, 85 insertions, 15 deletions
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 1ed7c603de2..f6e21315ed5 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -2877,8 +2877,10 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
stmt_vec_info stmt_info;
tree base, offset, init;
bool gather = false;
+ bool simd_lane_access = false;
int vf;
+again:
if (!dr || !DR_REF (dr))
{
if (dump_enabled_p ())
@@ -2890,16 +2892,34 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
stmt = DR_STMT (dr);
stmt_info = vinfo_for_stmt (stmt);
+ /* Discard clobbers from the dataref vector. We will remove
+ clobber stmts during vectorization. */
+ if (gimple_clobber_p (stmt))
+ {
+ if (i == datarefs.length () - 1)
+ {
+ datarefs.pop ();
+ break;
+ }
+ datarefs[i] = datarefs.pop ();
+ goto again;
+ }
+
/* Check that analysis of the data-ref succeeded. */
if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr) || !DR_INIT (dr)
|| !DR_STEP (dr))
{
- /* If target supports vector gather loads, see if they can't
- be used. */
- if (loop_vinfo
- && DR_IS_READ (dr)
+ bool maybe_gather
+ = DR_IS_READ (dr)
&& !TREE_THIS_VOLATILE (DR_REF (dr))
- && targetm.vectorize.builtin_gather != NULL
+ && targetm.vectorize.builtin_gather != NULL;
+ bool maybe_simd_lane_access
+ = loop_vinfo && loop->simduid;
+
+ /* If target supports vector gather loads, or if this might be
+ a SIMD lane access, see if they can't be used. */
+ if (loop_vinfo
+ && (maybe_gather || maybe_simd_lane_access)
&& !nested_in_vect_loop_p (loop, stmt))
{
struct data_reference *newdr
@@ -2912,14 +2932,59 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
&& DR_STEP (newdr)
&& integer_zerop (DR_STEP (newdr)))
{
- dr = newdr;
- gather = true;
+ if (maybe_simd_lane_access)
+ {
+ tree off = DR_OFFSET (newdr);
+ STRIP_NOPS (off);
+ if (TREE_CODE (DR_INIT (newdr)) == INTEGER_CST
+ && TREE_CODE (off) == MULT_EXPR
+ && host_integerp (TREE_OPERAND (off, 1), 1))
+ {
+ tree step = TREE_OPERAND (off, 1);
+ off = TREE_OPERAND (off, 0);
+ STRIP_NOPS (off);
+ if (CONVERT_EXPR_P (off)
+ && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (off,
+ 0)))
+ < TYPE_PRECISION (TREE_TYPE (off)))
+ off = TREE_OPERAND (off, 0);
+ if (TREE_CODE (off) == SSA_NAME)
+ {
+ gimple def = SSA_NAME_DEF_STMT (off);
+ tree reft = TREE_TYPE (DR_REF (newdr));
+ if (gimple_call_internal_p (def)
+ && gimple_call_internal_fn (def)
+ == IFN_GOMP_SIMD_LANE)
+ {
+ tree arg = gimple_call_arg (def, 0);
+ gcc_assert (TREE_CODE (arg) == SSA_NAME);
+ arg = SSA_NAME_VAR (arg);
+ if (arg == loop->simduid
+ /* For now. */
+ && tree_int_cst_equal
+ (TYPE_SIZE_UNIT (reft),
+ step))
+ {
+ DR_OFFSET (newdr) = ssize_int (0);
+ DR_STEP (newdr) = step;
+ dr = newdr;
+ simd_lane_access = true;
+ }
+ }
+ }
+ }
+ }
+ if (!simd_lane_access && maybe_gather)
+ {
+ dr = newdr;
+ gather = true;
+ }
}
- else
+ if (!gather && !simd_lane_access)
free_data_ref (newdr);
}
- if (!gather)
+ if (!gather && !simd_lane_access)
{
if (dump_enabled_p ())
{
@@ -2946,7 +3011,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
if (bb_vinfo)
break;
- if (gather)
+ if (gather || simd_lane_access)
free_data_ref (dr);
return false;
}
@@ -2979,7 +3044,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
if (bb_vinfo)
break;
- if (gather)
+ if (gather || simd_lane_access)
free_data_ref (dr);
return false;
}
@@ -2998,7 +3063,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
if (bb_vinfo)
break;
- if (gather)
+ if (gather || simd_lane_access)
free_data_ref (dr);
return false;
}
@@ -3019,7 +3084,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
if (bb_vinfo)
break;
- if (gather)
+ if (gather || simd_lane_access)
free_data_ref (dr);
return false;
}
@@ -3154,12 +3219,17 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
if (bb_vinfo)
break;
- if (gather)
+ if (gather || simd_lane_access)
free_data_ref (dr);
return false;
}
STMT_VINFO_DATA_REF (stmt_info) = dr;
+ if (simd_lane_access)
+ {
+ STMT_VINFO_SIMD_LANE_ACCESS_P (stmt_info) = true;
+ datarefs[i] = dr;
+ }
/* Set vectype for STMT. */
scalar_type = TREE_TYPE (DR_REF (dr));
@@ -3180,7 +3250,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
if (bb_vinfo)
break;
- if (gather)
+ if (gather || simd_lane_access)
{
STMT_VINFO_DATA_REF (stmt_info) = NULL;
free_data_ref (dr);