On September 18, 2018 5:47:34 AM GMT+02:00, Alexandre Oliva <ol...@adacore.com> wrote: >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)
I think so. We want to retain the alignment we'd extracted from the original ref. As you said the indirection is spuirously introduced by the compiler. > >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. OK. Richard. >From: Richard Biener <rguent...@suse.de> >for gcc/ChangeLog > > PR middle-end/87054 > * gimplify.c (gimplify_expr): Retain alignment of > addressable lvalue in dereference. > >From: Alexandre Oliva <ol...@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 >+ } >+}