Commit 468e1ef4 by Alexandre Oliva

[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
parent 894f597f
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
......
......@@ -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))
{
......
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
......
// { 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
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment