diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e6d1b9c6b5b1cc09aa992db21a624cd4fd83ad55..f2b2f54e377249d7cb67073d002a2c01cd5852a9 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 89b292c3d7f82fcc48ceddb202135a964e6c2467..ec53778ce1837488caf45cde777a3eb9b34d816f 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 0000000000000000000000000000000000000000..0a31aa7366ad2a86563747bedcb1a4c7b50a88e4 --- /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\\(" } } */