aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@gcc.gnu.org>2018-09-20 19:34:44 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2018-09-20 19:34:44 +0000
commit468e1ef4be47810052687c8193d106e591c74bc4 (patch)
tree420d98d2ccab135a9a94d7371b6f9f0f1ae6acd6
parent894f597f8fb8693a5d0f5834e98a8ccebbbb9106 (diff)
downloadgcc-468e1ef4be47810052687c8193d106e591c74bc4.zip
gcc-468e1ef4be47810052687c8193d106e591c74bc4.tar.gz
gcc-468e1ef4be47810052687c8193d106e591c74bc4.tar.bz2
[PR87054] fix unaligned access
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
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/gimplify.c8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr87054.c29
4 files changed, 47 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 641e359..361dfc4 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 f0eb04a..509fc2f 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 c7c8e90..a0a08a4 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 0000000..4ca2b62
--- /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
+ }
+}