Iva*_*van 5 c optimization gcc compiler-optimization
为了知道gcc究竟如何进行优化,我编写了两个用-O2编译的程序,但是汇编代码有一些区别.在我的程序中,我想在循环中输出"hello",并在每个输出之间添加一些延迟.这两个程序仅用于说明我的问题,我知道我可以在程序1中使用volatile或asm来实现我的目的.
计划1
#include <stdio.h>
int main(int argc, char **argv)
{
unsigned long i = 0;
while (1) {
if (++i > 0x1fffffffUL) {
printf("hello\n");
i = 0;
}
}
}
Run Code Online (Sandbox Code Playgroud)
用-O2编译,汇编代码是:
Disassembly of section .text.startup:
00000000 <_main>:
#include <stdio.h>
int main(int argc, char **argv)
{
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 10 sub $0x10,%esp
9: e8 00 00 00 00 call e <_main+0xe>
e: 66 90 xchg %ax,%ax
10: c7 04 24 00 00 00 00 movl $0x0,(%esp)
17: e8 00 00 00 00 call 1c <_main+0x1c>
1c: eb f2 jmp 10 <_main+0x10>
1e: 90 nop
1f: 90 nop
Run Code Online (Sandbox Code Playgroud)
计划2
int main(int argc, char **argv)
{
unsigned long i = 0;
while (1) {
if (i > 0x1fffffffUL) {
printf("hello\n");
i = 0;
}
i++;
}
}
Run Code Online (Sandbox Code Playgroud)
用-O2编译,汇编代码是:
Disassembly of section .text.startup:
00000000 <_main>:
#include <stdio.h>
int main(int argc, char **argv)
{
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 10 sub $0x10,%esp
9: e8 00 00 00 00 call e <_main+0xe>
e: 31 c0 xor %eax,%eax
10: 83 c0 01 add $0x1,%eax
13: 3d ff ff ff 1f cmp $0x1fffffff,%eax
18: 76 f6 jbe 10 <_main+0x10>
1a: c7 04 24 00 00 00 00 movl $0x0,(%esp)
while (1) {
if (i > 0x1fffffffUL) {
printf("hello\n");
i = 0;
}
i++;
21: e8 00 00 00 00 call 26 <_main+0x26>
int main(int argc, char **argv)
{
unsigned long i = 0;
while (1) {
if (i > 0x1fffffffUL) {
26: 31 c0 xor %eax,%eax
28: eb e6 jmp 10 <_main+0x10>
printf("hello\n");
2a: 90 nop
2b: 90 nop
2c: 90 nop
2d: 90 nop
2e: 90 nop
2f: 90 nop
Run Code Online (Sandbox Code Playgroud)
在程序1中,增加了i
优化,但它不在程序2中.为什么会发生这种情况?gcc在为这两个程序优化-O2时使用了哪些规则?
问"为什么"关于优化通常是浪费时间,因为那里有没有"规则"通过优化操作-比其他"好像":优化程序可能无法更改代码一致的观察到的行为.
你的程序的"可观察行为"是反复打印"你好".
在您的第一个程序中,计数被优化掉,使得可观察的行为更快地发生.这是优化器的工作.请高兴您的代码现在更高效!
在你的第二个程序中,计数没有被优化掉,因为不知何故优化器 - 在这个版本的这个编译器中有这个设置 - 并没有看到它没有它.为什么?谁知道(除了编译器的优化器模块的维护者)?
如果您希望的行为是在输出之间有延迟,请使用类似thrd_sleep()的内容.空计数循环是在C64上延迟BASIC 2.0程序的一种方法,但它们不应该在C中使用,原因在于您刚才观察到的:您永远不知道优化程序的作用.