http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53916
Bug #: 53916 Summary: [mips16] divide operation compiled result incorrect with GCC-4.6.3 '-O2' option Classification: Unclassified Product: gcc Version: 4.6.3 Status: UNCONFIRMED Severity: major Priority: P3 Component: rtl-optimization AssignedTo: unassig...@gcc.gnu.org ReportedBy: anmin_d...@yahoo.com.tw A simple C code with a simple divide operation to have incorrect compile result with '-O2' option (hence incorrect run time execution result). The very same C code compile result is OK with '-Os' option. I have not tested with other version of GCC, the compiler in question is a cross compiler GCC-4.6.3, target: mips-elf, host/build: i686-pc-cygwin. Here is the details... === full command line options ===== $ /cygdrive/c/Progra~1/vendor/tool-chain4/bin/mipsel-vendor-elf-gcc -mips16 -mips4 -msym32 -membedded-data -muninit-const-in-rodata -mcode-readable=pcrel -fno-common -msoft-float -EL -ansi -Wall -Wextra -G 0 -O2 -S afvals.c -o afvals.O2.S -v -save-temps === full console output messages ===== Using built-in specs. COLLECT_GCC=/cygdrive/c/Progra~1/vendor/tool-chain4/bin/mipsel-vendor-elf-gcc COLLECT_LTO_WRAPPER=/cygdrive/c/Progra~1/vendor/tool-chain4/libexec/gcc/mipsel-vendor-elf/4.6.3/lto-wrapper.exe Target: mipsel-vendor-elf Configured with: ../gcc-4.6.3/configure NEWLIB_CFLAGS=-D_R3000 LDFLAGS=--static --prefix='/cygdrive/c/Progra~1/vendor/tool-chain4' --target=mipsel-vendor-elf --build=i686-pc-cygwin --host=i686-pc-cygwin --with-sysroot='/cygdrive/c/Progra~1/vendor/tool-chain4' --with-gnu-as --with-gnu-ld --with-float=hard --disable-threads --with-stabs --disable-nls --disable-shared --with-newlib --without-headers --disable-biendian --with-divide=breaks --without-llsc --without-synci --disable-initfini-array --enable-version-specific-runtime-libs --enable-languages=c,c++ --disable-libssp --disable-libquadmath --disable-libgomp --disable-lto --disable-add-ons --enable-target-optspace --disable-profile --disable-nss-crypt --disable-nss --enable-cloog-backend=isl --with-host-libstdcxx=-Wl,-Bstatic,-lstdc++ Thread model: single gcc version 4.6.3 COLLECT_GCC_OPTIONS='-mips16' '-mips4' '-msym32' '-membedded-data' '-muninit-const-in-rodata' '-mcode-readable=pcrel' '-fno-common' '-msoft-float' '-EL' '-ansi' '-Wall' '-Wextra' '-G' '0' '-O2' '-S' '-o' 'afvals.O2.S' '-v' '-save-temps' '-mdivide-breaks' '-mno-llsc' '-mno-synci' /cygdrive/c/Progra~1/vendor/tool-chain4/libexec/gcc/mipsel-vendor-elf/4.6.3/cc1.exe -E -quiet -v -imultilib soft-float afvals.c -G 0 -mel -mips16 -mips4 -msym32 -membedded-data -muninit-const-in-rodata -mcode-readable=pcrel -msoft-float -mdivide-breaks -mno-llsc -mno-synci -ansi -Wall -Wextra -fno-common -O2 -fpch-preprocess -o afvals.i ignoring nonexistent directory "/cygdrive/c/Progra~1/vendor/tool-chain4/usr/local/include" ignoring nonexistent directory "/cygdrive/c/Progra~1/vendor/tool-chain4/usr/include" #include "..." search starts here: #include <...> search starts here: /cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/include /cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/include-fixed /cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/../../../../mipsel-vendor-elf/include End of search list. COLLECT_GCC_OPTIONS='-mips16' '-mips4' '-msym32' '-membedded-data' '-muninit-const-in-rodata' '-mcode-readable=pcrel' '-fno-common' '-msoft-float' '-EL' '-ansi' '-Wall' '-Wextra' '-G' '0' '-O2' '-S' '-o' 'afvals.O2.S' '-v' '-save-temps' '-mdivide-breaks' '-mno-llsc' '-mno-synci' /cygdrive/c/Progra~1/vendor/tool-chain4/libexec/gcc/mipsel-vendor-elf/4.6.3/cc1.exe -fpreprocessed afvals.i -G 0 -mel -quiet -dumpbase afvals.c -mips16 -mips4 -msym32 -membedded-data -muninit-const-in-rodata -mcode-readable=pcrel -msoft-float -mdivide-breaks -mno-llsc -mno-synci -auxbase-strip afvals.O2.S -O2 -Wall -Wextra -ansi -version -fno-common -o afvals.O2.S GNU C version 4.6.3 (mipsel-vendor-elf) compiled by GNU C version 4.5.3, GMP version 5.0.4, MPFR version 3.1.0-p7, MPC version 0.9 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C version 4.6.3 (mipsel-vendor-elf) compiled by GNU C version 4.5.3, GMP version 5.0.4, MPFR version 3.1.0-p7, MPC version 0.9 GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 301b4a641126d25934d363679c94e6be COMPILER_PATH=/cygdrive/c/Progra~1/vendor/tool-chain4/libexec/gcc/mipsel-vendor-elf/4.6.3/:/cygdrive/c/Progra~1/vendor/tool-chain4/libexec/gcc/mipsel-vendor-elf/4.6.3/:/cygdrive/c/Progra~1/vendor/tool-chain4/libexec/gcc/mipsel-vendor-elf/:/cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/:/cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/:/cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/../../../../mipsel-vendor-elf/bin/ LIBRARY_PATH=/cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/soft-float/:/cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/../../../../mipsel-vendor-elf/lib/soft-float/:/cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/:/cygdrive/c/Progra~1/vendor/tool-chain4/lib/gcc/mipsel-vendor-elf/4.6.3/../../../../mipsel-vendor-elf/lib/:/cygdrive/c/Progra~1/vendor/tool-chain4/lib/ COLLECT_GCC_OPTIONS='-mips16' '-mips4' '-msym32' '-membedded-data' '-muninit-const-in-rodata' '-mcode-readable=pcrel' '-fno-common' '-msoft-float' '-EL' '-ansi' '-Wall' '-Wextra' '-G' '0' '-O2' '-S' '-o' 'afvals.O2.S' '-v' '-save-temps' '-mdivide-breaks' '-mno-llsc' '-mno-synci' === file contents of "afvals.i" ==== # 1 "afvals.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "afvals.c" unsigned short afx = 3; unsigned short afy = 2; extern unsigned int afval1[6]; extern unsigned int afval2[6]; unsigned int myarray1[16][16]; unsigned int myarray2[16][16]; void fs(void) { unsigned short c1; for (c1=0; c1<afx*afy; ++c1) { unsigned int x, y; x = c1 % afx; y = c1 / afx; myarray1[y][x] = afval1[c1]; myarray2[y][x] = afval2[c1]; } } === hints === If to use '-Os' option instead of '-O2' option or to insert "__asm__ volatile ("nop");" just after "y = c1 / afx;", the compile result will be OK. === The result assembly where I think incorrect ("nl afvals.O2.S") ==== ... 34 $L3: 35 move $3,$11 36 divu $0,$2,$3 37 bnez $3,1f ... 46 sll $3,$3,4 47 move $6,$9 48 addu $3,$3,$6 ... === 1. (major problem) the value of register "$9" is never initialized before line 47. Run time execution result of this code could be incorrect. 2. (minor issue) the divide operations have type "unsigned short" for both the operands and are supposed to be integer-promoted to "int". so the divide instruction should be 'div' instead of 'divu', no?