Using this compiler: Reading specs from /usr/lib/gcc-lib/alpha-redhat-linux/2.96/specs gcc version 2.96 20000731 (Red Hat Linux 7.1 2.96-81) The optimizer combines two 32-bit stores (stl) in adjacent memory locations (in a struct, for instance) into one 64-bit store (stq) if you're storing zeroes. This is fine, unless the two 32-bit locations are not aligned on a 64-bit boundary. This test program shows the problem: #include <stdio.h> struct test { char * a; /* 8 bytes */ short int b; /* 2 bytes */ int c[2]; /* 8 bytes */ }; int main(int argc, char **argv) { struct test t = {argv[0], 0, { 0, 0 } }; printf("argv[0] is %s\n",t.a); return 0; } Compiled with the following flags, we get an unaligned access: gcc -O2 -o test test.c test(2636): unaligned trap at 00000001200005f8: 000000011ffff8fc 2d 31 argv[0] is ./test Looking at the assembler source for this program, we see: .file 1 "test.c" .set noat .set noreorder .section .rodata $LC0: .ascii "argv[0] is %s\12\0" .text .align 4 .globl main .ent main main: .frame $30,80,$26,0 .mask 0x4000000,-80 ldgp $29,0($27) $main..ng: lda $16,$LC0 lda $30,-80($30) ldq $2,0($17) ldl $1,56($30) stq $31,60($30) ; <---- problem fnop ldq $3,64($30) mov $2,$17 zapnot $1,252,$1 stq $26,0($30) .prologue 1 stq $2,48($30) stl $1,56($30) ldq $1,56($30) stq $3,32($30) stq $2,16($30) stq $1,24($30) jsr $26,printf ldgp $29,0($26) mov $31,$0 ldq $26,0($30) lda $30,80($30) ret $31,($26),1 .end main .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)" the line noted above is storing zero ($31) at an offset of 60 from the stack pointer ($30). 60 is not divisible by 8 and thus not 64-bit aligned, so doing a 64-bit store (stq) there causes an unaligned memory access exception. This occurs in the linux kernel in a few places, notably the nfs3 driver. If the program is changed so that the two 32-bit variables are assigned separately, the following happens: #include <stdio.h> struct test { char * a; /* 8 bytes */ short int b; /* 2 bytes */ int c[2]; /* 8 bytes */ }; int main(int argc, char **argv) { struct test t; t.a = argv[0]; t.b = 0; t.c[0] = 0; t.c[1] = 0; printf("argv[0] is %s\n",t.a); return 0; } Assembler output: .file 1 "test_ok.c" .set noat .set noreorder .section .rodata $LC0: .ascii "argv[0] is %s\12\0" .text .align 4 .globl main .ent main main: .frame $30,48,$26,0 .mask 0x4000000,-48 ldgp $29,0($27) $main..ng: lda $16,$LC0 lda $30,-48($30) ldq $2,0($17) ldl $1,24($30) stq $26,0($30) .prologue 1 mov $2,$17 stl $31,28($30) ; <---- the first 32-bit zero zapnot $1,252,$1 stl $31,32($30) ; <---- the second 32-bit zero stq $2,16($30) stl $1,24($30) jsr $26,printf ldgp $29,0($26) mov $31,$0 ldq $26,0($30) nop lda $30,48($30) ret $31,($26),1 .end main .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)" Now, in the lines above, the stq has been broken into two stl instructions, and no unaligned accesses occur. (This report is being sent to jakab and bugzilla instead of gcc.gnu.org's GNATS because it refers to Red Hat 7.1 in the gcc -v output) Will Woods was instrumental in finding problem and reporting it. Please direct any questions, to Will.Woods. --George
Should be fixed by: Tue Jan 2 10:47:38 2001 Richard Kenner <kenner.nyu.edu> * expr.c (store_constructor_field): Update ALIGN before calling store_constructor. This patch was actually in the src.rpm, though only as part of one of a few %ifarch ia64 patches. I'm moving it into separate patch and applying unconditionally on all arches for gcc-2.96-82.
Fixed in gcc-2.96-82.