Using __asm__ in what looks like a legal way produces code that is missing an initialization. Environment: System: Linux fred.ninemoons.com 2.4.20-18.9 #1 Thu May 29 06:54:41 EDT 2003 i686 athlon i386 GNU/Linux Architecture: i686 host: i686-pc-linux-gnu build: i686-pc-linux-gnu target: i686-pc-linux-gnu configured with: /src/sourceware/gcc/gcc/configure -v --prefix=/usr/local/sourceware --enable-languages=c,c++ How-To-Repeat: Given the following source, which has MIPS assembly, but exposes a bug in the current CVS gcc for other hosts like x86: static __inline__ void __delay(unsigned long loops) { __asm__ __volatile__ ( ".set\tnoreorder\n" "1:\tbnez\t%1,1b\n\t" "subu\t%0,1\n\t" ".set\treorder" : "+r" (loops) : "0" (loops)); } void func () { __delay(50000); } Compile to assembly with both the current RedHat 9.0 gcc and the latest CVS gcc: $ /usr/bin/gcc -S -O2 m.c $ mv m.s m.s.good $ /usr/local/sourceware/bin/gcc -S -O2 m.c $ mv m.s m.s.bad and then note that the initialization of "loops" to 50000 is missing for the current CVS gcc: $ diff -c m.s.good m.s.bad *** m.s.good 2003-06-18 14:36:28.000000000 -0700 --- m.s.bad 2003-06-18 14:37:03.000000000 -0700 *************** *** 1,20 **** .file "m.c" .text ! .p2align 2,,3 .globl func ! .type func,@function func: pushl %ebp movl %esp, %ebp - movl $50000, %eax #APP .set noreorder 1: bnez %eax,1b subu %eax,1 .set reorder #NO_APP ! leave ret ! .Lfe1: ! .size func,.Lfe1-func ! .ident "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)" --- 1,19 ---- .file "m.c" .text ! .p2align 4,,15 .globl func ! .type func, @function func: pushl %ebp movl %esp, %ebp #APP .set noreorder 1: bnez %eax,1b subu %eax,1 .set reorder #NO_APP ! popl %ebp ret ! .size func, .-func ! .section .note.GNU-stack,"",@progbits ! .ident "GCC: (GNU) 3.4 20030618 (experimental)"
I can confirm this on the mainline (20030618) but works as expect on 3.3.1 (20030616). See also http://gcc.gnu.org/ml/gcc/2003-06/msg00994.html to see how to change this to be valid and it still did not work.
This looks on the surface like a problem with inlining combined with "dead" code elimination. Does this snippet lose the loop initialization? If it doesn't then presumably inlining is responsible; if it does, it points elsewhere. :-) void func () { unsigned long loops = 50000 ; __asm__ __volatile__ ( ".set\tnoreorder\n" "1:\tbnez\t%1,1b\n\t" "subu\t%0,1\n\t" ".set\treorder" : "+r" (loops) : "0" (loops)); }
Also, is it initialized correctly at -O0, or with the __inline__ keyword removed?
Here is the reduced sources: void func () { unsigned long loops=10; __asm__ __volatile__ ( ".set\tnoreorder\n" "1:\tbnez\t%0,1b\n\t" "subu\t%0,1\n\t" ".set\treorder" : "+r" (loops) ); } And it works at -O0. This is with the mainline (20030719).
Fixed on the mainline (20030727).