[PATCH] vect: Fix bogus alignment assumption in alias checks [PR94994]

Richard Sandiford richard.sandiford@arm.com
Thu Dec 31 15:51:26 GMT 2020


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.

Tested on aarch64-linux-gnu, aarch64_be-elf and x86_64-linux-gnu.
OK to install?

Richard


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 <stdint.h>
+#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.17.1



More information about the Gcc-patches mailing list