===================================================================
@@ -22,6 +22,7 @@ Software Foundation; either version 3, o
#define GCC_TREE_VECTORIZER_H
#include "tree-data-ref.h"
+#include "tree-hash-traits.h"
#include "target.h"
/* Used for naming of new temporaries. */
@@ -84,6 +85,10 @@ struct stmt_info_for_cost {
typedef vec<stmt_info_for_cost> stmt_vector_for_cost;
+/* Maps base addresses to the largest alignment that we've been able
+ to calculate for them. */
+typedef hash_map<tree_operand_hash, unsigned int> vec_base_alignments;
+
/************************************************************************
SLP
************************************************************************/
@@ -156,6 +161,10 @@ struct vec_info {
/* All data references. */
vec<data_reference_p> datarefs;
+ /* Maps the base addresses of all data references in DATAREFS to the
+ largest alignment that we've been able to calculate for them. */
+ vec_base_alignments base_alignments;
+
/* All data dependences. */
vec<ddr_p> ddrs;
@@ -1123,6 +1132,7 @@ extern bool vect_prune_runtime_alias_tes
extern bool vect_check_gather_scatter (gimple *, loop_vec_info,
gather_scatter_info *);
extern bool vect_analyze_data_refs (vec_info *, int *);
+extern void vect_record_base_alignments (vec_info *);
extern tree vect_create_data_ref_ptr (gimple *, tree, struct loop *, tree,
tree *, gimple_stmt_iterator *,
gimple **, bool, bool *,
===================================================================
@@ -119,6 +119,11 @@ struct data_reference
/* True when the data reference is in RHS of a stmt. */
bool is_read;
+ /* True when the data reference is conditional within STMT,
+ i.e. if it might not occur even when the statement is executed
+ and runs to completion. */
+ bool is_conditional_in_stmt;
+
/* The alignment of INNERMOST.base_address, in bits. This is logically
part of INNERMOST, but is kept here to avoid unnecessary padding. */
unsigned int base_alignment;
@@ -142,6 +147,7 @@ #define DR_ACCESS_FN(DR, I) DR_AC
#define DR_NUM_DIMENSIONS(DR) DR_ACCESS_FNS (DR).length ()
#define DR_IS_READ(DR) (DR)->is_read
#define DR_IS_WRITE(DR) (!DR_IS_READ (DR))
+#define DR_IS_CONDITIONAL_IN_STMT(DR) (DR)->is_conditional_in_stmt
#define DR_BASE_ADDRESS(DR) (DR)->innermost.base_address
#define DR_BASE_ALIGNMENT(DR) (DR)->base_alignment
#define DR_OFFSET(DR) (DR)->innermost.offset
@@ -355,7 +361,8 @@ extern bool graphite_find_data_reference
vec<data_reference_p> *);
tree find_data_references_in_loop (struct loop *, vec<data_reference_p> *);
bool loop_nest_has_data_refs (loop_p loop);
-struct data_reference *create_data_ref (loop_p, loop_p, tree, gimple *, bool);
+struct data_reference *create_data_ref (loop_p, loop_p, tree, gimple *, bool,
+ bool);
extern bool find_loop_nest (struct loop *, vec<loop_p> *);
extern struct data_dependence_relation *initialize_data_dependence_relation
(struct data_reference *, struct data_reference *, vec<loop_p>);
===================================================================
@@ -1065,15 +1065,19 @@ free_data_ref (data_reference_p dr)
free (dr);
}
-/* Analyzes memory reference MEMREF accessed in STMT. The reference
- is read if IS_READ is true, write otherwise. Returns the
- data_reference description of MEMREF. NEST is the outermost loop
- in which the reference should be instantiated, LOOP is the loop in
- which the data reference should be analyzed. */
+/* Analyze memory reference MEMREF, which is accessed in STMT.
+ The reference is a read if IS_READ is true, otherwise it is a write.
+ IS_CONDITIONAL_IN_STMT indicates that the reference is conditional
+ within STMT, i.e. that it might not occur even if STMT is executed
+ and runs to completion.
+
+ Return the data_reference description of MEMREF. NEST is the outermost
+ loop in which the reference should be instantiated, LOOP is the loop
+ in which the data reference should be analyzed. */
struct data_reference *
create_data_ref (loop_p nest, loop_p loop, tree memref, gimple *stmt,
- bool is_read)
+ bool is_read, bool is_conditional_in_stmt)
{
struct data_reference *dr;
@@ -1088,6 +1092,7 @@ create_data_ref (loop_p nest, loop_p loo
DR_STMT (dr) = stmt;
DR_REF (dr) = memref;
DR_IS_READ (dr) = is_read;
+ DR_IS_CONDITIONAL_IN_STMT (dr) = is_conditional_in_stmt;
dr_analyze_innermost (dr, memref, nest != NULL ? loop : NULL);
dr_analyze_indices (dr, nest, loop);
@@ -4458,6 +4463,11 @@ struct data_ref_loc
/* True if the memory reference is read. */
bool is_read;
+
+ /* True if the data reference is conditional within the containing
+ statement, i.e. if it might not occur even when the statement
+ is executed and runs to completion. */
+ bool is_conditional_in_stmt;
};
@@ -4524,6 +4534,7 @@ get_references_in_stmt (gimple *stmt, ve
{
ref.ref = op1;
ref.is_read = true;
+ ref.is_conditional_in_stmt = false;
references->safe_push (ref);
}
}
@@ -4551,6 +4562,7 @@ get_references_in_stmt (gimple *stmt, ve
type = TREE_TYPE (gimple_call_arg (stmt, 3));
if (TYPE_ALIGN (type) != align)
type = build_aligned_type (type, align);
+ ref.is_conditional_in_stmt = true;
ref.ref = fold_build2 (MEM_REF, type, gimple_call_arg (stmt, 0),
ptr);
references->safe_push (ref);
@@ -4570,6 +4582,7 @@ get_references_in_stmt (gimple *stmt, ve
{
ref.ref = op1;
ref.is_read = true;
+ ref.is_conditional_in_stmt = false;
references->safe_push (ref);
}
}
@@ -4583,6 +4596,7 @@ get_references_in_stmt (gimple *stmt, ve
{
ref.ref = op0;
ref.is_read = false;
+ ref.is_conditional_in_stmt = false;
references->safe_push (ref);
}
return clobbers_memory;
@@ -4647,8 +4661,8 @@ find_data_references_in_stmt (struct loo
FOR_EACH_VEC_ELT (references, i, ref)
{
- dr = create_data_ref (nest, loop_containing_stmt (stmt),
- ref->ref, stmt, ref->is_read);
+ dr = create_data_ref (nest, loop_containing_stmt (stmt), ref->ref,
+ stmt, ref->is_read, ref->is_conditional_in_stmt);
gcc_assert (dr != NULL);
datarefs->safe_push (dr);
}
@@ -4677,7 +4691,8 @@ graphite_find_data_references_in_stmt (l
FOR_EACH_VEC_ELT (references, i, ref)
{
- dr = create_data_ref (nest, loop, ref->ref, stmt, ref->is_read);
+ dr = create_data_ref (nest, loop, ref->ref, stmt, ref->is_read,
+ ref->is_conditional_in_stmt);
gcc_assert (dr != NULL);
datarefs->safe_push (dr);
}
===================================================================
@@ -1633,7 +1633,7 @@ determine_loop_nest_reuse (struct loop *
for (ref = gr->refs; ref; ref = ref->next)
{
dr = create_data_ref (nest, loop_containing_stmt (ref->stmt),
- ref->mem, ref->stmt, !ref->write_p);
+ ref->mem, ref->stmt, !ref->write_p, false);
if (dr)
{
===================================================================
@@ -647,6 +647,67 @@ vect_slp_analyze_instance_dependence (sl
return res;
}
+/* Record in VINFO that base address BASE_ADDR has alignment
+ BASE_ALIGNMENT. This information came from DR (which is useful
+ for recording in the dump file). */
+
+void
+vect_record_base_alignment (vec_info *vinfo, data_reference *dr,
+ tree base_addr, unsigned int base_alignment)
+{
+ bool existed;
+ unsigned int &entry
+ = vinfo->base_alignments.get_or_insert (base_addr, &existed);
+ if (!existed || entry < base_alignment)
+ {
+ entry = base_alignment;
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "setting base alignment for ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, base_addr);
+ dump_printf (MSG_NOTE, " to %d, based on ", base_alignment);
+ dump_gimple_stmt (MSG_NOTE, TDF_SLIM, DR_STMT (dr), 0);
+ }
+ }
+}
+
+/* If the region we're going to vectorize is reached, all unconditional
+ data references occur at least once. We can therefore pool the base
+ alignment guarantees from each unconditional reference. Do this by
+ going through all the data references in VINFO and checking whether
+ the containing statement makes the reference unconditionally. If so,
+ record the alignment of the base address in VINFO so that it can be
+ used for all other references with the same base. */
+
+void
+vect_record_base_alignments (vec_info *vinfo)
+{
+ loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
+ struct loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL;
+ data_reference *dr;
+ unsigned int i;
+ FOR_EACH_VEC_ELT (vinfo->datarefs, i, dr)
+ if (!DR_IS_CONDITIONAL_IN_STMT (dr))
+ {
+ vect_record_base_alignment (vinfo, dr,
+ DR_BASE_ADDRESS (dr),
+ DR_BASE_ALIGNMENT (dr));
+
+ /* If DR is nested in the loop that is being vectorized, we can also
+ record the alignment of the base wrt the outer loop. */
+ gimple *stmt = DR_STMT (dr);
+ if (loop && nested_in_vect_loop_p (loop, DR_STMT (dr)))
+ {
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ vect_record_base_alignment
+ (vinfo, dr,
+ STMT_VINFO_DR_BASE_ADDRESS (stmt_info),
+ STMT_VINFO_DR_BASE_ALIGNMENT (stmt_info));
+ }
+ }
+}
+
/* Function vect_compute_data_ref_alignment
Compute the misalignment of the data reference DR.
@@ -664,6 +725,7 @@ vect_compute_data_ref_alignment (struct
{
gimple *stmt = DR_STMT (dr);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ vec_base_alignments *base_alignments = &stmt_info->vinfo->base_alignments;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
struct loop *loop = NULL;
tree ref = DR_REF (dr);
@@ -702,6 +764,9 @@ vect_compute_data_ref_alignment (struct
{
tree step = DR_STEP (dr);
+ aligned_to = STMT_VINFO_DR_ALIGNED_TO (stmt_info);
+ base_addr = STMT_VINFO_DR_BASE_ADDRESS (stmt_info);
+ base_alignment = STMT_VINFO_DR_BASE_ALIGNMENT (stmt_info);
if (tree_fits_shwi_p (step)
&& tree_to_shwi (step) % GET_MODE_SIZE (TYPE_MODE (vectype)) == 0)
{
@@ -709,9 +774,6 @@ vect_compute_data_ref_alignment (struct
dump_printf_loc (MSG_NOTE, vect_location,
"inner step divides the vector-size.\n");
misalign = STMT_VINFO_DR_INIT (stmt_info);
- aligned_to = STMT_VINFO_DR_ALIGNED_TO (stmt_info);
- base_addr = STMT_VINFO_DR_BASE_ADDRESS (stmt_info);
- base_alignment = STMT_VINFO_DR_BASE_ALIGNMENT (stmt_info);
}
else
{
@@ -742,6 +804,11 @@ vect_compute_data_ref_alignment (struct
}
}
+ /* Calculate the maximum of the pooled base address alignment and the
+ alignment that we can compute for DR itself. */
+ if (unsigned int *entry = base_alignments->get (base_addr))
+ base_alignment = MAX (base_alignment, *entry);
+
if (base_alignment >= TYPE_ALIGN (TREE_TYPE (vectype)))
DR_VECT_AUX (dr)->base_element_aligned = true;
@@ -2089,8 +2156,7 @@ vect_find_same_alignment_drs (struct dat
if (dra == drb)
return;
- if (!operand_equal_p (DR_BASE_OBJECT (dra), DR_BASE_OBJECT (drb),
- OEP_ADDRESS_OF)
+ if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
|| !operand_equal_p (DR_OFFSET (dra), DR_OFFSET (drb), 0)
|| !operand_equal_p (DR_STEP (dra), DR_STEP (drb), 0))
return;
@@ -2148,6 +2214,7 @@ vect_analyze_data_refs_alignment (loop_v
vec<data_reference_p> datarefs = vinfo->datarefs;
struct data_reference *dr;
+ vect_record_base_alignments (vinfo);
FOR_EACH_VEC_ELT (datarefs, i, dr)
{
stmt_vec_info stmt_info = vinfo_for_stmt (DR_STMT (dr));
@@ -3346,7 +3413,8 @@ vect_analyze_data_refs (vec_info *vinfo,
{
struct data_reference *newdr
= create_data_ref (NULL, loop_containing_stmt (stmt),
- DR_REF (dr), stmt, maybe_scatter ? false : true);
+ DR_REF (dr), stmt, !maybe_scatter,
+ DR_IS_CONDITIONAL_IN_STMT (dr));
gcc_assert (newdr != NULL && DR_REF (newdr));
if (DR_BASE_ADDRESS (newdr)
&& DR_OFFSET (newdr)
===================================================================
@@ -2367,6 +2367,7 @@ new_bb_vec_info (gimple_stmt_iterator re
gimple_stmt_iterator gsi;
res = (bb_vec_info) xcalloc (1, sizeof (struct _bb_vec_info));
+ new (&res->base_alignments) vec_base_alignments ();
res->kind = vec_info::bb;
BB_VINFO_BB (res) = bb;
res->region_begin = region_begin;
@@ -2741,6 +2742,8 @@ vect_slp_analyze_bb_1 (gimple_stmt_itera
return NULL;
}
+ vect_record_base_alignments (bb_vinfo);
+
/* Analyze and verify the alignment of data references and the
dependence in the SLP instances. */
for (i = 0; BB_VINFO_SLP_INSTANCES (bb_vinfo).iterate (i, &instance); )
===================================================================
@@ -1157,6 +1157,7 @@ new_loop_vec_info (struct loop *loop)
LOOP_VINFO_VECT_FACTOR (res) = 0;
LOOP_VINFO_LOOP_NEST (res) = vNULL;
LOOP_VINFO_DATAREFS (res) = vNULL;
+ new (&res->base_alignments) vec_base_alignments ();
LOOP_VINFO_DDRS (res) = vNULL;
LOOP_VINFO_UNALIGNED_DR (res) = NULL;
LOOP_VINFO_MAY_MISALIGN_STMTS (res) = vNULL;
===================================================================
@@ -370,6 +370,8 @@ vect_destroy_datarefs (vec_info *vinfo)
}
free_data_refs (vinfo->datarefs);
+
+ vinfo->base_alignments.~vec_base_alignments ();
}
/* A helper function to free scev and LOOP niter information, as well as
===================================================================
@@ -14,3 +14,5 @@ fn1 (int n)
for (int i = 0; i < n; i++)
a->bar[i] = b[i];
}
+
+/* { dg-final { scan-tree-dump-not "Unknown misalignment" "vect" } } */