While working on some Linux kernel code, I've found that functions that are declared as 'static inline' are having their arguments evaluated well before they are used. For example I have a function: static inline void trace(arg1, arg2) { if (unlikely(enabled)) { <use the arguments> } } To make this more concrete here is a simple .c program: #include <stdio.h> # define unlikely(x) __builtin_expect(!!(x), 0) int enabled = 0; struct foo { int value; }; struct foo a = { .value = 10 }; static inline evaluate(int value) { if (unlikely(enabled)) { printf("value is: %d\n", value); } } /* #define evaluate(val) \ do { \ if (unlikely(enabled)) { \ printf("value is: %d\n", val); \ } \ } while (0) */ int main() { evaluate((&a)->value); } With the macro commented out I get: 00000000004004cc <main>: 4004cc: 55 push %rbp 4004cd: 48 89 e5 mov %rsp,%rbp 4004d0: 48 83 ec 10 sub $0x10,%rsp 4004d4: 8b 3d 22 04 20 00 mov 0x200422(%rip),%edi # 6008fc <a> 4004da: e8 02 00 00 00 callq 4004e1 <evaluate> Thus, a is loaded before the call to 'evaluate' However, if i compile the macro version of 'evaluate' i get: 00000000004004cc <main>: 4004cc: 55 push %rbp 4004cd: 48 89 e5 mov %rsp,%rbp 4004d0: 48 83 ec 10 sub $0x10,%rsp 4004d4: 8b 05 ee 03 20 00 mov 0x2003ee(%rip),%eax # 6008c8 <enabled> 4004da: 85 c0 test %eax,%eax 4004dc: 0f 95 c0 setne %al 4004df: 0f b6 c0 movzbl %al,%eax 4004e2: 48 85 c0 test %rax,%rax 4004e5: 74 15 je 4004fc <main+0x30> 4004e7: 8b 35 c7 03 20 00 mov 0x2003c7(%rip),%esi # 6008b4 <a> 4004ed: bf f8 05 40 00 mov $0x4005f8,%edi 4004f2: b8 00 00 00 00 mov $0x0,%eax 4004f7: e8 bc fe ff ff callq 4003b8 <printf@plt> Thus, the load of 'a' happens after the 'unlikely' test as I would like it. It would be nice if gcc could optimize the 'unlikely' case in the 'static inline' function case. thanks.
The define and the static inline functions are not equivalent at all. #define evaluate(val) \ do { \ typeof(val) tmpval = val; \ if (unlikely(enabled)) { \ printf("value is: %d\n", tmpval); \ } \ } while (0) makes the define equivalent to the static inline funciton.
(In reply to comment #1) > The define and the static inline functions are not equivalent at all. Right, in general, but if the expressions are side-effect-free, gcc could move their evaluation farther down.
Fixed in GCC 5+ by r5-1146.