From 9fa5b473b5b8e289b6542adfd5cfaddfb3036048 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 31 Dec 2020 16:51:33 +0000 Subject: [PATCH] vect: Fix bogus alignment assumption in alias checks [PR94994] This PR is about a case in which the vectoriser was feeding incorrect alignment information to tree-data-ref.c, leading to incorrect runtime alias checks. The alignment was taken from the TREE_TYPE of the DR_REF, which in this case was a COMPONENT_REF with a normally-aligned type. However, the underlying MEM_REF was only byte-aligned. This patch uses dr_alignment to calculate the (byte) alignment instead, just like we do when creating vector MEM_REFs. gcc/ PR tree-optimization/94994 * tree-vect-data-refs.c (vect_vfa_align): Use dr_alignment. gcc/testsuite/ PR tree-optimization/94994 * gcc.dg/vect/pr94994.c: New test. --- gcc/testsuite/gcc.dg/vect/pr94994.c | 61 +++++++++++++++++++++++++++++ gcc/tree-vect-data-refs.c | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/vect/pr94994.c diff --git a/gcc/testsuite/gcc.dg/vect/pr94994.c b/gcc/testsuite/gcc.dg/vect/pr94994.c new file mode 100644 index 00000000000..e98aeb090d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr94994.c @@ -0,0 +1,61 @@ +#include +#include "tree-vect.h" + +#define BLOCK_SIZE (sizeof (uint32_t)) + +struct unaligned { + uint32_t x; +} __attribute__((packed, may_alias)); + +static inline uint32_t +load_unaligned (const char *p) +{ + return ((struct unaligned *) p)->x; +} + +static inline void +store_unaligned (uint32_t x, char *p) +{ + ((struct unaligned *) p)->x = x; +} + +void __attribute__((noipa)) +copy (char *dst, const char *src, size_t n) +{ + for (size_t i = 0; i < n; i += BLOCK_SIZE) + store_unaligned (load_unaligned (src + i), dst + i); +} + +#define INPUT_SIZE 64 +#define MAX_STEP 32 + +char x[INPUT_SIZE + MAX_STEP]; + +int +main (void) +{ + check_vect (); + + for (unsigned int i = 1; i < MAX_STEP; ++i) + { + for (unsigned int j = 0; j < INPUT_SIZE + MAX_STEP; ++j) + x[j] = j + 10; + copy (x + i, x, INPUT_SIZE); + for (int j = 0; j < INPUT_SIZE + i; ++j) + { + int expected; + if (j < i) + expected = j + 10; + else if (i >= BLOCK_SIZE) + expected = j % i + 10; + else if ((j - i) % BLOCK_SIZE < i) + expected = x[j - i]; + else + expected = j - i + 10; + if (x[j] != expected) + __builtin_abort (); + } + } + + return 0; +} diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 137017091e8..5fe9cad4da8 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -3258,7 +3258,7 @@ vect_vfa_access_size (vec_info *vinfo, dr_vec_info *dr_info) static unsigned int vect_vfa_align (dr_vec_info *dr_info) { - return TYPE_ALIGN_UNIT (TREE_TYPE (DR_REF (dr_info->dr))); + return dr_alignment (dr_info->dr); } /* Function vect_no_alias_p. -- 2.30.2