[PR87054] fix unaligned access
authorAlexandre Oliva <aoliva@gcc.gnu.org>
Thu, 20 Sep 2018 19:34:44 +0000 (19:34 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Thu, 20 Sep 2018 19:34:44 +0000 (19:34 +0000)
Building an ADDR_EXPR uses the canonical type to build the pointer
type, but then, as we dereference it, we lose track of lax alignment
known to apply to the dereferenced object.  This might not be a
problem in general, but it is when the compiler implicitly introduces
address taking and dereferencing, as it does for asm statements, and
as it may do in some loop optimizations.

From: Richard Biener <rguenther@suse.de>
for  gcc/ChangeLog

PR middle-end/87054
* gimplify.c (gimplify_expr): Retain alignment of
addressable lvalue in dereference.

From: Alexandre Oliva <oliva@adacore.com>
for  gcc/testsuite/ChangeLog

PR middle-end/87054
* gcc.dg/pr87054.c: New.

From-SVN: r264450

gcc/ChangeLog
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr87054.c [new file with mode: 0644]

index 641e3591040ffeaa3283aa0786a36434bd3b188a..361dfc468a1712dffb58657cd18a3c16bfe5a19a 100644 (file)
@@ -1,3 +1,9 @@
+2018-09-20  Richard Biener <rguenther@suse.de>
+
+       PR middle-end/87054
+       * gimplify.c (gimplify_expr): Retain alignment of
+       addressable lvalue in dereference.
+
 2018-09-20  Alexandre Oliva <aoliva@redhat.com>
 
        PR bootstrap/87013
index f0eb04a751ccc64ebeb5ba695ebf31f7b5758cec..509fc2f3f5be20985558e8b4f2e94a7cbf814567 100644 (file)
@@ -12538,9 +12538,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       /* An lvalue will do.  Take the address of the expression, store it
         in a temporary, and replace the expression with an INDIRECT_REF of
         that temporary.  */
+      tree ref_alias_type = reference_alias_ptr_type (*expr_p);
+      unsigned int ref_align = get_object_alignment (*expr_p);
+      tree ref_type = TREE_TYPE (*expr_p);
       tmp = build_fold_addr_expr_loc (input_location, *expr_p);
       gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
-      *expr_p = build_simple_mem_ref (tmp);
+      if (TYPE_ALIGN (ref_type) != ref_align)
+       ref_type = build_aligned_type (ref_type, ref_align);
+      *expr_p = build2 (MEM_REF, ref_type,
+                       tmp, build_zero_cst (ref_alias_type));
     }
   else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
     {
index c7c8e90b27c5670f7264285d75f3e2ef417201d7..a0a08a4d499856a1cb8712b3851c66a01e566cb5 100644 (file)
@@ -1,3 +1,8 @@
+2018-09-20  Alexandre Oliva <oliva@adacore.com>
+
+       PR middle-end/87054
+       * gcc.dg/pr87054.c: New.
+
 2018-09-20  Richard Sandiford  <richard.sandiford@arm.com>
 
        PR tree-optimization/87288
diff --git a/gcc/testsuite/gcc.dg/pr87054.c b/gcc/testsuite/gcc.dg/pr87054.c
new file mode 100644 (file)
index 0000000..4ca2b62
--- /dev/null
@@ -0,0 +1,29 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+#ifndef T
+# ifdef __SSE__
+#  define T __int128
+# else
+#  define T long
+# endif
+#endif
+#ifndef R
+# ifdef __SSE__
+#  define R "x"
+# else
+#  define R "r"
+# endif
+#endif
+
+
+typedef T A; // #define T to long or __int128
+struct B { char d; A c; } __attribute__((packed));
+struct B b[50]; // many elements to avoid loop unrolling
+
+int main () {
+  int i;
+  for (i = 0; i < sizeof(b) / sizeof(*b); i++) {
+    asm ("" : "+" R (b[i].c)); // #define R to "r" on ppc or "x" on x86_64
+  }
+}