vect: Enforce dr_with_seg_len::align precondition [PR116125]
tree-data-refs.cc uses alignment information to try to optimise the code generated for alias checks. The assumption for "normal" non-grouped, full-width scalar accesses was that the access size would be a multiple of the alignment. As Richi notes in the PR, this is a documented precondition of dr_with_seg_len: /* The minimum common alignment of DR's start address, SEG_LEN and ACCESS_SIZE. */ unsigned int align; PR115192 was a case in which this assumption didn't hold. The access was part of an aligned 4-element group, but only the first 2 elements of the group were accessed. The alignment was therefore double the access size. In r15-820-ga0fe4fb1c8d78045 I'd "fixed" that by capping the alignment in one of the output routines. But I think that was misconceived. The precondition means that we should cap the alignment at source instead. Failure to do that caused a similar wrong code bug in this PR, where the alignment comes from a short bitfield access rather than from a group access. gcc/ PR tree-optimization/116125 * tree-vect-data-refs.cc (vect_prune_runtime_alias_test_list): Make the dr_with_seg_len alignment fields describe tha access sizes as well as the pointer alignment. * tree-data-ref.cc (create_intersect_range_checks): Don't compensate for invalid alignment fields here. gcc/testsuite/ PR tree-optimization/116125 * gcc.dg/vect/pr116125.c: New test.
This commit is contained in:
parent
5ae621e2e8
commit
e8651b80ae
3 changed files with 38 additions and 3 deletions
30
gcc/testsuite/gcc.dg/vect/pr116125.c
Normal file
30
gcc/testsuite/gcc.dg/vect/pr116125.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "tree-vect.h"
|
||||
|
||||
struct st
|
||||
{
|
||||
unsigned int num : 8;
|
||||
};
|
||||
|
||||
void __attribute__((noipa))
|
||||
mem_overlap (struct st *a, struct st *b)
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
a[i].num = b[i].num + 1;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
check_vect ();
|
||||
|
||||
struct st a[9] = {};
|
||||
|
||||
// input a = 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
mem_overlap (&a[1], a);
|
||||
|
||||
// output a = 0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||
if (a[2].num == 2)
|
||||
return 0;
|
||||
else
|
||||
__builtin_abort ();
|
||||
}
|
|
@ -2647,8 +2647,6 @@ create_intersect_range_checks (class loop *loop, tree *cond_expr,
|
|||
if the maximum value of one segment is equal to the minimum
|
||||
value of the other. */
|
||||
min_align = std::min (dr_a.align, dr_b.align);
|
||||
min_align = std::min (min_align, known_alignment (dr_a.access_size));
|
||||
min_align = std::min (min_align, known_alignment (dr_b.access_size));
|
||||
cmp_code = LT_EXPR;
|
||||
}
|
||||
|
||||
|
|
|
@ -4074,7 +4074,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
|
|||
poly_uint64 lower_bound;
|
||||
tree segment_length_a, segment_length_b;
|
||||
unsigned HOST_WIDE_INT access_size_a, access_size_b;
|
||||
unsigned int align_a, align_b;
|
||||
unsigned HOST_WIDE_INT align_a, align_b;
|
||||
|
||||
/* Ignore the alias if the VF we chose ended up being no greater
|
||||
than the dependence distance. */
|
||||
|
@ -4231,6 +4231,13 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
|
|||
stmt_info_b->stmt);
|
||||
}
|
||||
|
||||
/* dr_with_seg_len requires the alignment to apply to the segment length
|
||||
and access size, not just the start address. The access size can be
|
||||
smaller than the pointer alignment for grouped accesses and bitfield
|
||||
references; see PR115192 and PR116125 respectively. */
|
||||
align_a = std::min (align_a, least_bit_hwi (access_size_a));
|
||||
align_b = std::min (align_b, least_bit_hwi (access_size_b));
|
||||
|
||||
dr_with_seg_len dr_a (dr_info_a->dr, segment_length_a,
|
||||
access_size_a, align_a);
|
||||
dr_with_seg_len dr_b (dr_info_b->dr, segment_length_b,
|
||||
|
|
Loading…
Add table
Reference in a new issue