This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PR87054] fix unaligned access


Richard, this is the patch you proposed in the PR a while ago, along
with the testcase I'd posted.  Please let me know if the commit-message
paragraph below sounds good to you, and then I'll proceed to install it,
or amend as requested.  (do we really want the MEM_REF to carry stricter
alignment than the base type?  I'd have retained the object's alignment
only for looser-than-type alignment)

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.

Regstrapped on x86_64-linux-gnu.

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.
---
 gcc/gimplify.c                 |    8 +++++++-
 gcc/testsuite/gcc.dg/pr87054.c |   29 +++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr87054.c

diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f0eb04a751ccc..509fc2f3f5be2 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/gcc.dg/pr87054.c b/gcc/testsuite/gcc.dg/pr87054.c
new file mode 100644
index 0000000000000..4ca2b62d2c7c9
--- /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
+  }
+}


-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free!         FSF Latin America board member
GNU Toolchain Engineer                Free Software Evangelist


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]