Я написал эту простую программу C:Как GCC оптимизирует неиспользуемую переменную, увеличивающуюся внутри цикла?
int main() {
int i;
int count = 0;
for(i = 0; i < 2000000000; i++){
count = count + 1;
}
}
Я хотел увидеть, как GCC компилятор оптимизирует этот цикл (очевидно, добавить 2000000000 раз должны быть «добавить один раз»). Итак:
НКУ test.c, а затем time
на a.out
дает:
real 0m7.717s
user 0m7.710s
sys 0m0.000s
$ НКУ -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
и петли на L3, если 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
Я не могу понять, что там происходит! У меня мало знаний о сборке, но я ожидал что-то вроде
addl $2000000000, -8(%rbp)
Я даже попытался с GCC -c -g -Wa, -a, -ad -O2 test.c, чтобы увидеть код C вместе с сборкой он был преобразован, но результат не был более ясным, чем предыдущий.
Может кто-нибудь вкратце объяснить:
- В Gcc -S -O2 выход.
- Если цикл оптимизирован, как я ожидал (одна сумма вместо многих сумм)?
Хороший вопрос кстати, и добро пожаловать в Stackoverflow! Это прекрасный пример превосходного первого вопроса. :) – Mysticial