diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 641e3591040ffeaa3283aa0786a36434bd3b188a..361dfc468a1712dffb58657cd18a3c16bfe5a19a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f0eb04a751ccc64ebeb5ba695ebf31f7b5758cec..509fc2f3f5be20985558e8b4f2e94a7cbf814567 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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))
     {
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c7c8e90b27c5670f7264285d75f3e2ef417201d7..a0a08a4d499856a1cb8712b3851c66a01e566cb5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000000000000000000000000000000000000..4ca2b62d2c7c97516c7032dd3f253cde4986127e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr87054.c
@@ -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
+  }
+}