The g++ compiler for i386 target assumes that the stack is aligned by 16 when storing xmm registers to the stack. However, the stack is not aligned when compiling with option -Os (or with the Intel compiler). A misaligned memory operand to an XMM instruction causes a general protection exception. An example to reproduce the error is included below.
Suggested remedies: Either (1): Keep the stack pointer aligned by 16, even when compiling with option -Os and make this alignment an official requirement in the ABI (the ABI for IA32 Gnu is shamefully poorly documented!). This alignment is already a requirement in the Mac OS X IA32 ABI (http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/index.html#//apple_ref/doc/uid/TP40002521). It is preferred to have the same ABI for IA32/i386 on MacOS and Linux, BSD, etc. since they all use the Gnu compiler. Or (2): Make no assumptions about alignment of the stack. Align the stack pointer with an AND-instruction whenever an alignment higher than 4 is needed. (This is in accordance with the Windows IA32 ABI). Steps to reproduce: ---------- begin file e1.cpp ------------- #include <stdio.h> #include <emmintrin.h> // Example showing stack alignment error // compile with g++ v. 4.1.0: // g++ -m32 -Os -msse2 e1.cpp // ./a.out char * e1() { // This function assumes that the stack is aligned by 16 // This puts 0 in an XMM register and stores it on the stack: volatile __m128 dummy = _mm_set_ps1(0.f); return "OK"; } int main() { // This function calls e1() without proper alignment printf("%s %s \n", e1(), e1()); return 0; } ---------- end file e1.cpp ------------- compile this file with: g++ -m32 -Os -msse2 e1.cpp ./a.out ------------------------------ Expected output: OK OK Actual output: Segmentation fault ----------------------------- Cause of error: The instruction that generates the error is: movaps %xmm0,-16(%ebp) This instruction requires that the memory operand is aligned by 16, but there is only a 25% chance that %ebp is divisible by 16 when compiling with option -Os. The program works correctly when compiled with any other optimization option. Also works correctly when compiling for x64 platform. -------------------------------------------- I have submitted a bug report about the same issue to the Intel compiler developers. Issue # 369990 at premier.intel.com Whether you choose remedy (1) or (2) above should preferably be coordinated with the Intel compiler developers and with Apple, because this is an ABI issue and the solution must be standardized. -------------------------------------------- [EMAIL PROTECTED] t]# g++ -v -save-temps -m32 -Os -msse2 e1.cpp Using built-in specs. Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux Thread model: posix gcc version 4.1.0 20060304 (Red Hat 4.1.0-3) /usr/libexec/gcc/x86_64-redhat-linux/4.1.0/cc1plus -E -quiet -v -D_GNU_SOURCE e1.cpp -m32 -msse2 -mtune=generic -Os -fpch-preprocess -o e1.ii ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../x86_64-redhat-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../include/c++/4.1.0 /usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../include/c++/4.1.0/x86_64-redhat-linux /usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../include/c++/4.1.0/backward /usr/local/include /usr/lib/gcc/x86_64-redhat-linux/4.1.0/include /usr/include End of search list. /usr/libexec/gcc/x86_64-redhat-linux/4.1.0/cc1plus -fpreprocessed e1.ii -quiet -dumpbase e1.cpp -m32 -msse2 -mtune=generic -auxbase e1 -Os -version -o e1.s GNU C++ version 4.1.0 20060304 (Red Hat 4.1.0-3) (x86_64-redhat-linux) compiled by GNU C version 4.1.0 20060304 (Red Hat 4.1.0-3). GGC heuristics: --param ggc-min-expand=64 --param ggc-min-heapsize=63766 Compiler executable checksum: 145c15e175e7b5491c5723c9bdb452f1 as -V -Qy --32 -o e1.o e1.s GNU assembler version 2.16.91.0.6 (x86_64-redhat-linux) using BFD version 2.16.91.0.6 20060212 /usr/libexec/gcc/x86_64-redhat-linux/4.1.0/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../lib/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.1.0/32/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.1.0/32 -L/usr/lib/gcc/x86_64-redhat-linux/4.1.0/32 -L/usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib e1.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-redhat-linux/4.1.0/32/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.1.0/../../../../lib/crtn.o [EMAIL PROTECTED] t]# ./a.out Segmentation fault [EMAIL PROTECTED] t]# -- Summary: XMM alignment fault when compiling for i386 with -Os. Needs ABI specification. Product: gcc Version: 4.1.0 Status: UNCONFIRMED Severity: critical Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: agner at agner dot org GCC host triplet: x64 GCC target triplet: ia32 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27537