[gcc r11-11465] vect: Fix access size alignment assumption [PR115192]
Richard Sandiford
rsandifo@gcc.gnu.org
Tue Jun 4 12:47:50 GMT 2024
https://gcc.gnu.org/g:741ea10418987ac02eb8e680f2946a6e5928eb23
commit r11-11465-g741ea10418987ac02eb8e680f2946a6e5928eb23
Author: Richard Sandiford <richard.sandiford@arm.com>
Date: Tue Jun 4 13:47:34 2024 +0100
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.c (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)
Diff:
---
gcc/testsuite/gcc.dg/vect/pr115192.c | 28 ++++++++++++++++++++++++++++
gcc/tree-data-ref.c | 5 ++++-
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/gcc/testsuite/gcc.dg/vect/pr115192.c b/gcc/testsuite/gcc.dg/vect/pr115192.c
new file mode 100644
index 00000000000..923d377c1bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr115192.c
@@ -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;
+}
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index b3dd2f0ca41..d127aba8792 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -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"
@@ -2629,7 +2630,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;
}
More information about the Gcc-cvs
mailing list