vect: Fix access size alignment assumption [PR115192]

create_intersect_range_checks checks whether two access ranges
a and b are alias-free using something equivalent to:

  end_a <= start_b || end_b <= start_a

It has two ways of doing this: a "vanilla" way that calculates
the exact exclusive end pointers, and another way that uses the
last inclusive aligned pointers (and changes the comparisons
accordingly).  The comment for the latter is:

      /* Calculate the minimum alignment shared by all four pointers,
	 then arrange for this alignment to be subtracted from the
	 exclusive maximum values to get inclusive maximum values.
	 This "- min_align" is cumulative with a "+ access_size"
	 in the calculation of the maximum values.  In the best
	 (and common) case, the two cancel each other out, leaving
	 us with an inclusive bound based only on seg_len.  In the
	 worst case we're simply adding a smaller number than before.

The problem is that the associated code implicitly assumed that the
access size was a multiple of the pointer alignment, and so the
alignment could be carried over to the exclusive end pointer.

The testcase started failing after g:9fa5b473b5b8e289b6542
because that commit improved the alignment information for
the accesses.

gcc/
	PR tree-optimization/115192
	* tree-data-ref.cc (create_intersect_range_checks): Take the
	alignment of the access sizes into account.

gcc/testsuite/
	PR tree-optimization/115192
	* gcc.dg/vect/pr115192.c: New test.

(cherry picked from commit a0fe4fb1c8d7804515845dd5d2a814b3c7a1ccba)
This commit is contained in:
Richard Sandiford 2024-05-31 08:22:55 +01:00
parent cd161b335c
commit 36575f5fe4
2 changed files with 32 additions and 1 deletions

View file

@ -0,0 +1,28 @@
#include "tree-vect.h"
int data[4 * 16 * 16] __attribute__((aligned(16)));
__attribute__((noipa)) void
foo (__SIZE_TYPE__ n)
{
for (__SIZE_TYPE__ i = 1; i < n; ++i)
{
data[i * n * 4] = data[(i - 1) * n * 4] + 1;
data[i * n * 4 + 1] = data[(i - 1) * n * 4 + 1] + 2;
}
}
int
main ()
{
check_vect ();
data[0] = 10;
data[1] = 20;
foo (3);
if (data[24] != 12 || data[25] != 24)
__builtin_abort ();
return 0;
}

View file

@ -73,6 +73,7 @@ along with GCC; see the file COPYING3. If not see
*/
#define INCLUDE_ALGORITHM
#include "config.h"
#include "system.h"
#include "coretypes.h"
@ -2640,7 +2641,9 @@ create_intersect_range_checks (class loop *loop, tree *cond_expr,
Because the maximum values are inclusive, there is an alias
if the maximum value of one segment is equal to the minimum
value of the other. */
min_align = MIN (dr_a.align, dr_b.align);
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;
}