On Fri, 7 Mar 2025, Richard Sandiford wrote: > 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. > > Tested on aarch64-linux-gnu & x86_64-linux-gnu. OK to install?
OK. Thanks, Richard. > Richard > > > 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. > --- > gcc/testsuite/gcc.dg/vect/pr116125.c | 30 ++++++++++++++++++++++++++++ > gcc/tree-data-ref.cc | 2 -- > gcc/tree-vect-data-refs.cc | 9 ++++++++- > 3 files changed, 38 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/vect/pr116125.c > > diff --git a/gcc/testsuite/gcc.dg/vect/pr116125.c > b/gcc/testsuite/gcc.dg/vect/pr116125.c > new file mode 100644 > index 00000000000..eab9efdc061 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/vect/pr116125.c > @@ -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 (); > +} > diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc > index 5decfb1abf5..18d9f0fa766 100644 > --- a/gcc/tree-data-ref.cc > +++ b/gcc/tree-data-ref.cc > @@ -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; > } > > diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc > index 6d5854ac7c7..eb43526094b 100644 > --- a/gcc/tree-vect-data-refs.cc > +++ b/gcc/tree-vect-data-refs.cc > @@ -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, > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)