aboutsummaryrefslogtreecommitdiff
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.c265
1 files changed, 151 insertions, 114 deletions
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 97c8577..f43d0f4 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-hash-traits.h"
#include "vec-perm-indices.h"
#include "internal-fn.h"
+#include "gimple-fold.h"
/* Return true if load- or store-lanes optab OPTAB is implemented for
COUNT vectors of type VECTYPE. NAME is the name of OPTAB. */
@@ -115,11 +116,8 @@ vect_lanes_optab_supported_p (const char *name, convert_optab optab,
types. */
tree
-vect_get_smallest_scalar_type (stmt_vec_info stmt_info,
- HOST_WIDE_INT *lhs_size_unit,
- HOST_WIDE_INT *rhs_size_unit)
+vect_get_smallest_scalar_type (stmt_vec_info stmt_info, tree scalar_type)
{
- tree scalar_type = gimple_expr_type (stmt_info->stmt);
HOST_WIDE_INT lhs, rhs;
/* During the analysis phase, this function is called on arbitrary
@@ -130,21 +128,24 @@ vect_get_smallest_scalar_type (stmt_vec_info stmt_info,
lhs = rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (scalar_type));
gassign *assign = dyn_cast <gassign *> (stmt_info->stmt);
- if (assign
- && (gimple_assign_cast_p (assign)
+ if (assign)
+ {
+ scalar_type = TREE_TYPE (gimple_assign_lhs (assign));
+ if (gimple_assign_cast_p (assign)
|| gimple_assign_rhs_code (assign) == DOT_PROD_EXPR
|| gimple_assign_rhs_code (assign) == WIDEN_SUM_EXPR
|| gimple_assign_rhs_code (assign) == WIDEN_MULT_EXPR
|| gimple_assign_rhs_code (assign) == WIDEN_LSHIFT_EXPR
|| gimple_assign_rhs_code (assign) == WIDEN_PLUS_EXPR
|| gimple_assign_rhs_code (assign) == WIDEN_MINUS_EXPR
- || gimple_assign_rhs_code (assign) == FLOAT_EXPR))
- {
- tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (assign));
+ || gimple_assign_rhs_code (assign) == FLOAT_EXPR)
+ {
+ tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (assign));
- rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (rhs_type));
- if (rhs < lhs)
- scalar_type = rhs_type;
+ rhs = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (rhs_type));
+ if (rhs < lhs)
+ scalar_type = rhs_type;
+ }
}
else if (gcall *call = dyn_cast <gcall *> (stmt_info->stmt))
{
@@ -152,10 +153,16 @@ vect_get_smallest_scalar_type (stmt_vec_info stmt_info,
if (gimple_call_internal_p (call))
{
internal_fn ifn = gimple_call_internal_fn (call);
- if (internal_load_fn_p (ifn) || internal_store_fn_p (ifn))
- /* gimple_expr_type already picked the type of the loaded
- or stored data. */
+ if (internal_load_fn_p (ifn))
+ /* For loads the LHS type does the trick. */
i = ~0U;
+ else if (internal_store_fn_p (ifn))
+ {
+ /* For stores use the tyep of the stored value. */
+ i = internal_fn_stored_value_index (ifn);
+ scalar_type = TREE_TYPE (gimple_call_arg (call, i));
+ i = ~0U;
+ }
else if (internal_fn_mask_index (ifn) == 0)
i = 1;
}
@@ -171,8 +178,6 @@ vect_get_smallest_scalar_type (stmt_vec_info stmt_info,
}
}
- *lhs_size_unit = lhs;
- *rhs_size_unit = rhs;
return scalar_type;
}
@@ -207,7 +212,7 @@ vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo)
static void
vect_check_nonzero_value (loop_vec_info loop_vinfo, tree value)
{
- vec<tree> checks = LOOP_VINFO_CHECK_NONZERO (loop_vinfo);
+ const vec<tree> &checks = LOOP_VINFO_CHECK_NONZERO (loop_vinfo);
for (unsigned int i = 0; i < checks.length(); ++i)
if (checks[i] == value)
return;
@@ -290,9 +295,7 @@ vect_analyze_possibly_independent_ddr (data_dependence_relation *ddr,
int loop_depth, unsigned int *max_vf)
{
class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- lambda_vector dist_v;
- unsigned int i;
- FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, dist_v)
+ for (lambda_vector &dist_v : DDR_DIST_VECTS (ddr))
{
int dist = dist_v[loop_depth];
if (dist != 0 && !(dist > 0 && DDR_REVERSED_P (ddr)))
@@ -729,9 +732,8 @@ vect_slp_analyze_node_dependences (vec_info *vinfo, slp_tree node,
{
if (stmt_info != last_store_info)
continue;
- unsigned i;
- stmt_vec_info store_info;
- FOR_EACH_VEC_ELT (stores, i, store_info)
+
+ for (stmt_vec_info &store_info : stores)
{
data_reference *store_dr
= STMT_VINFO_DATA_REF (store_info);
@@ -780,16 +782,20 @@ vect_slp_analyze_node_dependences (vec_info *vinfo, slp_tree node,
stmt we have to resort to the alias oracle. */
stmt_vec_info stmt_info = vinfo->lookup_stmt (stmt);
data_reference *dr_b = STMT_VINFO_DATA_REF (stmt_info);
- if (!dr_b)
+
+ /* We are hoisting a load - this means we can use
+ TBAA for disambiguation. */
+ if (!ref_initialized_p)
+ ao_ref_init (&ref, DR_REF (dr_a));
+ if (stmt_may_clobber_ref_p_1 (stmt, &ref, true))
{
- /* We are hoisting a load - this means we can use
- TBAA for disambiguation. */
- if (!ref_initialized_p)
- ao_ref_init (&ref, DR_REF (dr_a));
- if (stmt_may_clobber_ref_p_1 (stmt, &ref, true))
+ if (!dr_b)
return false;
- continue;
+ /* Resort to dependence checking below. */
}
+ else
+ /* No dependence. */
+ continue;
bool dependent = false;
/* If we run into a store of this same instance (we've just
@@ -800,9 +806,8 @@ vect_slp_analyze_node_dependences (vec_info *vinfo, slp_tree node,
{
if (stmt_info != last_store_info)
continue;
- unsigned i;
- stmt_vec_info store_info;
- FOR_EACH_VEC_ELT (stores, i, store_info)
+
+ for (stmt_vec_info &store_info : stores)
{
data_reference *store_dr
= STMT_VINFO_DATA_REF (store_info);
@@ -843,9 +848,9 @@ vect_slp_analyze_instance_dependence (vec_info *vinfo, slp_instance instance)
DUMP_VECT_SCOPE ("vect_slp_analyze_instance_dependence");
/* The stores of this instance are at the root of the SLP tree. */
- slp_tree store = SLP_INSTANCE_TREE (instance);
- if (! STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (store)))
- store = NULL;
+ slp_tree store = NULL;
+ if (SLP_INSTANCE_KIND (instance) == slp_inst_kind_store)
+ store = SLP_INSTANCE_TREE (instance);
/* Verify we can sink stores to the vectorized stmt insert location. */
stmt_vec_info last_store_info = NULL;
@@ -864,9 +869,7 @@ vect_slp_analyze_instance_dependence (vec_info *vinfo, slp_instance instance)
/* Verify we can sink loads to the vectorized stmt insert location,
special-casing stores of this instance. */
- slp_tree load;
- unsigned int i;
- FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (instance), i, load)
+ for (slp_tree &load : SLP_INSTANCE_LOADS (instance))
if (! vect_slp_analyze_node_dependences (vinfo, load,
store
? SLP_TREE_SCALAR_STMTS (store)
@@ -892,11 +895,11 @@ vect_record_base_alignment (vec_info *vinfo, stmt_vec_info stmt_info,
innermost_loop_behavior *drb)
{
bool existed;
- innermost_loop_behavior *&entry
+ std::pair<stmt_vec_info, innermost_loop_behavior *> &entry
= vinfo->base_alignments.get_or_insert (drb->base_address, &existed);
- if (!existed || entry->base_alignment < drb->base_alignment)
+ if (!existed || entry.second->base_alignment < drb->base_alignment)
{
- entry = drb;
+ entry = std::make_pair (stmt_info, drb);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"recording new base alignment for %T\n"
@@ -923,9 +926,7 @@ vect_record_base_alignments (vec_info *vinfo)
{
loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
class loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
- data_reference *dr;
- unsigned int i;
- FOR_EACH_VEC_ELT (vinfo->shared->datarefs, i, dr)
+ for (data_reference *dr : vinfo->shared->datarefs)
{
dr_vec_info *dr_info = vinfo->lookup_dr (dr);
stmt_vec_info stmt_info = dr_info->stmt;
@@ -1059,11 +1060,18 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info)
/* Calculate the maximum of the pooled base address alignment and the
alignment that we can compute for DR itself. */
- innermost_loop_behavior **entry = base_alignments->get (drb->base_address);
- if (entry && base_alignment < (*entry)->base_alignment)
+ std::pair<stmt_vec_info, innermost_loop_behavior *> *entry
+ = base_alignments->get (drb->base_address);
+ if (entry
+ && base_alignment < (*entry).second->base_alignment
+ && (loop_vinfo
+ || (dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt_info->stmt),
+ gimple_bb (entry->first->stmt))
+ && (gimple_bb (stmt_info->stmt) != gimple_bb (entry->first->stmt)
+ || (entry->first->dr_aux.group <= dr_info->group)))))
{
- base_alignment = (*entry)->base_alignment;
- base_misalignment = (*entry)->base_misalignment;
+ base_alignment = entry->second->base_alignment;
+ base_misalignment = entry->second->base_misalignment;
}
if (drb->offset_alignment < vect_align_c
@@ -1459,10 +1467,8 @@ vect_get_peeling_costs_all_drs (loop_vec_info loop_vinfo,
bool unknown_misalignment)
{
vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
- unsigned i;
- data_reference *dr;
- FOR_EACH_VEC_ELT (datarefs, i, dr)
+ for (data_reference *dr : datarefs)
{
dr_vec_info *dr_info = loop_vinfo->lookup_dr (dr);
if (!vect_relevant_for_alignment_p (dr_info))
@@ -1571,13 +1577,11 @@ static bool
vect_peeling_supportable (loop_vec_info loop_vinfo, dr_vec_info *dr0_info,
unsigned npeel)
{
- unsigned i;
- struct data_reference *dr = NULL;
vec<data_reference_p> datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
enum dr_alignment_support supportable_dr_alignment;
/* Ensure that all data refs can be vectorized after the peel. */
- FOR_EACH_VEC_ELT (datarefs, i, dr)
+ for (data_reference *dr : datarefs)
{
int save_misalignment;
@@ -2352,8 +2356,8 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (do_versioning)
{
- vec<stmt_vec_info> may_misalign_stmts
- = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
+ const vec<stmt_vec_info> &may_misalign_stmts
+ = LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo);
stmt_vec_info stmt_info;
/* It can now be assumed that the data references in the statements
@@ -2472,8 +2476,7 @@ vect_slp_analyze_instance_alignment (vec_info *vinfo,
if (! vect_slp_analyze_node_alignment (vinfo, node))
return false;
- node = SLP_INSTANCE_TREE (instance);
- if (STMT_VINFO_DATA_REF (SLP_TREE_REPRESENTATIVE (node))
+ if (SLP_INSTANCE_KIND (instance) == slp_inst_kind_store
&& ! vect_slp_analyze_node_alignment
(vinfo, SLP_INSTANCE_TREE (instance)))
return false;
@@ -2817,33 +2820,25 @@ vect_analyze_data_ref_access (vec_info *vinfo, dr_vec_info *dr_info)
return vect_analyze_group_access (vinfo, dr_info);
}
-typedef std::pair<data_reference_p, int> data_ref_pair;
-
/* Compare two data-references DRA and DRB to group them into chunks
suitable for grouping. */
static int
dr_group_sort_cmp (const void *dra_, const void *drb_)
{
- data_ref_pair dra_pair = *(data_ref_pair *)const_cast<void *>(dra_);
- data_ref_pair drb_pair = *(data_ref_pair *)const_cast<void *>(drb_);
- data_reference_p dra = dra_pair.first;
- data_reference_p drb = drb_pair.first;
+ dr_vec_info *dra_info = *(dr_vec_info **)const_cast<void *>(dra_);
+ dr_vec_info *drb_info = *(dr_vec_info **)const_cast<void *>(drb_);
+ data_reference_p dra = dra_info->dr;
+ data_reference_p drb = drb_info->dr;
int cmp;
/* Stabilize sort. */
if (dra == drb)
return 0;
- /* DRs in different basic-blocks never belong to the same group. */
- int bb_index1 = gimple_bb (DR_STMT (dra))->index;
- int bb_index2 = gimple_bb (DR_STMT (drb))->index;
- if (bb_index1 != bb_index2)
- return bb_index1 < bb_index2 ? -1 : 1;
-
/* Different group IDs lead never belong to the same group. */
- if (dra_pair.second != drb_pair.second)
- return dra_pair.second < drb_pair.second ? -1 : 1;
+ if (dra_info->group != drb_info->group)
+ return dra_info->group < drb_info->group ? -1 : 1;
/* Ordering of DRs according to base. */
cmp = data_ref_compare_tree (DR_BASE_ADDRESS (dra),
@@ -2963,12 +2958,18 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
/* Sort the array of datarefs to make building the interleaving chains
linear. Don't modify the original vector's order, it is needed for
determining what dependencies are reversed. */
- vec<data_ref_pair> datarefs_copy;
+ vec<dr_vec_info *> datarefs_copy;
datarefs_copy.create (datarefs.length ());
for (unsigned i = 0; i < datarefs.length (); i++)
{
- int group_id = dataref_groups ? (*dataref_groups)[i] : 0;
- datarefs_copy.quick_push (data_ref_pair (datarefs[i], group_id));
+ dr_vec_info *dr_info = vinfo->lookup_dr (datarefs[i]);
+ /* If the caller computed DR grouping use that, otherwise group by
+ basic blocks. */
+ if (dataref_groups)
+ dr_info->group = (*dataref_groups)[i];
+ else
+ dr_info->group = gimple_bb (DR_STMT (datarefs[i]))->index;
+ datarefs_copy.quick_push (dr_info);
}
datarefs_copy.qsort (dr_group_sort_cmp);
hash_set<stmt_vec_info> to_fixup;
@@ -2976,9 +2977,9 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
/* Build the interleaving chains. */
for (i = 0; i < datarefs_copy.length () - 1;)
{
- data_reference_p dra = datarefs_copy[i].first;
- int dra_group_id = datarefs_copy[i].second;
- dr_vec_info *dr_info_a = vinfo->lookup_dr (dra);
+ dr_vec_info *dr_info_a = datarefs_copy[i];
+ data_reference_p dra = dr_info_a->dr;
+ int dra_group_id = dr_info_a->group;
stmt_vec_info stmtinfo_a = dr_info_a->stmt;
stmt_vec_info lastinfo = NULL;
if (!STMT_VINFO_VECTORIZABLE (stmtinfo_a)
@@ -2989,9 +2990,9 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
}
for (i = i + 1; i < datarefs_copy.length (); ++i)
{
- data_reference_p drb = datarefs_copy[i].first;
- int drb_group_id = datarefs_copy[i].second;
- dr_vec_info *dr_info_b = vinfo->lookup_dr (drb);
+ dr_vec_info *dr_info_b = datarefs_copy[i];
+ data_reference_p drb = dr_info_b->dr;
+ int drb_group_id = dr_info_b->group;
stmt_vec_info stmtinfo_b = dr_info_b->stmt;
if (!STMT_VINFO_VECTORIZABLE (stmtinfo_b)
|| STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b))
@@ -3003,13 +3004,8 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
matters we can push those to a worklist and re-iterate
over them. The we can just skip ahead to the next DR here. */
- /* DRs in a different BBs should not be put into the same
+ /* DRs in a different DR group should not be put into the same
interleaving group. */
- int bb_index1 = gimple_bb (DR_STMT (dra))->index;
- int bb_index2 = gimple_bb (DR_STMT (drb))->index;
- if (bb_index1 != bb_index2)
- break;
-
if (dra_group_id != drb_group_id)
break;
@@ -3057,7 +3053,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
HOST_WIDE_INT init_a = TREE_INT_CST_LOW (DR_INIT (dra));
HOST_WIDE_INT init_b = TREE_INT_CST_LOW (DR_INIT (drb));
HOST_WIDE_INT init_prev
- = TREE_INT_CST_LOW (DR_INIT (datarefs_copy[i-1].first));
+ = TREE_INT_CST_LOW (DR_INIT (datarefs_copy[i-1]->dr));
gcc_assert (init_a <= init_b
&& init_a <= init_prev
&& init_prev <= init_b);
@@ -3065,7 +3061,7 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
/* Do not place the same access in the interleaving chain twice. */
if (init_b == init_prev)
{
- gcc_assert (gimple_uid (DR_STMT (datarefs_copy[i-1].first))
+ gcc_assert (gimple_uid (DR_STMT (datarefs_copy[i-1]->dr))
< gimple_uid (DR_STMT (drb)));
/* Simply link in duplicates and fix up the chain below. */
}
@@ -3178,10 +3174,9 @@ vect_analyze_data_ref_accesses (vec_info *vinfo,
to_fixup.add (newgroup);
}
- data_ref_pair *dr_pair;
- FOR_EACH_VEC_ELT (datarefs_copy, i, dr_pair)
+ dr_vec_info *dr_info;
+ FOR_EACH_VEC_ELT (datarefs_copy, i, dr_info)
{
- dr_vec_info *dr_info = vinfo->lookup_dr (dr_pair->first);
if (STMT_VINFO_VECTORIZABLE (dr_info->stmt)
&& !vect_analyze_data_ref_access (vinfo, dr_info))
{
@@ -3368,7 +3363,8 @@ static void
vect_check_lower_bound (loop_vec_info loop_vinfo, tree expr, bool unsigned_p,
poly_uint64 min_value)
{
- vec<vec_lower_bound> lower_bounds = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo);
+ vec<vec_lower_bound> &lower_bounds
+ = LOOP_VINFO_LOWER_BOUNDS (loop_vinfo);
for (unsigned int i = 0; i < lower_bounds.length (); ++i)
if (operand_equal_p (lower_bounds[i].expr, expr, 0))
{
@@ -3470,10 +3466,10 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
typedef pair_hash <tree_operand_hash, tree_operand_hash> tree_pair_hash;
hash_set <tree_pair_hash> compared_objects;
- vec<ddr_p> may_alias_ddrs = LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
+ const vec<ddr_p> &may_alias_ddrs = LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
vec<dr_with_seg_len_pair_t> &comp_alias_ddrs
= LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
- vec<vec_object_pair> &check_unequal_addrs
+ const vec<vec_object_pair> &check_unequal_addrs
= LOOP_VINFO_CHECK_UNEQUAL_ADDRS (loop_vinfo);
poly_uint64 vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
tree scalar_loop_iters = LOOP_VINFO_NITERS (loop_vinfo);
@@ -3487,9 +3483,9 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
/* Step values are irrelevant for aliasing if the number of vector
iterations is equal to the number of scalar iterations (which can
happen for fully-SLP loops). */
- bool ignore_step_p = known_eq (LOOP_VINFO_VECT_FACTOR (loop_vinfo), 1U);
+ bool vf_one_p = known_eq (LOOP_VINFO_VECT_FACTOR (loop_vinfo), 1U);
- if (!ignore_step_p)
+ if (!vf_one_p)
{
/* Convert the checks for nonzero steps into bound tests. */
tree value;
@@ -3542,6 +3538,11 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
bool preserves_scalar_order_p
= vect_preserves_scalar_order_p (dr_info_a, dr_info_b);
+ bool ignore_step_p
+ = (vf_one_p
+ && (preserves_scalar_order_p
+ || operand_equal_p (DR_STEP (dr_info_a->dr),
+ DR_STEP (dr_info_b->dr))));
/* Skip the pair if inter-iteration dependencies are irrelevant
and intra-iteration dependencies are guaranteed to be honored. */
@@ -3733,11 +3734,17 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
return false;
/* Work out which function we need. */
- internal_fn ifn;
+ internal_fn ifn, alt_ifn;
if (read_p)
- ifn = masked_p ? IFN_MASK_GATHER_LOAD : IFN_GATHER_LOAD;
+ {
+ ifn = masked_p ? IFN_MASK_GATHER_LOAD : IFN_GATHER_LOAD;
+ alt_ifn = IFN_MASK_GATHER_LOAD;
+ }
else
- ifn = masked_p ? IFN_MASK_SCATTER_STORE : IFN_SCATTER_STORE;
+ {
+ ifn = masked_p ? IFN_MASK_SCATTER_STORE : IFN_SCATTER_STORE;
+ alt_ifn = IFN_MASK_SCATTER_STORE;
+ }
for (;;)
{
@@ -3753,6 +3760,16 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
*offset_vectype_out = offset_vectype;
return true;
}
+ else if (!masked_p
+ && internal_gather_scatter_fn_supported_p (alt_ifn, vectype,
+ memory_type,
+ offset_vectype,
+ scale))
+ {
+ *ifn_out = alt_ifn;
+ *offset_vectype_out = offset_vectype;
+ return true;
+ }
if (TYPE_PRECISION (offset_type) >= POINTER_SIZE
&& TYPE_PRECISION (offset_type) >= element_bits)
@@ -4006,8 +4023,24 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
continue;
}
- if (TYPE_PRECISION (TREE_TYPE (op0))
- < TYPE_PRECISION (TREE_TYPE (off)))
+ /* Include the conversion if it is widening and we're using
+ the IFN path or the target can handle the converted from
+ offset or the current size is not already the same as the
+ data vector element size. */
+ if ((TYPE_PRECISION (TREE_TYPE (op0))
+ < TYPE_PRECISION (TREE_TYPE (off)))
+ && (use_ifn_p
+ || (DR_IS_READ (dr)
+ ? (targetm.vectorize.builtin_gather
+ && targetm.vectorize.builtin_gather (vectype,
+ TREE_TYPE (op0),
+ scale))
+ : (targetm.vectorize.builtin_scatter
+ && targetm.vectorize.builtin_scatter (vectype,
+ TREE_TYPE (op0),
+ scale)))
+ || !operand_equal_p (TYPE_SIZE (TREE_TYPE (off)),
+ TYPE_SIZE (TREE_TYPE (vectype)), 0)))
{
off = op0;
offtype = TREE_TYPE (off);
@@ -4035,7 +4068,8 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
if (!vect_gather_scatter_fn_p (loop_vinfo, DR_IS_READ (dr), masked_p,
vectype, memory_type, offtype, scale,
&ifn, &offset_vectype))
- return false;
+ ifn = IFN_LAST;
+ decl = NULL_TREE;
}
else
{
@@ -4049,10 +4083,6 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
if (targetm.vectorize.builtin_scatter)
decl = targetm.vectorize.builtin_scatter (vectype, offtype, scale);
}
-
- if (!decl)
- return false;
-
ifn = IFN_LAST;
/* The offset vector type will be read from DECL when needed. */
offset_vectype = NULL_TREE;
@@ -4282,9 +4312,7 @@ vect_analyze_data_refs (vec_info *vinfo, poly_uint64 *min_vf, bool *fatal)
{
bool maybe_gather
= DR_IS_READ (dr)
- && !TREE_THIS_VOLATILE (DR_REF (dr))
- && (targetm.vectorize.builtin_gather != NULL
- || supports_vec_gather_load_p ());
+ && !TREE_THIS_VOLATILE (DR_REF (dr));
bool maybe_scatter
= DR_IS_WRITE (dr)
&& !TREE_THIS_VOLATILE (DR_REF (dr))
@@ -5035,7 +5063,7 @@ bump_vector_ptr (vec_info *vinfo,
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree update = TYPE_SIZE_UNIT (vectype);
- gassign *incr_stmt;
+ gimple *incr_stmt;
ssa_op_iter iter;
use_operand_p use_p;
tree new_dataref_ptr;
@@ -5050,6 +5078,15 @@ bump_vector_ptr (vec_info *vinfo,
incr_stmt = gimple_build_assign (new_dataref_ptr, POINTER_PLUS_EXPR,
dataref_ptr, update);
vect_finish_stmt_generation (vinfo, stmt_info, incr_stmt, gsi);
+ /* Fold the increment, avoiding excessive chains use-def chains of
+ those, leading to compile-time issues for passes until the next
+ forwprop pass which would do this as well. */
+ gimple_stmt_iterator fold_gsi = gsi_for_stmt (incr_stmt);
+ if (fold_stmt (&fold_gsi, follow_all_ssa_edges))
+ {
+ incr_stmt = gsi_stmt (fold_gsi);
+ update_stmt (incr_stmt);
+ }
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
@@ -5329,7 +5366,7 @@ vect_store_lanes_supported (tree vectype, unsigned HOST_WIDE_INT count,
I4: 6 14 22 30 7 15 23 31. */
void
-vect_permute_store_chain (vec_info *vinfo, vec<tree> dr_chain,
+vect_permute_store_chain (vec_info *vinfo, vec<tree> &dr_chain,
unsigned int length,
stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi,