What are the exceptions for __always_inline and __never_inline in gcc?

Viewed 105

Andrei Alexandrescu mentioned in a talk that he presented at cppcon that gcc doesnt always inline when then __always inline macro is defined and used, and vice-versa for __never_inline. I couldn't find much documentation about which scenarios that occurs in, so someone tell me?

1 Answers

I couldn't find much documentation about which scenarios that occurs in, so someone tell me?

Could you give a code example?

Passing the function as a function pointer and calling it from a different translation unit (even from the same translation unit assuming optimization is -O0 or -Os and it's better for size or like really just... "lucky") will effectively disallow the possibility of inlining the function:

cat << EOF > main.c
__attribute__((__always_inline__))
static inline
void f(void) {
    printf("Hey buddy!\n");
}

extern void call_fp(void (*fp)(void));

int main() {
    call_fp(f);
}
EOF

cat << EOF > g.c
void call_fp(void (*fp)(void)) {
    printf("Hey pal!");
    fp();
}
EOF

Compile and inspect:

$ gcc -g -Ofast main.c g.c && objdump -S ./a.out | grep '<main>:\|<call_fp>:'
0000000000001050 <main>:
int main() {
    1050:   48 83 ec 08             sub    $0x8,%rsp
    call_fp(f);
    1054:   48 8d 3d 35 01 00 00    lea    0x135(%rip),%rdi        # 1190 <f>
################################### vvvvv NOT INLINED ###############
    105b:   e8 40 01 00 00          callq  11a0 <call_fp>
}
    1060:   31 c0                   xor    %eax,%eax
    1062:   48 83 c4 08             add    $0x8,%rsp
    1066:   c3                      retq   
    1067:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
    106e:   00 00
--
00000000000011a0 <call_fp>:
void call_fp(void (*fp)(void)) {
    11a0:   53                      push   %rbx
    printf("Hey pal!");
    11a1:   31 c0                   xor    %eax,%eax
void call_fp(void (*fp)(void)) {
    11a3:   48 89 fb                mov    %rdi,%rbx
    printf("Hey pal!");
    11a6:   48 8d 3d 62 0e 00 00    lea    0xe62(%rip),%rdi        # 200f <_IO_stdin_used+0xf>
    11ad:   e8 8e fe ff ff          callq  1040 <printf@plt>
    fp();
    11b2:   48 89 d8                mov    %rbx,%rax
}
    11b5:   5b                      pop    %rbx
    fp();
################################### vvvv NOT INLINED ####################
    11b6:   ff e0                   jmpq   *%rax
    11b8:   0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
    11bf:   00 

You could still optimize across translation units with LTO:

$ gcc -g -flto -Ofast main.c g.c && objdump -S ./a.out | grep '<main>:' -A30
int main() {
    1050:   48 83 ec 08             sub    $0x8,%rsp
void call_fp(void (*fp)(void)) {
    printf("Hey pal!");
    1054:   48 8d 3d a9 0f 00 00    lea    0xfa9(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>
    105b:   31 c0                   xor    %eax,%eax
    105d:   e8 de ff ff ff          callq  1040 <printf@plt>
    printf("Hey buddy!\n");
    1062:   48 8d 3d a4 0f 00 00    lea    0xfa4(%rip),%rdi        # 200d <_IO_stdin_used+0xd>
####################### Both call_fp() and f()  were inlined!!!!!!!!!!!!! 
    1069:   e8 c2 ff ff ff          callq  1030 <puts@plt>  
    call_fp(f);
}
    106e:   31 c0                   xor    %eax,%eax
    1070:   48 83 c4 08             add    $0x8,%rsp
    1074:   c3                      retq   
    1075:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
    107c:   00 00 00 
    107f:   90                      nop

As for __attribute__((__noinline__)) I did not encounter a possible case where gcc would rather choose to inline a __noinline__ function.

Related