static bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
static bool vect_analyze_scalar_cycles (loop_vec_info);
static bool vect_analyze_data_ref_accesses (loop_vec_info);
+static bool vect_analyze_data_ref_dependence
+ (struct data_reference *, struct data_reference *, loop_vec_info);
+static bool vect_analyze_data_ref_dependences (loop_vec_info);
static bool vect_analyze_data_refs_alignment (loop_vec_info);
static bool vect_compute_data_refs_alignment (loop_vec_info);
static bool vect_analyze_operations (loop_vec_info);
static void vect_enhance_data_refs_alignment (loop_vec_info);
/* Utility functions for the analyses. */
-static bool vect_is_simple_use (tree , struct loop *, tree *);
+static bool vect_is_simple_use (tree , loop_vec_info, tree *);
static bool exist_non_indexing_operands_for_use_p (tree, tree);
static bool vect_is_simple_iv_evolution (unsigned, tree, tree *, tree *, bool);
static void vect_mark_relevant (varray_type *, tree);
static bool vect_can_force_dr_alignment_p (tree, unsigned int);
static struct data_reference * vect_analyze_pointer_ref_access
(tree, tree, bool);
-static bool vect_can_advance_ivs_p (struct loop *);
+static bool vect_can_advance_ivs_p (loop_vec_info);
static tree vect_get_base_and_offset (struct data_reference *, tree, tree,
loop_vec_info, tree *, tree *, tree *,
bool*);
static tree vect_create_destination_var (tree, tree);
static tree vect_create_data_ref_ptr
(tree, block_stmt_iterator *, tree, tree *, bool);
-static tree vect_create_index_for_vector_ref (struct loop *);
+static tree vect_create_index_for_vector_ref (loop_vec_info);
static tree vect_create_addr_base_for_vector_ref (tree, tree *, tree);
static tree get_vectype_for_scalar_type (tree);
static tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
static void vect_generate_tmps_on_preheader
(loop_vec_info, tree *, tree *, tree *);
static tree vect_build_loop_niters (loop_vec_info);
-static void vect_update_ivs_after_vectorizer (struct loop *, tree, edge);
+static void vect_update_ivs_after_vectorizer (loop_vec_info, tree, edge);
static tree vect_gen_niters_for_prolog_loop (loop_vec_info, tree);
static void vect_update_inits_of_dr (struct data_reference *, tree niters);
static void vect_update_inits_of_drs (loop_vec_info, tree);
/* Utilities for creation and deletion of vec_info structs. */
loop_vec_info new_loop_vec_info (struct loop *loop);
void destroy_loop_vec_info (loop_vec_info);
-stmt_vec_info new_stmt_vec_info (tree stmt, struct loop *loop);
+stmt_vec_info new_stmt_vec_info (tree, loop_vec_info);
static bool vect_debug_stats (struct loop *loop);
static bool vect_debug_details (struct loop *loop);
tree step = build_int_cst (TREE_TYPE (niters), 1);
tree then_label;
tree else_label;
- tree incr;
orig_cond = get_loop_exit_condition (loop);
#ifdef ENABLE_CHECKING
standard_iv_increment_position (loop, &incr_bsi, &insert_after);
create_iv (init, step, NULL_TREE, loop,
&incr_bsi, insert_after, &indx_before_incr, &indx_after_incr);
- incr = bsi_stmt (incr_bsi);
- get_stmt_operands (incr);
- set_stmt_info (stmt_ann (incr), new_stmt_vec_info (incr, loop));
if (exit_edge->flags & EDGE_TRUE_VALUE) /* 'then' edge exits the loop. */
{
at_exit = (e == loop->exit_edges[0]);
if (!at_exit && e != loop_preheader_edge (loop))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Edge is not an entry nor an exit edge.\n");
- return NULL;
- }
+ return NULL;
bbs = get_loop_body (loop);
/* Check whether duplication is possible. */
if (!can_copy_bbs_p (bbs, loop->num_nodes))
{
- if (vect_debug_stats (loop) || vect_debug_details (loop))
- fprintf (dump_file, "Cannot copy basic blocks.\n");
free (bbs);
return NULL;
}
new_loop = duplicate_loop (loops, loop, loop->outer);
if (!new_loop)
{
- if (vect_debug_stats (loop) || vect_debug_details (loop))
- fprintf (dump_file, "duplicate_loop returns NULL.\n");
free (bbs);
return NULL;
}
Create and initialize a new stmt_vec_info struct for STMT. */
stmt_vec_info
-new_stmt_vec_info (tree stmt, struct loop *loop)
+new_stmt_vec_info (tree stmt, loop_vec_info loop_vinfo)
{
stmt_vec_info res;
res = (stmt_vec_info) xcalloc (1, sizeof (struct _stmt_vec_info));
STMT_VINFO_TYPE (res) = undef_vec_info_type;
STMT_VINFO_STMT (res) = stmt;
- STMT_VINFO_LOOP (res) = loop;
+ STMT_VINFO_LOOP_VINFO (res) = loop_vinfo;
STMT_VINFO_RELEVANT_P (res) = 0;
STMT_VINFO_VECTYPE (res) = NULL;
STMT_VINFO_VEC_STMT (res) = NULL;
get_stmt_operands (stmt);
ann = stmt_ann (stmt);
- set_stmt_info (ann, new_stmt_vec_info (stmt, loop));
+ set_stmt_info (ann, new_stmt_vec_info (stmt, res));
}
}
if (!vect_analyze_offset_expr (oprnd0, loop, vectype_alignment, &left_offset,
&left_misalign, &left_step)
|| !vect_analyze_offset_expr (oprnd1, loop, vectype_alignment,
- &right_offset, &right_misalign, &right_step))
- return false;
+ &right_offset, &right_misalign, &right_step))
+ return false;
/* The type of the operation: plus, minus or mult. */
code = TREE_CODE (expr);
/* Misalignment computation. */
if (SSA_VAR_P (left_offset))
{
- /* If the left side contains variable that cannot be substituted with
- constant, we check if the right side is a multiple of ALIGNMENT. */
+ /* If the left side contains variables that can't be substituted with
+ constants, we check if the right side is a multiple of ALIGNMENT.
+ */
if (integer_zerop (size_binop (TRUNC_MOD_EXPR, right_offset,
fold_convert (ssizetype, vectype_alignment))))
*misalign = ssize_int (0);
else
- /* If the remainder is not zero or the right side isn't constant, we
- can't compute misalignment. */
+ /* If the remainder is not zero or the right side isn't constant,
+ we can't compute misalignment. */
*misalign = NULL_TREE;
}
else
just before the conditional expression that ends the single block loop. */
static tree
-vect_create_index_for_vector_ref (struct loop *loop)
+vect_create_index_for_vector_ref (loop_vec_info loop_vinfo)
{
tree init, step;
block_stmt_iterator incr_bsi;
bool insert_after;
tree indx_before_incr, indx_after_incr;
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree incr;
/* It is assumed that the base pointer used for vectorized access contains
&indx_before_incr, &indx_after_incr);
incr = bsi_stmt (incr_bsi);
get_stmt_operands (incr);
- set_stmt_info (stmt_ann (incr), new_stmt_vec_info (incr, loop));
+ set_stmt_info (stmt_ann (incr), new_stmt_vec_info (incr, loop_vinfo));
return indx_before_incr;
}
add_referenced_tmp_var (tmp);
offset = fold (build2 (MULT_EXPR, TREE_TYPE (offset), offset,
STMT_VINFO_VECT_STEP (stmt_info)));
- base_offset = fold (build2 (PLUS_EXPR, TREE_TYPE (base_offset), base_offset,
- offset));
+ base_offset = fold (build2 (PLUS_EXPR, TREE_TYPE (base_offset),
+ base_offset, offset));
base_offset = force_gimple_operand (base_offset, &new_stmt, false, tmp);
append_to_statement_list_force (new_stmt, new_stmt_list);
}
tree base_name;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- struct loop *loop = STMT_VINFO_LOOP (stmt_info);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree vect_ptr_type;
tree vect_ptr;
if (only_init) /* No update in loop is required. */
return vect_ptr_init;
- idx = vect_create_index_for_vector_ref (loop);
+ idx = vect_create_index_for_vector_ref (loop_vinfo);
/* Create: update = idx * vectype_size */
tmp = create_tmp_var (integer_type_node, "update");
vect_init_vector (tree stmt, tree vector_var)
{
stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
- struct loop *loop = STMT_VINFO_LOOP (stmt_vinfo);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree new_var;
tree init_stmt;
tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
int nunits = GET_MODE_NUNITS (TYPE_MODE (vectype));
- struct loop *loop = STMT_VINFO_LOOP (stmt_vinfo);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block bb;
tree vec_inv;
tree t = NULL_TREE;
tree vec_oprnd;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- struct loop *loop = STMT_VINFO_LOOP (stmt_info);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
tree new_temp;
/* Is vectorizable assignment? */
return false;
op = TREE_OPERAND (stmt, 1);
- if (!vect_is_simple_use (op, loop, NULL))
+ if (!vect_is_simple_use (op, loop_vinfo, NULL))
{
if (vect_debug_details (NULL))
fprintf (dump_file, "use not simple.");
tree vec_oprnd0, vec_oprnd1=NULL;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- struct loop *loop = STMT_VINFO_LOOP (stmt_info);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
int i;
enum tree_code code;
enum machine_mode vec_mode;
for (i = 0; i < op_type; i++)
{
op = TREE_OPERAND (operation, i);
- if (!vect_is_simple_use (op, loop, NULL))
+ if (!vect_is_simple_use (op, loop_vinfo, NULL))
{
if (vect_debug_details (NULL))
fprintf (dump_file, "use not simple.");
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- struct loop *loop = STMT_VINFO_LOOP (stmt_info);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum machine_mode vec_mode;
tree dummy;
enum dr_alignment_support alignment_support_cheme;
return false;
op = TREE_OPERAND (stmt, 1);
- if (!vect_is_simple_use (op, loop, NULL))
+ if (!vect_is_simple_use (op, loop_vinfo, NULL))
{
if (vect_debug_details (NULL))
fprintf (dump_file, "use not simple.");
tree new_stmt;
tree dummy;
basic_block new_bb;
- struct loop *loop = STMT_VINFO_LOOP (stmt_info);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
edge pe = loop_preheader_edge (loop);
enum dr_alignment_support alignment_support_cheme;
*/
static void
-vect_update_ivs_after_vectorizer (struct loop *loop, tree niters, edge update_e)
+vect_update_ivs_after_vectorizer (loop_vec_info loop_vinfo, tree niters,
+ edge update_e)
{
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block exit_bb = loop->exit_edges[0]->dest;
tree phi, phi1;
basic_block update_bb = update_e->dest;
- /* gcc_assert (vect_can_advance_ivs_p (loop)); */
+ /* gcc_assert (vect_can_advance_ivs_p (loop_vinfo)); */
/* Make sure there exists a single-predecessor exit bb: */
gcc_assert (EDGE_COUNT (exit_bb->preds) == 1);
/* Update IVs of original loop as if they were advanced
by ratio_mult_vf_name steps. */
- vect_update_ivs_after_vectorizer (loop, ratio_mult_vf_name, update_e);
+ vect_update_ivs_after_vectorizer (loop_vinfo, ratio_mult_vf_name, update_e);
/* After peeling we have to reset scalar evolution analyzer. */
scev_reset ();
in reduction/induction computations). */
static bool
-vect_is_simple_use (tree operand, struct loop *loop, tree *def)
+vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, tree *def)
{
tree def_stmt;
basic_block bb;
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
if (def)
*def = NULL_TREE;
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file, "epilog loop required.");
- if (!vect_can_advance_ivs_p (loop))
+ if (!vect_can_advance_ivs_p (loop_vinfo))
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file, "not vectorized: can't create epilog loop 1.");
static bool
vect_analyze_data_ref_dependence (struct data_reference *dra,
struct data_reference *drb,
- struct loop *loop)
+ loop_vec_info loop_vinfo)
{
bool differ_p;
struct data_dependence_relation *ddr;
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
if (!array_base_name_differ_p (dra, drb, &differ_p))
{
unsigned int i, j;
varray_type loop_write_refs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
varray_type loop_read_refs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
/* Examine store-store (output) dependences. */
VARRAY_GENERIC_PTR (loop_write_refs, i);
struct data_reference *drb =
VARRAY_GENERIC_PTR (loop_write_refs, j);
- if (vect_analyze_data_ref_dependence (dra, drb, loop))
+ if (vect_analyze_data_ref_dependence (dra, drb, loop_vinfo))
return false;
}
}
struct data_reference *dra = VARRAY_GENERIC_PTR (loop_read_refs, i);
struct data_reference *drb =
VARRAY_GENERIC_PTR (loop_write_refs, j);
- if (vect_analyze_data_ref_dependence (dra, drb, loop))
+ if (vect_analyze_data_ref_dependence (dra, drb, loop_vinfo))
return false;
}
}
vect_analyze_pointer_ref_access (tree memref, tree stmt, bool is_read)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- struct loop *loop = STMT_VINFO_LOOP (stmt_info);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree access_fn = analyze_scalar_evolution (loop, TREE_OPERAND (memref, 0));
tree init, step;
tree reftype, innertype;
and SSA_NAME (this is category 3 - "recursion stop condition").
When the MEMREF falls into category 1 there is still no data reference struct
- (DR) available. It is created by this function, and then, along the recursion,
- MEMREF will fall into category 2 or 3, in which case a DR will have already
- been created, but the analysis continues to retrieve the MEMTAG.
+ (DR) available. It is created by this function, and then, along the
+ recursion, MEMREF will fall into category 2 or 3, in which case a DR will
+ have already been created, but the analysis continues to retrieve the MEMTAG.
Input:
MEMREF - data reference in STMT
}
-
/* Function vect_analyze_data_refs.
Find all the data references in the loop.
tree arg = PHI_ARG_DEF (stmt, j);
tree def_stmt = NULL_TREE;
basic_block bb;
- if (!vect_is_simple_use (arg, loop, &def_stmt))
+ if (!vect_is_simple_use (arg, loop_vinfo, &def_stmt))
{
if (vect_debug_details (NULL))
fprintf (dump_file, "worklist: unsupported use.");
{
tree def_stmt = NULL_TREE;
basic_block bb;
- if (!vect_is_simple_use (use, loop, &def_stmt))
+ if (!vect_is_simple_use (use, loop_vinfo, &def_stmt))
{
if (vect_debug_details (NULL))
fprintf (dump_file, "worklist: unsupported use.");
These restrictions will be relaxed in the future. */
static bool
-vect_can_advance_ivs_p (struct loop *loop)
+vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
{
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
basic_block bb = loop->header;
tree phi;
};
/*-----------------------------------------------------------------*/
+/* Info on vectorized loops. */
+/*-----------------------------------------------------------------*/
+typedef struct _loop_vec_info {
+
+ /* The loop to which this info struct refers to. */
+ struct loop *loop;
+
+ /* The loop basic blocks. */
+ basic_block *bbs;
+
+ /* The loop exit_condition. */
+ tree exit_cond;
+
+ /* Number of iterations. */
+ tree num_iters;
+
+ /* Is the loop vectorizable? */
+ bool vectorizable;
+
+ /* Unrolling factor */
+ int vectorization_factor;
+
+ /* Unknown DRs according to which loop was peeled. */
+ struct data_reference *unaligned_dr;
+
+ /* If true, loop is peeled.
+ unaligned_drs show in this case DRs used for peeling. */
+ bool do_peeling_for_alignment;
+
+ /* All data references in the loop that are being written to. */
+ varray_type data_ref_writes;
+
+ /* All data references in the loop that are being read from. */
+ varray_type data_ref_reads;
+
+} *loop_vec_info;
+
+/* Access Functions. */
+#define LOOP_VINFO_LOOP(L) (L)->loop
+#define LOOP_VINFO_BBS(L) (L)->bbs
+#define LOOP_VINFO_EXIT_COND(L) (L)->exit_cond
+#define LOOP_VINFO_NITERS(L) (L)->num_iters
+#define LOOP_VINFO_VECTORIZABLE_P(L) (L)->vectorizable
+#define LOOP_VINFO_VECT_FACTOR(L) (L)->vectorization_factor
+#define LOOP_VINFO_DATAREF_WRITES(L) (L)->data_ref_writes
+#define LOOP_VINFO_DATAREF_READS(L) (L)->data_ref_reads
+#define LOOP_VINFO_INT_NITERS(L) (TREE_INT_CST_LOW ((L)->num_iters))
+#define LOOP_DO_PEELING_FOR_ALIGNMENT(L) (L)->do_peeling_for_alignment
+#define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr
+
+
+#define LOOP_VINFO_NITERS_KNOWN_P(L) \
+(host_integerp ((L)->num_iters,0) \
+&& TREE_INT_CST_LOW ((L)->num_iters) > 0)
+
+/*-----------------------------------------------------------------*/
/* Info on vectorized defs. */
/*-----------------------------------------------------------------*/
enum stmt_vec_info_type {
/* The stmt to which this info struct refers to. */
tree stmt;
- /* The loop with respect to which STMT is vectorized. */
- struct loop *loop;
+ /* The loop_vec_info with respect to which STMT is vectorized. */
+ loop_vec_info loop_vinfo;
/* Not all stmts in the loop need to be vectorized. e.g, the incrementation
of the loop induction variable and computation of array indexes. relevant
/* Access Functions. */
#define STMT_VINFO_TYPE(S) (S)->type
#define STMT_VINFO_STMT(S) (S)->stmt
-#define STMT_VINFO_LOOP(S) (S)->loop
+#define STMT_VINFO_LOOP_VINFO(S) (S)->loop_vinfo
#define STMT_VINFO_RELEVANT_P(S) (S)->relevant
#define STMT_VINFO_VECTYPE(S) (S)->vectype
#define STMT_VINFO_VEC_STMT(S) (S)->vectorized_stmt
/*-----------------------------------------------------------------*/
-/* Info on vectorized loops. */
-/*-----------------------------------------------------------------*/
-typedef struct _loop_vec_info {
-
- /* The loop to which this info struct refers to. */
- struct loop *loop;
-
- /* The loop basic blocks. */
- basic_block *bbs;
-
- /* The loop exit_condition. */
- tree exit_cond;
-
- /* Number of iterations. */
- tree num_iters;
-
- /* Is the loop vectorizable? */
- bool vectorizable;
-
- /* Unrolling factor */
- int vectorization_factor;
-
- /* Unknown DRs according to which loop was peeled. */
- struct data_reference *unaligned_dr;
-
- /* If true, loop is peeled.
- unaligned_drs show in this case DRs used for peeling. */
- bool do_peeling_for_alignment;
-
- /* All data references in the loop that are being written to. */
- varray_type data_ref_writes;
-
- /* All data references in the loop that are being read from. */
- varray_type data_ref_reads;
-} *loop_vec_info;
-
-/* Access Functions. */
-#define LOOP_VINFO_LOOP(L) (L)->loop
-#define LOOP_VINFO_BBS(L) (L)->bbs
-#define LOOP_VINFO_EXIT_COND(L) (L)->exit_cond
-#define LOOP_VINFO_NITERS(L) (L)->num_iters
-#define LOOP_VINFO_VECTORIZABLE_P(L) (L)->vectorizable
-#define LOOP_VINFO_VECT_FACTOR(L) (L)->vectorization_factor
-#define LOOP_VINFO_DATAREF_WRITES(L) (L)->data_ref_writes
-#define LOOP_VINFO_DATAREF_READS(L) (L)->data_ref_reads
-#define LOOP_VINFO_INT_NITERS(L) (TREE_INT_CST_LOW ((L)->num_iters))
-#define LOOP_DO_PEELING_FOR_ALIGNMENT(L) (L)->do_peeling_for_alignment
-#define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr
-
-
-#define LOOP_VINFO_NITERS_KNOWN_P(L) \
-(host_integerp ((L)->num_iters,0) \
-&& TREE_INT_CST_LOW ((L)->num_iters) > 0)
-
-/*-----------------------------------------------------------------*/
/* Function prototypes. */
/*-----------------------------------------------------------------*/
/* creation and deletion of loop and stmt info structs. */
extern loop_vec_info new_loop_vec_info (struct loop *loop);
extern void destroy_loop_vec_info (loop_vec_info);
-extern stmt_vec_info new_stmt_vec_info (tree stmt, struct loop *loop);
+extern stmt_vec_info new_stmt_vec_info (tree stmt, loop_vec_info);
#endif /* GCC_TREE_VECTORIZER_H */