【发布时间】:2018-07-18 13:58:03
【问题描述】:
以下是在 x86_64 上运行的一些简单测试,以显示使用内联语句时生成的汇编代码:
测试 1
static inline void
show_text(void)
{
printf("Hello\n");
}
int main(int argc, char *argv[])
{
show_text();
return 0;
}
和汇编程序:
gcc -O0 -fno-asynchronous-unwind-tables -S -masm=att main.c && less main.s
.file "main.c"
.text
.section .rodata
.LC0:
.string "Hello"
.text
.type show_text, @function
show_text:
pushq %rbp
movq %rsp, %rbp
leaq .LC0(%rip), %rdi
call puts@PLT
nop
popq %rbp
ret
.size show_text, .-show_text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
call show_text
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180312"
.section .note.GNU-stack,"",@progbits
测试 1 结果:编译器未考虑内联建议
测试 2
与测试 1 相同的代码,但带有 -O1 优化标志
gcc -O1 -fno-asynchronous-unwind-tables -S -masm=att main.c && less main.s
.file "main.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hello"
.text
.globl main
.type main, @function
main:
subq $8, %rsp
leaq .LC0(%rip), %rdi
call puts@PLT
movl $0, %eax
addq $8, %rsp
ret
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180312"
.section .note.GNU-stack,"",@progbits
测试 2 结果: 汇编器中不再定义 show_text 函数
测试 3 show_text 未声明为内联,-O1 优化标志
测试 3 结果: 汇编器中不再定义 show_text 函数,有或没有内联:生成的代码相同
测试 4
#include <stdio.h>
static inline void
show_text(void)
{
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
printf("Hello\n");
}
int main(int argc, char *argv[])
{
show_text();
show_text();
return 0;
}
产生:
gcc -O1 -fno-asynchronous-unwind-tables -S -masm=att main.c && less main.s
.file "main.c"
.text
.section .rodata
.LC0:
.string "Hello"
.text
.type show_text, @function
show_text:
pushq %rbp
movq %rsp, %rbp
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC0(%rip), %rdi
call puts@PLT
nop
popq %rbp
ret
.size show_text, .-show_text
.globl main
.type main, @function
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
call show_text
call show_text
movl $0, %eax
leave
ret
.size main, .-main
.ident "GCC: (GNU) 7.3.1 20180312"
.section .note.GNU-stack,"",@progbits
测试 4 结果: show_text 在汇编程序中定义,未考虑内联建议
我了解 inline 关键字不会强制内联。但是对于 Test 1 结果,什么可以防止 show_text 在 main 中替换代码?
到目前为止,我曾经在我的 C 源代码中内联一些小的静态函数。但从这些结果来看,它似乎毫无用处。
为什么我在使用一些现代编译器(并且可能编译优化代码)时要声明我的一些小函数static inline?
【问题讨论】:
-
优化时,GCC 可以并且确实生成内联代码,而不是在没有
inline关键字的情况下调用(足够小)静态函数。事实上,如果函数只被调用一次,它甚至可以为相当大的函数做到这一点。这就是您在测试 3 中看到的内容。 -
您是否为测试 4 尝试过更高级别的优化(
-O2或-O3)?结果有变化吗?