Какие исключения для __always_inline и __never_inline в g cc? - PullRequest
3 голосов
/ 08 апреля 2020

Андрей Александреску упомянул в своем выступлении , которое он представил на cppcon , что g cc не всегда встраивается, когда тогда определяется и используется встроенный макрос __ всегда, и наоборот для __never_inline. Я не смог найти много документации о том, в каком сценарии ios происходит, так что кто-то скажет мне?

1 Ответ

4 голосов
/ 08 апреля 2020

Я не смог найти много документации о том, в каком сценарии ios происходит, так что кто-то скажет мне?

Не могли бы вы привести пример кода?

Передача функции в качестве указателя на функцию и вызов ее из другой единицы перевода (даже из той же единицы перевода, предполагая, что оптимизация равна -O0 или -Os, и она лучше подходит для размера или, как на самом деле просто .. . "lucky") будет эффективно запрещать возможность встраивания функции:

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

Компилировать и проверять:

$ 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 

Вы все еще можете оптимизировать для единиц перевода с помощью 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

Что касается __attribute__((__noinline__)), я не встречал возможного случая, когда g cc предпочел бы встроить функцию __noinline__.

...