aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
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 /gcc/gimplify.c
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
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c8
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))
{