When using the recent debian 4.0 build (gcc version 4.0.2 20050806 (prerelease) (Debian 4.0.1-4)) I had some problems with a 64bit kernel. A cut down test case is: #define BUG_ON(x) asm volatile("tdnei %0,0" : : "r" (x)); static inline int bar(int val) { return val + 1; } int foo; void baz() { BUG_ON(bar(foo)); } gcc 3.4 sign extends before passing it to the inline assembly: .baz: ld 11,.LC0@toc(2) lwa 9,0(11) addi 9,9,1 extsw 9,9 tdnei 9,0 But gcc 4.0 has removed the sign extension: .baz: ld 11,.LC0@toc(2) lwz 9,0(11) addi 9,9,1 tdnei 9,0 gcc 4.0 does get it right with -fno-inline.
This is not a bug. The code you gave is equivalant to as that is what inlining does (3.4 had a bug in that it had an extra overhead as you noticed, which you thought was a feature): #define BUG_ON(x) asm volatile("tdnei %0,0" : : "r" (x)); int foo; void baz() { BUG_ON(foo+1); } So it will pick the SImode (32bit part) for the "r" selector. If you want the BUG_ON to take a signed extended (DImode) for the "r", use something like the following: #define BUG_ON(x) asm volatile("tdnei %0,0" : : "r" ((long long)x)); static inline int bar(int val) { return val + 1; } int foo; void baz() { BUG_ON(bar(foo)); } That will both work on 3.4 and 4.0.0 with no asm changes in both.
Thanks, after applying the suggested fix the kernel works.