summaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-17 09:00:23 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-17 09:00:23 +0000
commit5b99ff01d0f288316fb391c4053b25d769bce546 (patch)
tree4a30594d5197d1ab67d4bb385ff0565f90546283 /gcc/builtins.c
parentcdc58a668b4cdcbdd4cc885abcb52bad2aedd8b9 (diff)
downloadgcc-5b99ff01d0f288316fb391c4053b25d769bce546.tar.gz
2010-09-17 Richard Guenther <rguenther@suse.de>
PR middle-end/45678 * builtins.c (fold_builtin_memory_op): Always properly adjust alignment of memory accesses. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164356 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 2dd6119c782..384a81a035b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -8555,12 +8555,21 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
STRIP_NOPS (srcvar);
if (TREE_CODE (srcvar) == ADDR_EXPR
&& var_decl_component_p (TREE_OPERAND (srcvar, 0))
- && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
- && (!STRICT_ALIGNMENT
- || !destvar
- || src_align >= TYPE_ALIGN (desttype)))
- srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
- srcvar, off0);
+ && tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len))
+ {
+ if (!destvar
+ || src_align >= TYPE_ALIGN (desttype))
+ srcvar = fold_build2 (MEM_REF, destvar ? desttype : srctype,
+ srcvar, off0);
+ else if (!STRICT_ALIGNMENT)
+ {
+ srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
+ src_align);
+ srcvar = fold_build2 (MEM_REF, srctype, srcvar, off0);
+ }
+ else
+ srcvar = NULL_TREE;
+ }
else
srcvar = NULL_TREE;
@@ -8569,19 +8578,31 @@ fold_builtin_memory_op (location_t loc, tree dest, tree src,
if (srcvar == NULL_TREE)
{
- if (STRICT_ALIGNMENT
- && src_align < TYPE_ALIGN (desttype))
- return NULL_TREE;
STRIP_NOPS (src);
- srcvar = fold_build2 (MEM_REF, desttype, src, off0);
+ if (src_align >= TYPE_ALIGN (desttype))
+ srcvar = fold_build2 (MEM_REF, desttype, src, off0);
+ else
+ {
+ if (STRICT_ALIGNMENT)
+ return NULL_TREE;
+ srctype = build_aligned_type (TYPE_MAIN_VARIANT (desttype),
+ src_align);
+ srcvar = fold_build2 (MEM_REF, srctype, src, off0);
+ }
}
else if (destvar == NULL_TREE)
{
- if (STRICT_ALIGNMENT
- && dest_align < TYPE_ALIGN (srctype))
- return NULL_TREE;
STRIP_NOPS (dest);
- destvar = fold_build2 (MEM_REF, srctype, dest, off0);
+ if (dest_align >= TYPE_ALIGN (srctype))
+ destvar = fold_build2 (MEM_REF, srctype, dest, off0);
+ else
+ {
+ if (STRICT_ALIGNMENT)
+ return NULL_TREE;
+ desttype = build_aligned_type (TYPE_MAIN_VARIANT (srctype),
+ dest_align);
+ destvar = fold_build2 (MEM_REF, desttype, dest, off0);
+ }
}
expr = build2 (MODIFY_EXPR, TREE_TYPE (destvar), destvar, srcvar);