------- 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

Reply via email to