因此,當您在編譯C++時添加優化標誌時,其運行速度會更快,但這是如何工作的?有人可以解釋組裝中究竟發生了什麼嗎?編譯器在優化代碼時在做什麼?即-O2標誌
8
A
回答
13
這意味着您在編譯時讓編譯器做了額外的工作/分析,因此您可以在運行時獲得一些額外寶貴CPU週期的回報。可能最好用一個例子來解釋。
考慮一個循環是這樣的:
const int n = 5;
for (int i = 0; i < n; ++i)
cout << "bleh" << endl;
如果你編譯這個沒有優化,編譯器不會爲你做任何額外的工作 - 此代碼片段組件產生的將可能是文字翻譯成比較並跳轉指令。 (這不是最快的,只是最簡單的)
但是,如果使用優化編譯,編譯器可以很容易地inline
這個循環,因爲它知道上界永遠不能改變,因爲n
是const
。 (即它可以直接複製重複代碼5次而不是比較/檢查終止循環條件)。
下面是優化函數調用的另一個示例。下面是我的整個程序:
#include <stdio.h>
static int foo(int a, int b) {
return a * b;
}
int main(int argc, char** argv) {
fprintf(stderr, "%d\n", foo(10, 15));
return 0;
}
如果我在我的x86機器上使用gcc foo.c
沒有優化編譯這段代碼,我的組裝是這樣的:
movq %rsi, %rax
movl %edi, -4(%rbp)
movq %rax, -16(%rbp)
movl $10, %eax ; these are my parameters to
movl $15, %ecx ; the foo function
movl %eax, %edi
movl %ecx, %esi
callq _foo
; .. about 20 other instructions ..
callq _fprintf
在這裏,它沒有任何優化。它用我的常量值加載寄存器並調用我的foo
函數。但是,看看,如果我與-O2
標誌重新編譯:
movq (%rax), %rdi
leaq L_.str(%rip), %rsi
movl $150, %edx
xorb %al, %al
callq _fprintf
編譯器是非常聰明,它甚至不叫foo
了。它只是說明了它的回報價值。
0
在生成程序集之前,大多數優化都發生在編譯器的中間表示中。你一定要看看Agner Fog的Software optimization resources。第1章手冊第8章介紹了編譯器通過實例進行的優化。
相關問題
- 1. 編譯器標誌更改代碼行爲(O2,Ox)
- 2. 什麼時候編譯器優化我的代碼
- 3. - 預編譯標誌應該做什麼?
- 4. 爲什麼qmake在這種情況下添加-O1和-O2優化標誌?
- 5. 編譯器在這個彙編代碼中做了什麼?
- 6. 在VC是什麼的#pragma當量/ O2編譯選項的(優化速度)
- 7. GWT編譯代碼優化
- 8. 在優化的編譯的代碼
- 9. C#編譯器 - 在優化代碼標誌打開的情況下執行了哪些優化?
- 10. 編譯器爲什麼不優化?
- 11. 用優化標誌編譯C
- 12. Rust編譯器用`loop`和`true`做了什麼優化?
- 13. C#編譯器和JIT都做了什麼樣的優化?
- 14. xcache - 啓用編碼器/解碼器/優化器/彙編器是做什麼的?
- 15. 什麼是「DNS_BLOCK_ASSERTIONS」(C編譯器標誌)?
- 16. 'optimize'scala編譯器標誌是做什麼的?
- 17. 目標代碼文件ctr1.o在gcc編譯器中做什麼?
- 18. 什麼是C代碼通過和編譯/無優化?
- 19. 優化原生Android代碼 - 編譯器標記
- 20. 在分析代碼時,我應該使用匹配(gcc)編譯器優化標誌嗎?
- 21. 編譯器標誌在Eclipse
- 22. 什麼是代碼優化?
- 23. golang編譯器將做什麼時fmt.Println()
- 24. 什麼是在反應性擴展源代碼NO_PERF標誌做
- 25. 我相信-O2標誌讓我不得不在每臺機器上重新編譯。爲什麼?
- 26. 編譯器優化
- 27. 編譯器優化
- 28. 如何在代碼塊中向編譯器添加標誌?
- 29. LINQ在編譯器級別執行什麼類型的優化?
- 30. 沒有-O標誌,Python會做什麼優化?
非常酷!當你在調用函數時也有區別嗎? – kayla
@TidusSmith以更深入的示例更新了答案。希望你覺得它有用。 – yamafontes