------- Comment #2 from matz at gcc dot gnu dot org 2010-06-18 15:58 ------- It's not SSA expand (might be exposed by it, don't know), but the bug is pre-existing already in 4.3:
long unsigned int D.2219; struct S116 va_arg_tmp.3; ... addr.0 = &va_arg_tmp.3; addr.4 = (long unsigned int *) addr.0; sse_addr.5 = (long unsigned int *) sse_addr.2; D.2214 = *sse_addr.5; *addr.4 = D.2214; addr.6 = (long unsigned int *) addr.0; D.2216 = addr.6 + 8; sse_addr.7 = (long unsigned int *) sse_addr.2; D.2218 = sse_addr.7 + 16; D.2219 = *D.2218; *D.2216 = D.2219; Here the second store is also a 8-byte store at offset 8 of a struct only 12 bytes long. The problem is in ix86_gimplify_va_arg (and friends). For the type in question (struct S116), we build this classes[] array: (gdb) p regclass $47 = {X86_64_SSE_CLASS, X86_64_SSE_CLASS, ... That's okay, for such structs we really need two words, and both are passed in registers (if available). But the construct_container constructs this container: (gdb) p debug_rtx(container) (parallel:BLK [ (expr_list:REG_DEP_TRUE (reg:DI 21 xmm0) (const_int 0 [0])) (expr_list:REG_DEP_TRUE (reg:DI 22 xmm1) (const_int 8 [0x8])) ]) So, we try to move the content at offset 0 in DImode (the register itself will be irrelevant here, as we're needing a temporary), which is still fine. But the register of slot 1 also has DImode, for moving the values at offset 8. This mode will be used to determine the type of the move instruction generated, and is the one where things become wrong. See the loop in ix86_gimplify_va_arg, starting here: for (i = 0; i < XVECLEN (container, 0); i++) { ... -- matz at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hubicka at gcc dot gnu dot | |org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44575