diff options
author | Alexandre Oliva <aoliva@gcc.gnu.org> | 2018-09-20 19:34:44 +0000 |
---|---|---|
committer | Alexandre Oliva <aoliva@gcc.gnu.org> | 2018-09-20 19:34:44 +0000 |
commit | 468e1ef4be47810052687c8193d106e591c74bc4 (patch) | |
tree | 420d98d2ccab135a9a94d7371b6f9f0f1ae6acd6 /gcc/gimplify.c | |
parent | 894f597f8fb8693a5d0f5834e98a8ccebbbb9106 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 8 |
1 files changed, 7 insertions, 1 deletions
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)) { |