aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-data-ref.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-07-03 13:36:55 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-07-03 13:36:55 +0000
commitbb64297941f34721c7d4e94e754b454086511cf9 (patch)
treeaa95ccdabebcc6989fd1aaff624bf8dbfafbd39b /gcc/tree-data-ref.c
parent832b4117d4068670cc9ed496a7ab06104a12dc00 (diff)
downloadgcc-bb64297941f34721c7d4e94e754b454086511cf9.zip
gcc-bb64297941f34721c7d4e94e754b454086511cf9.tar.gz
gcc-bb64297941f34721c7d4e94e754b454086511cf9.tar.bz2
Add DR_BASE_ALIGNMENT and DR_BASE_MISALIGNMENT
This patch records the base alignment and misalignment in innermost_loop_behavior, to avoid the second-guessing that was previously done in vect_compute_data_ref_alignment. It also makes vect_analyze_data_refs use dr_analyze_innermost, instead of having an almost-copy of the same code. I wasn't sure whether the alignments should be measured in bits (for consistency with most other interfaces) or in bytes (for consistency with DR_ALIGNED_TO, now DR_OFFSET_ALIGNMENT, and with *_ptr_info_alignment). I went for bytes because: - I think in practice most consumers are going to want bytes. E.g. using bytes avoids having to mix TYPE_ALIGN and TYPE_ALIGN_UNIT in vect_compute_data_ref_alignment. - It means that any bit-level paranoia is dealt with when building the innermost_loop_behavior and doesn't get pushed down to consumers. 2017-07-03 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * tree-data-ref.h (innermost_loop_behavior): Add base_alignment and base_misalignment fields. (DR_BASE_ALIGNMENT, DR_BASE_MISALIGNMENT): New macros. * tree-data-ref.c: Include builtins.h. (dr_analyze_innermost): Set up the new innmost_loop_behavior fields. * tree-vectorizer.h (STMT_VINFO_DR_BASE_ALIGNMENT): New macro. (STMT_VINFO_DR_BASE_MISALIGNMENT): Likewise. * tree-vect-data-refs.c: Include tree-cfg.h. (vect_compute_data_ref_alignment): Use the new innermost_loop_behavior fields instead of calculating an alignment here. (vect_analyze_data_refs): Use dr_analyze_innermost. Dump the new innermost_loop_behavior fields. From-SVN: r249916
Diffstat (limited to 'gcc/tree-data-ref.c')
-rw-r--r--gcc/tree-data-ref.c51
1 files changed, 48 insertions, 3 deletions
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 03dfb20..ab76853 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -94,6 +94,7 @@ along with GCC; see the file COPYING3. If not see
#include "dumpfile.h"
#include "tree-affine.h"
#include "params.h"
+#include "builtins.h"
static struct datadep_stats
{
@@ -802,11 +803,26 @@ dr_analyze_innermost (innermost_loop_behavior *drb, tree ref,
return false;
}
+ /* Calculate the alignment and misalignment for the inner reference. */
+ unsigned int HOST_WIDE_INT base_misalignment;
+ unsigned int base_alignment;
+ get_object_alignment_1 (base, &base_alignment, &base_misalignment);
+
+ /* There are no bitfield references remaining in BASE, so the values
+ we got back must be whole bytes. */
+ gcc_assert (base_alignment % BITS_PER_UNIT == 0
+ && base_misalignment % BITS_PER_UNIT == 0);
+ base_alignment /= BITS_PER_UNIT;
+ base_misalignment /= BITS_PER_UNIT;
+
if (TREE_CODE (base) == MEM_REF)
{
if (!integer_zerop (TREE_OPERAND (base, 1)))
{
+ /* Subtract MOFF from the base and add it to POFFSET instead.
+ Adjust the misalignment to reflect the amount we subtracted. */
offset_int moff = mem_ref_offset (base);
+ base_misalignment -= moff.to_short_addr ();
tree mofft = wide_int_to_tree (sizetype, moff);
if (!poffset)
poffset = mofft;
@@ -855,20 +871,46 @@ dr_analyze_innermost (innermost_loop_behavior *drb, tree ref,
}
init = ssize_int (pbitpos / BITS_PER_UNIT);
+
+ /* Subtract any constant component from the base and add it to INIT instead.
+ Adjust the misalignment to reflect the amount we subtracted. */
split_constant_offset (base_iv.base, &base_iv.base, &dinit);
- init = size_binop (PLUS_EXPR, init, dinit);
+ init = size_binop (PLUS_EXPR, init, dinit);
+ base_misalignment -= TREE_INT_CST_LOW (dinit);
+
split_constant_offset (offset_iv.base, &offset_iv.base, &dinit);
- init = size_binop (PLUS_EXPR, init, dinit);
+ init = size_binop (PLUS_EXPR, init, dinit);
step = size_binop (PLUS_EXPR,
fold_convert (ssizetype, base_iv.step),
fold_convert (ssizetype, offset_iv.step));
- drb->base_address = canonicalize_base_object_address (base_iv.base);
+ base = canonicalize_base_object_address (base_iv.base);
+
+ /* See if get_pointer_alignment can guarantee a higher alignment than
+ the one we calculated above. */
+ unsigned int HOST_WIDE_INT alt_misalignment;
+ unsigned int alt_alignment;
+ get_pointer_alignment_1 (base, &alt_alignment, &alt_misalignment);
+
+ /* As above, these values must be whole bytes. */
+ gcc_assert (alt_alignment % BITS_PER_UNIT == 0
+ && alt_misalignment % BITS_PER_UNIT == 0);
+ alt_alignment /= BITS_PER_UNIT;
+ alt_misalignment /= BITS_PER_UNIT;
+
+ if (base_alignment < alt_alignment)
+ {
+ base_alignment = alt_alignment;
+ base_misalignment = alt_misalignment;
+ }
+ drb->base_address = base;
drb->offset = fold_convert (ssizetype, offset_iv.base);
drb->init = init;
drb->step = step;
+ drb->base_alignment = base_alignment;
+ drb->base_misalignment = base_misalignment & (base_alignment - 1);
drb->offset_alignment = highest_pow2_factor (offset_iv.base);
drb->step_alignment = highest_pow2_factor (step);
@@ -1085,6 +1127,9 @@ create_data_ref (loop_p nest, loop_p loop, tree memref, gimple *stmt,
print_generic_expr (dump_file, DR_INIT (dr), TDF_SLIM);
fprintf (dump_file, "\n\tstep: ");
print_generic_expr (dump_file, DR_STEP (dr), TDF_SLIM);
+ fprintf (dump_file, "\n\tbase alignment: %d", DR_BASE_ALIGNMENT (dr));
+ fprintf (dump_file, "\n\tbase misalignment: %d",
+ DR_BASE_MISALIGNMENT (dr));
fprintf (dump_file, "\n\toffset alignment: %d",
DR_OFFSET_ALIGNMENT (dr));
fprintf (dump_file, "\n\tstep alignment: %d", DR_STEP_ALIGNMENT (dr));