diff options
-rw-r--r-- | gcc/ChangeLog | 29 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/pr81136.c | 2 | ||||
-rw-r--r-- | gcc/tree-data-ref.c | 33 | ||||
-rw-r--r-- | gcc/tree-data-ref.h | 9 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-prefetch.c | 2 | ||||
-rw-r--r-- | gcc/tree-vect-data-refs.c | 80 | ||||
-rw-r--r-- | gcc/tree-vect-slp.c | 2 | ||||
-rw-r--r-- | gcc/tree-vectorizer.h | 11 |
9 files changed, 159 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b39dc47..c0d747d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,34 @@ 2017-08-04 Richard Sandiford <richard.sandiford@linaro.org> + PR tree-optimization/81136 + * tree-vectorizer.h: Include tree-hash-traits.h. + (vec_base_alignments): New typedef. + (vec_info): Add a base_alignments field. + (vect_record_base_alignments): Declare. + * tree-data-ref.h (data_reference): Add an is_conditional_in_stmt + field. + (DR_IS_CONDITIONAL_IN_STMT): New macro. + (create_data_ref): Add an is_conditional_in_stmt argument. + * tree-data-ref.c (create_data_ref): Likewise. Use it to initialize + the is_conditional_in_stmt field. + (data_ref_loc): Add an is_conditional_in_stmt field. + (get_references_in_stmt): Set the is_conditional_in_stmt field. + (find_data_references_in_stmt): Update call to create_data_ref. + (graphite_find_data_references_in_stmt): Likewise. + * tree-ssa-loop-prefetch.c (determine_loop_nest_reuse): Likewise. + * tree-vect-data-refs.c (vect_analyze_data_refs): Likewise. + (vect_record_base_alignment): New function. + (vect_record_base_alignments): Likewise. + (vect_compute_data_ref_alignment): Adjust base_addr and aligned_to + for nested statements even if we fail to compute a misalignment. + Use pooled base alignments for unconditional references. + (vect_find_same_alignment_drs): Compare base addresses instead + of base objects. + (vect_analyze_data_refs_alignment): Call vect_record_base_alignments. + * tree-vect-slp.c (vect_slp_analyze_bb_1): Likewise. + +2017-08-04 Richard Sandiford <richard.sandiford@linaro.org> + * tree-vectorizer.h (vec_info): Add a constructor and destructor. Add an explicit name for the enum. Use auto_vec for slp_instances and grouped_stores. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 999d5cd..23f9c8f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2017-08-04 Richard Sandiford <richard.sandiford@linaro.org> + PR tree-optimization/81136 + * gcc.dg/vect/pr81136.c: Add scan test. + +2017-08-04 Richard Sandiford <richard.sandiford@linaro.org> + * gcc.dg/vect/vect-alias-check-3.c: New test. * gcc.dg/vect/vect-alias-check-4.c: Likewise. * gcc.dg/vect/vect-alias-check-5.c: Likewise. diff --git a/gcc/testsuite/gcc.dg/vect/pr81136.c b/gcc/testsuite/gcc.dg/vect/pr81136.c index 24bd8fa..c673576 100644 --- a/gcc/testsuite/gcc.dg/vect/pr81136.c +++ b/gcc/testsuite/gcc.dg/vect/pr81136.c @@ -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" } } */ diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 4956c03..26387f8 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -1125,15 +1125,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; @@ -1148,6 +1152,7 @@ create_data_ref (loop_p nest, loop_p loop, tree memref, gimple *stmt, 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_INNERMOST (dr), memref, nest != NULL ? loop : NULL); @@ -4774,6 +4779,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; }; @@ -4840,6 +4850,7 @@ get_references_in_stmt (gimple *stmt, vec<data_ref_loc, va_heap> *references) { ref.ref = op1; ref.is_read = true; + ref.is_conditional_in_stmt = false; references->safe_push (ref); } } @@ -4867,6 +4878,7 @@ get_references_in_stmt (gimple *stmt, vec<data_ref_loc, va_heap> *references) 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); @@ -4886,6 +4898,7 @@ get_references_in_stmt (gimple *stmt, vec<data_ref_loc, va_heap> *references) { ref.ref = op1; ref.is_read = true; + ref.is_conditional_in_stmt = false; references->safe_push (ref); } } @@ -4899,6 +4912,7 @@ get_references_in_stmt (gimple *stmt, vec<data_ref_loc, va_heap> *references) { ref.ref = op0; ref.is_read = false; + ref.is_conditional_in_stmt = false; references->safe_push (ref); } return clobbers_memory; @@ -4963,8 +4977,8 @@ find_data_references_in_stmt (struct loop *nest, gimple *stmt, 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); } @@ -4993,7 +5007,8 @@ graphite_find_data_references_in_stmt (loop_p nest, loop_p loop, gimple *stmt, 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); } diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h index 0f22d9d..a66d335 100644 --- a/gcc/tree-data-ref.h +++ b/gcc/tree-data-ref.h @@ -159,6 +159,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; + /* Behavior of the memory reference in the innermost loop. */ struct innermost_loop_behavior innermost; @@ -178,6 +183,7 @@ struct data_reference #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_OFFSET(DR) (DR)->innermost.offset #define DR_INIT(DR) (DR)->innermost.init @@ -434,7 +440,8 @@ extern bool graphite_find_data_references_in_stmt (loop_p, loop_p, gimple *, 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>); diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index f8ad6b6..ecf14d1 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -1633,7 +1633,7 @@ determine_loop_nest_reuse (struct loop *loop, struct mem_ref_group *refs, 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) { diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index a91e304..60f2539 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -708,6 +708,69 @@ vect_slp_analyze_instance_dependence (slp_instance instance) return res; } +/* Record in VINFO the base alignment guarantee given by DRB. STMT is + the statement that contains DRB, which is useful for recording in the + dump file. */ + +static void +vect_record_base_alignment (vec_info *vinfo, gimple *stmt, + innermost_loop_behavior *drb) +{ + bool existed; + innermost_loop_behavior *&entry + = vinfo->base_alignments.get_or_insert (drb->base_address, &existed); + if (!existed || entry->base_alignment < drb->base_alignment) + { + entry = drb; + if (dump_enabled_p ()) + { + dump_printf_loc (MSG_NOTE, vect_location, + "recording new base alignment for "); + dump_generic_expr (MSG_NOTE, TDF_SLIM, drb->base_address); + dump_printf (MSG_NOTE, "\n"); + dump_printf_loc (MSG_NOTE, vect_location, + " alignment: %d\n", drb->base_alignment); + dump_printf_loc (MSG_NOTE, vect_location, + " misalignment: %d\n", drb->base_misalignment); + dump_printf_loc (MSG_NOTE, vect_location, + " based on: "); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 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)) + { + gimple *stmt = DR_STMT (dr); + vect_record_base_alignment (vinfo, stmt, &DR_INNERMOST (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. */ + if (loop && nested_in_vect_loop_p (loop, stmt)) + { + stmt_vec_info stmt_info = vinfo_for_stmt (stmt); + vect_record_base_alignment + (vinfo, stmt, &STMT_VINFO_DR_WRT_VEC_LOOP (stmt_info)); + } + } +} + /* Function vect_compute_data_ref_alignment Compute the misalignment of the data reference DR. @@ -725,6 +788,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr) { 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); @@ -793,6 +857,15 @@ vect_compute_data_ref_alignment (struct data_reference *dr) unsigned int base_misalignment = drb->base_misalignment; unsigned HOST_WIDE_INT vector_alignment = TYPE_ALIGN_UNIT (vectype); + /* 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) + { + base_alignment = (*entry)->base_alignment; + base_misalignment = (*entry)->base_misalignment; + } + if (drb->offset_alignment < vector_alignment || !step_preserves_misalignment_p /* We need to know whether the step wrt the vectorized loop is @@ -2113,8 +2186,7 @@ vect_find_same_alignment_drs (struct data_dependence_relation *ddr) 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; @@ -2172,6 +2244,7 @@ vect_analyze_data_refs_alignment (loop_vec_info vinfo) 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)); @@ -3437,7 +3510,8 @@ again: { 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) diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index c713745..1334df3 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -2780,6 +2780,8 @@ vect_slp_analyze_bb_1 (gimple_stmt_iterator region_begin, 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); ) diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index e8acf66..4ee3c3f 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #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,11 @@ struct stmt_info_for_cost { typedef vec<stmt_info_for_cost> stmt_vector_for_cost; +/* Maps base addresses to an innermost_loop_behavior that gives the maximum + known alignment for that base. */ +typedef hash_map<tree_operand_hash, + innermost_loop_behavior *> vec_base_alignments; + /************************************************************************ SLP ************************************************************************/ @@ -169,6 +175,10 @@ struct vec_info { /* All data references. Freed by free_data_refs, so not an auto_vec. */ vec<data_reference_p> datarefs; + /* Maps base addresses to an innermost_loop_behavior that gives the maximum + known alignment for that base. */ + vec_base_alignments base_alignments; + /* All data dependences. Freed by free_dependence_relations, so not an auto_vec. */ vec<ddr_p> ddrs; @@ -1162,6 +1172,7 @@ extern bool vect_prune_runtime_alias_test_list (loop_vec_info); 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 *, |