我写了一个简单的C程序:
int main() {
int i;
int count = 0;
for(i = 0; i < 2000000000; i++){
count = count + 1;
}
}
我想看看GCC编译器是如何优化这个循环的(显然加2000000000次应该是"加2000000000一次").因此:
a.out
上的gcc test.c和time
给出:
real 0m7.717s
user 0m7.710s
sys 0m0.000s
$ gcc -O2 test.c,然后time on
a.out`给出:
real 0m0.003s
user 0m0.000s
sys 0m0.000s
然后我用gcc -S
把它们拆开.第一点似乎很清楚:
.file "test.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl $0, -8(%rbp)
movl $0, -4(%rbp)
jmp .L2
.L3:
addl $1, -8(%rbp)
addl $1, -4(%rbp)
.L2:
cmpl $1999999999, -4(%rbp)
jle .L3
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
.section .note.GNU-stack,"",@progbits
L3相加,L2比较-4(%rbp)
和1999999999
,如果是i < 2000000000
,则循环到L3.
Now the optimized one:
.file "test.c"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
rep
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
.section .note.GNU-stack,"",@progbits
我完全不明白那里发生了什么!我对组装知之甚少,但我希望
addl $2000000000, -8(%rbp)
我甚至试着用gcc -c -g -Wa,-a,-ad -O2 test.c来查看C代码及其转换成的程序集,但结果与前一个不一样.
Can someone briefly explain:
- gcc -S -O2输出.
- 如果循环像我预期的那样进行了优化(一次求和而不是多次求和)?