Hai*_*ile 64 c gcc disassembly compiler-optimization
我写了这个简单的C程序:
int main() {
int i;
int count = 0;
for(i = 0; i < 2000000000; i++){
count = count + 1;
}
}
Run Code Online (Sandbox Code Playgroud)
我想看看gcc编译器如何优化这个循环(显然添加1 2000000000次应该是"一次添加2000000000 ").所以:
GCC test.c的,然后time就a.out给出了:
real 0m7.717s
user 0m7.710s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
$ gcc -O2 test.c 然后time ona.out`给出:
real 0m0.003s
user 0m0.000s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)
然后我用两个人拆开了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
Run Code Online (Sandbox Code Playgroud)
L3添加,L2 -4(%rbp)与L3比较1999999999并循环到L3 if i < 2000000000.
现在优化的一个:
.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
Run Code Online (Sandbox Code Playgroud)
我根本无法理解那里发生了什么!我对装配知之甚少,但我期待类似的东西
addl $2000000000, -8(%rbp)
Run Code Online (Sandbox Code Playgroud)
我甚至尝试使用gcc -c -g -Wa,-a,-ad -O2 test.c来查看C代码以及它转换为的程序集,但结果不再清楚前一个.
有人能简单解释一下:
Mys*_*ial 73
编译器甚至比这更聪明.:)
实际上,它意识到你没有使用循环的结果.所以它完全取出了整个循环!
这称为死代码消除.
更好的测试是打印结果:
#include <stdio.h>
int main(void) {
int i; int count = 0;
for(i = 0; i < 2000000000; i++){
count = count + 1;
}
// Print result to prevent Dead Code Elimination
printf("%d\n", count);
}
Run Code Online (Sandbox Code Playgroud)
编辑:我添加了所需#include <stdio.h>; MSVC程序集列表对应于没有的版本#include,但它应该是相同的.
我现在没有GCC在我面前,因为我已经启动进入Windows.但这是使用printf()on MSVC 的版本的反汇编:
编辑:我有错误的汇编输出.这是正确的.
; 57 : int main(){
$LN8:
sub rsp, 40 ; 00000028H
; 58 :
; 59 :
; 60 : int i; int count = 0;
; 61 : for(i = 0; i < 2000000000; i++){
; 62 : count = count + 1;
; 63 : }
; 64 :
; 65 : // Print result to prevent Dead Code Elimination
; 66 : printf("%d\n",count);
lea rcx, OFFSET FLAT:??_C@_03PMGGPEJJ@?$CFd?6?$AA@
mov edx, 2000000000 ; 77359400H
call QWORD PTR __imp_printf
; 67 :
; 68 :
; 69 :
; 70 :
; 71 : return 0;
xor eax, eax
; 72 : }
add rsp, 40 ; 00000028H
ret 0
Run Code Online (Sandbox Code Playgroud)
是的,Visual Studio进行了这种优化.我认为GCC也可能会这样做.
是的,GCC执行类似的优化.这是gcc -S -O2 test.c(gcc 4.5.2,Ubuntu 11.10,x86)相同程序的汇编列表:
.file "test.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%d\n"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $2000000000, 8(%esp)
movl $.LC0, 4(%esp)
movl $1, (%esp)
call __printf_chk
leave
ret
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)