clang 是否优化了空体功能?
Do empty body functions get optimized by clang?
像这样:
static void MyFunction(int x, int y) {};
Clang 会在调用时优化它们吗?
当然可以,只要定义对调用站点的编译器可见即可。既然你已经宣布它 static
那可能永远都是真的。
当然有 -O3(实际上任何 != 0)
这取决于优化级别。如果您没有优化,那么 you'll probably still end up with a function. However, even with -O
you'll see it disappear. If your function were not marked static
it would be a bit more complicated because the function would need to exist for other translation units, so you might see an empty body,并且在同一个 TU 中省略了对它的调用,但函数本身必须仍然存在。
给定代码:
/* Optmizing empty functions */
static void myFunc(int x, int y);
int main(void)
{
int x=1, y=2;
myFunc(x, y);
return 0;
}
static void myFunc(int x, int y)
{
;
}
每个优化级别生成的程序集如下所示:
GCC - 带 -g 的优化级别 0(调试)
gcc emptyfunc.c -g -O0 -o emptyfunc.x
Dump of assembler code for function main:
0x0000000000000660 <+0>: push %rbp
0x0000000000000661 <+1>: mov %rsp,%rbp
0x0000000000000664 <+4>: sub [=11=]x10,%rsp
0x0000000000000668 <+8>: movl [=11=]x1,-0x4(%rbp)
0x000000000000066f <+15>: movl [=11=]x2,-0x8(%rbp)
0x0000000000000676 <+22>: mov -0x8(%rbp),%edx
0x0000000000000679 <+25>: mov -0x4(%rbp),%eax
0x000000000000067c <+28>: mov %edx,%esi
0x000000000000067e <+30>: mov %eax,%edi
0x0000000000000680 <+32>: callq 0x68c <myFunc>
0x0000000000000685 <+37>: mov [=11=]x0,%eax
0x000000000000068a <+42>: leaveq
0x000000000000068b <+43>: retq
End of assembler dump.
GCC - 优化级别 1
gcc emptyfunc.c -O1 -o emptyfunc-gccO1.x
Dump of assembler code for function main:
0x0000000000000660 <+0>: mov [=12=]x0,%eax
0x0000000000000665 <+5>: retq
End of assembler dump.
GCC - 优化级别 2、3、Os(大小)、Og(调试)和 Ofast
- gcc emptyfunc.c -O2 -o emptyfunc-gccO2.x
- gcc emptyfunc.c -O3 -o emptyfunc-gccO3.x
- gcc emptyfunc.c -Os -o emptyfunc-gccOs.x
- gcc emptyfunc.c -Og -o emptyfunc-gccOg.x
gcc emptyfunc.c -Ofast -o emptyfunc-gccOfast.x
Dump of assembler code for function main:
0x0000000000000530 <+0>: xor %eax,%eax
0x0000000000000532 <+2>: retq
End of assembler dump.
Clang - 带 -g 的优化级别 0(调试)
clang emptyfunc.c -o emptyfunc-clangO0.x -g -O0
Dump of assembler code for function main:
0x00000000004004c0 <+0>: push %rbp
0x00000000004004c1 <+1>: mov %rsp,%rbp
0x00000000004004c4 <+4>: sub [=14=]x10,%rsp
0x00000000004004c8 <+8>: movl [=14=]x0,-0x4(%rbp)
0x00000000004004cf <+15>: movl [=14=]x1,-0x8(%rbp)
0x00000000004004d6 <+22>: movl [=14=]x2,-0xc(%rbp)
0x00000000004004dd <+29>: mov -0x8(%rbp),%edi
0x00000000004004e0 <+32>: mov -0xc(%rbp),%esi
0x00000000004004e3 <+35>: callq 0x4004f0 <myFunc>
0x00000000004004e8 <+40>: xor %eax,%eax
0x00000000004004ea <+42>: add [=14=]x10,%rsp
0x00000000004004ee <+46>: pop %rbp
0x00000000004004ef <+47>: retq
End of assembler dump.
Clang - 优化级别 1、2、3,Os(大小),Ofast,Oz(大小 II)
- clang emptyfunc.c -o emptyfunc-clangO1.x -O1
- clang emptyfunc.c -o emptyfunc-clangO2.x -O2
- clang emptyfunc.c -o emptyfunc-clangO3.x -O3
- clang emptyfunc.c -o emptyfunc-clangOs.x -Os
- clang emptyfunc.c -o emptyfunc-clangOfast.x -Ofast
clang emptyfunc.c -o emptyfunc-clangOz.x -Oz
Dump of assembler code for function main:
0x00000000004004c0 <+0>: xor %eax,%eax
0x00000000004004c2 <+2>: retq
End of assembler dump.
如你所见,是的,当然会去掉空函数
像这样:
static void MyFunction(int x, int y) {};
Clang 会在调用时优化它们吗?
当然可以,只要定义对调用站点的编译器可见即可。既然你已经宣布它 static
那可能永远都是真的。
当然有 -O3(实际上任何 != 0)
这取决于优化级别。如果您没有优化,那么 you'll probably still end up with a function. However, even with -O
you'll see it disappear. If your function were not marked static
it would be a bit more complicated because the function would need to exist for other translation units, so you might see an empty body,并且在同一个 TU 中省略了对它的调用,但函数本身必须仍然存在。
给定代码:
/* Optmizing empty functions */
static void myFunc(int x, int y);
int main(void)
{
int x=1, y=2;
myFunc(x, y);
return 0;
}
static void myFunc(int x, int y)
{
;
}
每个优化级别生成的程序集如下所示:
GCC - 带 -g 的优化级别 0(调试)
gcc emptyfunc.c -g -O0 -o emptyfunc.x
Dump of assembler code for function main: 0x0000000000000660 <+0>: push %rbp 0x0000000000000661 <+1>: mov %rsp,%rbp 0x0000000000000664 <+4>: sub [=11=]x10,%rsp 0x0000000000000668 <+8>: movl [=11=]x1,-0x4(%rbp) 0x000000000000066f <+15>: movl [=11=]x2,-0x8(%rbp) 0x0000000000000676 <+22>: mov -0x8(%rbp),%edx 0x0000000000000679 <+25>: mov -0x4(%rbp),%eax 0x000000000000067c <+28>: mov %edx,%esi 0x000000000000067e <+30>: mov %eax,%edi 0x0000000000000680 <+32>: callq 0x68c <myFunc> 0x0000000000000685 <+37>: mov [=11=]x0,%eax 0x000000000000068a <+42>: leaveq 0x000000000000068b <+43>: retq End of assembler dump.
GCC - 优化级别 1
gcc emptyfunc.c -O1 -o emptyfunc-gccO1.x
Dump of assembler code for function main: 0x0000000000000660 <+0>: mov [=12=]x0,%eax 0x0000000000000665 <+5>: retq End of assembler dump.
GCC - 优化级别 2、3、Os(大小)、Og(调试)和 Ofast
- gcc emptyfunc.c -O2 -o emptyfunc-gccO2.x
- gcc emptyfunc.c -O3 -o emptyfunc-gccO3.x
- gcc emptyfunc.c -Os -o emptyfunc-gccOs.x
- gcc emptyfunc.c -Og -o emptyfunc-gccOg.x
gcc emptyfunc.c -Ofast -o emptyfunc-gccOfast.x
Dump of assembler code for function main: 0x0000000000000530 <+0>: xor %eax,%eax 0x0000000000000532 <+2>: retq End of assembler dump.
Clang - 带 -g 的优化级别 0(调试)
clang emptyfunc.c -o emptyfunc-clangO0.x -g -O0
Dump of assembler code for function main: 0x00000000004004c0 <+0>: push %rbp 0x00000000004004c1 <+1>: mov %rsp,%rbp 0x00000000004004c4 <+4>: sub [=14=]x10,%rsp 0x00000000004004c8 <+8>: movl [=14=]x0,-0x4(%rbp) 0x00000000004004cf <+15>: movl [=14=]x1,-0x8(%rbp) 0x00000000004004d6 <+22>: movl [=14=]x2,-0xc(%rbp) 0x00000000004004dd <+29>: mov -0x8(%rbp),%edi 0x00000000004004e0 <+32>: mov -0xc(%rbp),%esi 0x00000000004004e3 <+35>: callq 0x4004f0 <myFunc> 0x00000000004004e8 <+40>: xor %eax,%eax 0x00000000004004ea <+42>: add [=14=]x10,%rsp 0x00000000004004ee <+46>: pop %rbp 0x00000000004004ef <+47>: retq End of assembler dump.
Clang - 优化级别 1、2、3,Os(大小),Ofast,Oz(大小 II)
- clang emptyfunc.c -o emptyfunc-clangO1.x -O1
- clang emptyfunc.c -o emptyfunc-clangO2.x -O2
- clang emptyfunc.c -o emptyfunc-clangO3.x -O3
- clang emptyfunc.c -o emptyfunc-clangOs.x -Os
- clang emptyfunc.c -o emptyfunc-clangOfast.x -Ofast
clang emptyfunc.c -o emptyfunc-clangOz.x -Oz
Dump of assembler code for function main: 0x00000000004004c0 <+0>: xor %eax,%eax 0x00000000004004c2 <+2>: retq End of assembler dump.
如你所见,是的,当然会去掉空函数