aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/emit-rtl.c32
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr24178.c16
4 files changed, 49 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 00d54bc..ace409d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2010-08-09 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/45212
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Adjust
+ alignment from MEM_REF offset only if we took it from the
+ base object.
+
2010-08-09 Eric Fisher <joefoxreal@gmail.com>
* doc/sourcebuild.texi (vect_int_mult): Remove duplicate entry.
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index fe8de9b..91c5d857 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1587,29 +1587,31 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
else if (TREE_CODE (t) == MEM_REF)
{
tree op0 = TREE_OPERAND (t, 0);
- unsigned HOST_WIDE_INT aoff = BITS_PER_UNIT;
- if (host_integerp (TREE_OPERAND (t, 1), 1))
+ if (TREE_CODE (op0) == ADDR_EXPR
+ && (DECL_P (TREE_OPERAND (op0, 0))
+ || CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))))
{
- unsigned HOST_WIDE_INT ioff = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
- aoff = (ioff & -ioff) * BITS_PER_UNIT;
- }
- if (TREE_CODE (op0) == ADDR_EXPR && DECL_P (TREE_OPERAND (op0, 0)))
- align = MAX (align, DECL_ALIGN (TREE_OPERAND (op0, 0)));
- else if (TREE_CODE (op0) == ADDR_EXPR
- && CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)))
- {
- align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0)));
+ if (DECL_P (TREE_OPERAND (op0, 0)))
+ align = DECL_ALIGN (TREE_OPERAND (op0, 0));
+ else if (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)))
+ {
+ align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0)));
#ifdef CONSTANT_ALIGNMENT
- align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), align);
+ align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), align);
#endif
+ }
+ if (TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) != 0)
+ {
+ unsigned HOST_WIDE_INT ioff
+ = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
+ unsigned HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT;
+ align = MIN (aoff, align);
+ }
}
else
/* ??? This isn't fully correct, we can't set the alignment from the
type in all cases. */
align = MAX (align, TYPE_ALIGN (type));
-
- if (!integer_zerop (TREE_OPERAND (t, 1)) && aoff < align)
- align = aoff;
}
else if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 175f101..4455729 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2010-08-09 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/45212
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Adjust
+ alignment from MEM_REF offset only if we took it from the
+ base object.
+
+ * gcc.target/i386/pr24178.c: New testcase.
+
2010-08-08 Uros Bizjak <ubizjak@gmail.com>
* gcc.dg/20030107-1.c: Do not call cleanup-coverage-files.
diff --git a/gcc/testsuite/gcc.target/i386/pr24178.c b/gcc/testsuite/gcc.target/i386/pr24178.c
new file mode 100644
index 0000000..b1a9208
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr24178.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-rtl-expand" } */
+
+struct S {
+ int l;
+ unsigned char c;
+};
+unsigned long f(unsigned char *p10) {
+ struct S *p = (struct S *) (p10 + 10);
+ return p->c;
+}
+
+/* The p->c memory access should have alignment of 4 bytes. */
+
+/* { dg-final { scan-rtl-dump "MEM\[^\\n\]*A32" "expand" } } */
+/* { dg-final { cleanup-rtl-dump "expand" } } */