所以我一直在看一些在GCC中的O3
的一些魔術(其實我正在使用Clang進行編譯,但它與GCC一樣,我猜猜優化器的很大一部分是從GCC中拉出來的到Clang)。編譯器如何優化這個階乘函數?
考慮這個C程序:
int foo(int n) {
if (n == 0) return 1;
return n * foo(n-1);
}
int main() {
return foo(10);
}
的第一件事,我非常WOW-ED的(這也是在這個問題WOW-ED - https://stackoverflow.com/a/414774/1068248)是如何int foo(int)
(基本的階乘函數)編譯進入一個緊密的循環。這是它的ARM組件:
.globl _foo
.align 2
.code 16
.thumb_func _foo
_foo:
mov r1, r0
movs r0, #1
cbz r1, LBB0_2
LBB0_1:
muls r0, r1, r0
subs r1, #1
bne LBB0_1
LBB0_2:
bx lr
Blimey我想。這很有趣!完全緊密循環做階乘。哇。這不是一個尾巴呼叫優化,因爲它不是尾巴呼叫。但它似乎做了很多類似的優化。
現在看main
:
.globl _main
.align 2
.code 16
.thumb_func _main
_main:
movw r0, #24320
movt r0, #55
bx lr
這只是吹了我的心是誠實的。這只是完全繞過foo
並返回3628800
這是10!
。
這讓我真正意識到你的編譯器通常可以做得比你在優化代碼方面做得更好。但它提出了這樣一個問題,它如何做到這麼好做?所以,任何人都可以解釋(可能通過鏈接到相關的代碼)以下的優化是如何工作的:
初始
foo
優化是一個緊密的循環。優化
main
只是去並直接返回結果,而不是實際執行foo
。
此問題的另一個有趣的副作用是顯示一些GCC/Clang可以做的更有趣的優化。
優秀的答案!是的,主要的優化確實可以用常數相乘來代替,這樣一個很容易。我喜歡你通過'foo'優化:-)。 – mattjgalloway 2012-01-15 12:59:20