diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-08-04 10:42:53 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-08-04 10:42:53 +0000 |
commit | 62c8a2cf17cd794241c8f978c8fcfc4682ca4315 (patch) | |
tree | 52a7de7b09fb0528bcb735d67d552670ecb519f3 /gcc/tree-data-ref.c | |
parent | 2c515559f9dbe8bace5f68e2fec7600a9edc7c42 (diff) | |
download | gcc-62c8a2cf17cd794241c8f978c8fcfc4682ca4315.zip gcc-62c8a2cf17cd794241c8f978c8fcfc4682ca4315.tar.gz gcc-62c8a2cf17cd794241c8f978c8fcfc4682ca4315.tar.bz2 |
Pool alignment information for common bases
This patch is a follow-on to the fix for PR81136. The testcase for that
PR shows that we can (correctly) calculate different base alignments
for two data_references but still tell that their misalignments wrt the
vector size are equal. This is because we calculate the base alignments
for each dr individually, without looking at the other drs, and in
general the alignment we calculate is only guaranteed if the dr's DR_REF
actually occurs.
This is working as designed, but it does expose a missed opportunity.
We know that if a vectorised loop is reached, all statements in that
loop execute at least once, so it should be safe to pool the alignment
information for all the statements we're vectorising. The only catch is
that DR_REFs for masked loads and stores only occur if the mask value is
nonzero. For example, in:
struct s __attribute__((aligned(32))) {
int misaligner;
int array[N];
};
int *ptr;
for (int i = 0; i < n; ++i)
ptr[i] = c[i] ? ((struct s *) (ptr - 1))->array[i] : 0;
we can only guarantee that ptr points to a "struct s" if at least
one c[i] is true.
This patch adds a DR_IS_CONDITIONAL_IN_STMT flag to record whether
the DR_REF is guaranteed to occur every time that the statement
executes to completion. It then pools the alignment information
for references that aren't conditional in this sense.
2017-08-04 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
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.
gcc/testsuite/
PR tree-optimization/81136
* gcc.dg/vect/pr81136.c: Add scan test.
From-SVN: r250870
Diffstat (limited to 'gcc/tree-data-ref.c')
-rw-r--r-- | gcc/tree-data-ref.c | 33 |
1 files changed, 24 insertions, 9 deletions
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); } |