summaryrefslogtreecommitdiff
path: root/gcc/tree-sra.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2012-01-27 14:56:54 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2012-01-27 14:56:54 +0000
commit25b3bbad6624357c1ac6a31e0be6fca37182fb78 (patch)
tree32ec665bb53ff9c8bb80cf933b2e0e8513aab2ba /gcc/tree-sra.c
parenta598af2a9120feca416b38688593070db46cd07e (diff)
downloadgcc-25b3bbad6624357c1ac6a31e0be6fca37182fb78.tar.gz
2012-01-27 Richard Guenther <rguenther@suse.de>
PR tree-optimization/50444 * tree-sra.c (build_ref_for_offset): Properly adjust the MEM_REF type for unaligned accesses. * gcc.dg/torture/pr50444.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183630 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r--gcc/tree-sra.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index f4146b2acbc..fa67e94cca3 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1461,6 +1461,8 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
tree prev_base = base;
tree off;
HOST_WIDE_INT base_offset;
+ unsigned HOST_WIDE_INT misalign;
+ unsigned int align;
gcc_checking_assert (offset % BITS_PER_UNIT == 0);
@@ -1506,6 +1508,23 @@ build_ref_for_offset (location_t loc, tree base, HOST_WIDE_INT offset,
base = build_fold_addr_expr (unshare_expr (base));
}
+ /* If prev_base were always an originally performed access
+ we can extract more optimistic alignment information
+ by looking at the access mode. That would constrain the
+ alignment of base + base_offset which we would need to
+ adjust according to offset.
+ ??? But it is not at all clear that prev_base is an access
+ that was in the IL that way, so be conservative for now. */
+ align = get_pointer_alignment_1 (base, &misalign);
+ misalign += (double_int_sext (tree_to_double_int (off),
+ TYPE_PRECISION (TREE_TYPE (off))).low
+ * BITS_PER_UNIT);
+ misalign = misalign & (align - 1);
+ if (misalign != 0)
+ align = (misalign & -misalign);
+ if (align < TYPE_ALIGN (exp_type))
+ exp_type = build_aligned_type (exp_type, align);
+
return fold_build2_loc (loc, MEM_REF, exp_type, base, off);
}