【发布时间】:2016-06-13 17:48:56
【问题描述】:
为了知道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;
}
}
}
用-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
程序 2
int main(int argc, char **argv)
{
unsigned long i = 0;
while (1) {
if (i > 0x1fffffffUL) {
printf("hello\n");
i = 0;
}
i++;
}
}
用-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
在程序1中,优化了i的增加,但在程序2中没有,为什么会出现这种情况?使用 -O2 对这两个程序进行优化时,gcc 使用什么规则?
【问题讨论】:
-
可能是因为你的程序永远循环?
-
我认为这是因为通常很难在编译时检测到逻辑对行为没有影响。在某些极少数情况下是可能的,在大多数情况下不是。您的程序 1 似乎是幸运的案例之一。程序 2 不是。
-
请随时在 gcc 的 bugzilla 上提交增强请求。请注意,当您测试优化时,您应该避免使用
main函数:编译器知道它只会被调用一次,因此有时会对其进行较少的优化(显然不是这次)。 -
这是一个bug,我已经把它归档到gcc的bugzilla,参考here。我想它可能会在以后修复。
标签: c gcc optimization compiler-optimization