------- Comment #6 from falk at debian dot org 2005-10-15 15:04 ------- OK, let's have a look at this somewhat minimal example:
struct S { long l; unsigned char c; }; unsigned long f(unsigned char *p10) { struct S *p = (struct S *) (p10 + 10); return p->c; } What we want is of course: ldl v0,18(a0) and v0,0xff,v0 but we get: ldl v0,16(a0) extbl v0,0x2,v0 The problem comes from get_aligned_mem being passed (mem/s:QI (plus:DI (reg/v/f:DI 70 [ p10 ] (const_int 18 [0x12])) [0 S1 A64]) However, get_aligned_mem assumes the *base* without offset is aligned, so it generates bogus code. get_aligned_mem is being called from alpha_expand_mov_nobwx because aligned_memory_operand says "yeah" to the above rtx. aligned_memory_operand is supposed to do: ;; Return 1 if this memory address is a known aligned register plus ;; a constant. which is in fact what get_aligned_mem needs. However, the first thing aligned_memory_operand checks is if (MEM_ALIGN (op) >= 32) return 1; which happens to be true, since the base *with* offset is aligned. This check seems bogus, since the base is still unaligned. However, given the scary comments surrounding it I don't really dare touching it. Richard, can you give a hint? -- falk at debian dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rth at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24178