re PR middle-end/58041 (Unaligned access to arrays in packed structure)
authorMartin Jambor <mjambor@suse.cz>
Tue, 6 Aug 2013 09:22:16 +0000 (11:22 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Tue, 6 Aug 2013 09:22:16 +0000 (11:22 +0200)
2013-08-06  Martin Jambor  <mjambor@suse.cz>

PR middle-end/58041
* gimple-ssa-strength-reduction.c (replace_ref): Make sure built
MEM_REF has proper alignment information.

testsuite/
* gcc.dg/torture/pr58041.c: New test.
* gcc.target/arm/pr58041.c: Likewise.

From-SVN: r201523

gcc/ChangeLog
gcc/gimple-ssa-strength-reduction.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr58041.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr58041.c [new file with mode: 0644]

index 394da1348b242596089910095bb1b14e60fa9ac7..6274c8bd56453af65c8b051df9cf1870d41dd1e4 100644 (file)
@@ -1,3 +1,9 @@
+2013-08-06  Martin Jambor  <mjambor@suse.cz>
+
+       PR middle-end/58041
+       * gimple-ssa-strength-reduction.c (replace_ref): Make sure built
+       MEM_REF has proper alignment information.
+
 2013-08-05  Oleg Endo <olegendo@gcc.gnu.org>
 
        PR other/12081
index c6f305c35eaaf563263559dc798264bd91db750c..e85e6293db412ec7e12fd0064333d6670c814a4b 100644 (file)
@@ -1728,11 +1728,23 @@ dump_incr_vec (void)
 static void
 replace_ref (tree *expr, slsr_cand_t c)
 {
-  tree add_expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (c->base_expr),
-                              c->base_expr, c->stride);
-  tree mem_ref = fold_build2 (MEM_REF, TREE_TYPE (*expr), add_expr,
-                             double_int_to_tree (c->cand_type, c->index));
-  
+  tree add_expr, mem_ref, acc_type = TREE_TYPE (*expr);
+  unsigned HOST_WIDE_INT misalign;
+  unsigned align;
+
+  /* Ensure the memory reference carries the minimum alignment
+     requirement for the data type.  See PR58041.  */
+  get_object_alignment_1 (*expr, &align, &misalign);
+  if (misalign != 0)
+    align = (misalign & -misalign);
+  if (align < TYPE_ALIGN (acc_type))
+    acc_type = build_aligned_type (acc_type, align);
+
+  add_expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (c->base_expr),
+                         c->base_expr, c->stride);
+  mem_ref = fold_build2 (MEM_REF, acc_type, add_expr,
+                        double_int_to_tree (c->cand_type, c->index));
+
   /* Gimplify the base addressing expression for the new MEM_REF tree.  */
   gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
   TREE_OPERAND (mem_ref, 0)
index e8ac8604c769fec14650dfc3ca008afc597f29e2..790c5568cdc23df765bd3539e4190b5348f54667 100644 (file)
@@ -1,3 +1,9 @@
+2013-08-06  Martin Jambor  <mjambor@suse.cz>
+
+       PR middle-end/58041
+       * gcc.dg/torture/pr58041.c: New test.
+       * gcc.target/arm/pr58041.c: Likewise.
+
 2013-08-06  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/57306
diff --git a/gcc/testsuite/gcc.dg/torture/pr58041.c b/gcc/testsuite/gcc.dg/torture/pr58041.c
new file mode 100644 (file)
index 0000000..e22ec3c
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+
+typedef long long V
+  __attribute__ ((vector_size (2 * sizeof (long long)), may_alias));
+
+typedef struct S { V v; } P __attribute__((aligned (1)));
+
+struct s
+{
+  char u;
+  V v[2];
+} __attribute__((packed,aligned(1)));
+
+__attribute__((noinline, noclone))
+long long foo(struct s *x, int y, V z)
+{
+  V a = x->v[y];
+  x->v[y] = z;
+  return a[1];
+}
+
+struct s a = {0,{0,0}};
+int main()
+{
+  V v1 = {0,1};
+  V v2 = {0,2};
+
+  if (foo(&a,0,v1) != 0)
+    __builtin_abort();
+  if (foo(&a,0,v2) != 1)
+    __builtin_abort();
+  if (foo(&a,1,v1) != 0)
+    __builtin_abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr58041.c b/gcc/testsuite/gcc.target/arm/pr58041.c
new file mode 100644 (file)
index 0000000..481a72b
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mno-unaligned-access" } */
+/* { dg-final { scan-assembler "ldrb" } } */
+/* { dg-final { scan-assembler "strb" } } */
+
+struct s
+{
+  char u;
+  long long v[2];
+} __attribute__((packed,aligned(1)));
+
+__attribute__((noinline, noclone))
+long long foo(struct s *x, int y, long long z)
+{
+  long long a = x->v[y];
+  x->v[y] = z;
+  return a;
+}
+
+struct s a = {0,{0,0}};
+int main()
+{
+  if (foo(&a,0,1) != 0)
+    __builtin_abort();
+  if (foo(&a,0,2) != 1)
+    __builtin_abort();
+  if (foo(&a,1,1) != 0)
+    __builtin_abort();
+  return 0;
+}