aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-11-02 10:20:07 -0800
committerRichard Henderson <rth@gcc.gnu.org>2005-11-02 10:20:07 -0800
commit525e67c1e839212666cbcec7c64ad77925472949 (patch)
treee2cced7f10ef56e2daf669d5da637210ada561c2
parentf85f1ca7b80e46fd145be68f0dffc87f661656ec (diff)
downloadgcc-525e67c1e839212666cbcec7c64ad77925472949.zip
gcc-525e67c1e839212666cbcec7c64ad77925472949.tar.gz
gcc-525e67c1e839212666cbcec7c64ad77925472949.tar.bz2
re PR target/24178 (generates code that produces unaligned access exceptions)
PR target/24178 * config/alpha/alpha.c (get_aligned_mem): Honor alignment given by MEM_ALIGN. From-SVN: r106388
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/alpha/alpha.c27
-rw-r--r--gcc/testsuite/gcc.target/alpha/pr24178.c13
3 files changed, 38 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e6d1b9c..f2b2f54 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2005-11-02 Richard Henderson <rth@redhat.com>
+
+ PR target/24178
+ * config/alpha/alpha.c (get_aligned_mem): Honor alignment given
+ by MEM_ALIGN.
+
2005-11-01 Richard Henderson <rth@redhat.com>
PR 21518
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 89b292c..ec53778 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1487,7 +1487,7 @@ void
get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum)
{
rtx base;
- HOST_WIDE_INT offset = 0;
+ HOST_WIDE_INT disp, offset;
gcc_assert (GET_CODE (ref) == MEM);
@@ -1495,23 +1495,34 @@ get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum)
&& ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
{
base = find_replacement (&XEXP (ref, 0));
-
gcc_assert (memory_address_p (GET_MODE (ref), base));
}
else
base = XEXP (ref, 0);
if (GET_CODE (base) == PLUS)
- offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
+ disp = INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
+ else
+ disp = 0;
+
+ /* Find the byte offset within an aligned word. If the memory itself is
+ claimed to be aligned, believe it. Otherwise, aligned_memory_operand
+ will have examined the base register and determined it is aligned, and
+ thus displacements from it are naturally alignable. */
+ if (MEM_ALIGN (ref) >= 32)
+ offset = 0;
+ else
+ offset = disp & 3;
- *paligned_mem
- = widen_memory_access (ref, SImode, (offset & ~3) - offset);
+ /* Access the entire aligned word. */
+ *paligned_mem = widen_memory_access (ref, SImode, -offset);
+ /* Convert the byte offset within the word to a bit offset. */
if (WORDS_BIG_ENDIAN)
- *pbitnum = GEN_INT (32 - (GET_MODE_BITSIZE (GET_MODE (ref))
- + (offset & 3) * 8));
+ offset = 32 - (GET_MODE_BITSIZE (GET_MODE (ref)) + offset * 8);
else
- *pbitnum = GEN_INT ((offset & 3) * 8);
+ offset *= 8;
+ *pbitnum = GEN_INT (offset);
}
/* Similar, but just get the address. Handle the two reload cases.
diff --git a/gcc/testsuite/gcc.target/alpha/pr24178.c b/gcc/testsuite/gcc.target/alpha/pr24178.c
new file mode 100644
index 0000000..0a31aa7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/alpha/pr24178.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcpu=ev4" } */
+
+struct S {
+ long l;
+ unsigned char c;
+};
+unsigned long f(unsigned char *p10) {
+ struct S *p = (struct S *) (p10 + 10);
+ return p->c;
+}
+
+/* { dg-final { scan-assembler "ldl.*,18\\(" } } */