gcc 优化选项 -O1 -O2 -O3 -Os 优先级
Gcc?編譯優化簡介?
? ? ? ?gcc?提供了為了滿足用戶不同程度的的優化需要,提供了近百種優化選項,用來對{編譯時間,目標文件長度,執行效率}這個三維模型進行不同的取舍和平衡。優化的方法不一而足,總體上將有以下幾類:
- 1)精簡操作指令;
- 2)盡量滿足cpu的流水操作;
- 3)通過對程序行為地猜測,重新調整代碼的執行順序;
- 4)充分使用寄存器;
- 5)對簡單的調用進行展開等等。? ??
? ? ? 想全部了解這些編譯選項,并在其中挑選適合的選項進行優化,無疑像個噩夢般的過程。單從gnu的官方網站上得到的手冊來看,描述依然比較蒼白,不足以完全了解選項的使用范圍和原理。(GCC?has?well?over?a?hundred?individual?optimization?flags?and?it?would?be?insane?to?try?and?describe?them?all)?
? ? ? 幸而gcc提供了從O0-O3以及Os這幾種不同的優化級別供大家選擇,在這些選項中,包含了大部分有效的編譯優化選項,并且可以在這個基礎上,對某些選項進行屏蔽或添加,從而大大降低了使用的難度,畢竟,在一定基礎上進行取舍,比萬事從頭開始要好得多。下面著重圍繞這幾個不同的級別進行簡單介紹。(由于gcc不同版本手冊差異比較大,以下主要以gcc-3.4.6為參考)?
?
少優化->多優化:
O0 -->> O1 -->> O2 -->> O3
-O0表示沒有優化,-O1為缺省值,-O3優化級別最高
英文解析:
`-O '?
`-O1 '?
????????????????Optimize. ?????Optimizing ??compilation ??takes ??somewhat ??more ??time, ??and ??a?
????????????????lot ??more ??memory ??for ??a ??large ??function.?
??
????????????????With ??`-O ', ??the ??compiler ??tries ??to ??reduce ??code ??size ??and ??execution?
????????????????time, ??without ??performing ??any ??optimizations ??that ??take ??a ??great ??deal?
????????????????of ??compilation ??time.?
??
????????????????`-O ' ??turns ??on ??the ??following ??optimization ??flags:?
???????????????????????????????-fdefer-pop ???
???????????????????????????????-fdelayed-branch ???
???????????????????????????????-fguess-branch-probability ???
???????????????????????????????-fcprop-registers ???
???????????????????????????????-floop-optimize ???
???????????????????????????????-fif-conversion ???
???????????????????????????????-fif-conversion2 ???
???????????????????????????????-ftree-ccp ???
???????????????????????????????-ftree-dce ???
???????????????????????????????-ftree-dominator-opts ???
???????????????????????????????-ftree-dse ???
???????????????????????????????-ftree-ter ???
???????????????????????????????-ftree-lrs ???
???????????????????????????????-ftree-sra ???
???????????????????????????????-ftree-copyrename ???
???????????????????????????????-ftree-fre ???
???????????????????????????????-ftree-ch ???
???????????????????????????????-funit-at-a-time ???
???????????????????????????????-fmerge-constants?
??
????????????????`-O ' ??also ??turns ??on ??`-fomit-frame-pointer ' ??on ??machines ??where ??doing?
????????????????so ??does ??not ??interfere ??with ??debugging.?
??
????????????????`-O ' ??doesn 't ??turn ??on ??`-ftree-sra ' ??for ??the ??Ada ??compiler. ?????This?
????????????????option ??must ??be ??explicitly ??specified ??on ??the ??command ??line ??to ??be?
????????????????enabled ??for ??the ??Ada ??compiler.?
??
`-O2 '?
????????????????Optimize ??even ??more. ?????GCC ??performs ??nearly ??all ??supported?
????????????????optimizations ??that ??do ??not ??involve ??a ??space-speed ??tradeoff. ?????The?
????????????????compiler ??does ??not ??perform ??loop ??unrolling ??or ??function ??inlining ??when?
????????????????you ??specify ??`-O2 '. ?????As ??compared ??to ??`-O ', ??this ??option ??increases?
????????????????both ??compilation ??time ??and ??the ??performance ??of ??the ??generated ??code.?
??
????????????????`-O2 ' ??turns ??on ??all ??optimization ??flags ??specified ??by ??`-O '. ?????It ??also?
????????????????turns ??on ??the ??following ??optimization ??flags:?
???????????????????????????????-fthread-jumps ???
???????????????????????????????-fcrossjumping ???
???????????????????????????????-foptimize-sibling-calls ???
???????????????????????????????-fcse-follow-jumps ?????-fcse-skip-blocks ???
???????????????????????????????-fgcse ?????-fgcse-lm ??????
???????????????????????????????-fexpensive-optimizations ???
???????????????????????????????-fstrength-reduce ???
???????????????????????????????-frerun-cse-after-loop ?????-frerun-loop-opt ???
???????????????????????????????-fcaller-saves ???
???????????????????????????????-fpeephole2 ???
???????????????????????????????-fschedule-insns ?????-fschedule-insns2 ???
???????????????????????????????-fsched-interblock ?????-fsched-spec ???
???????????????????????????????-fregmove ???
???????????????????????????????-fstrict-aliasing ???
???????????????????????????????-fdelete-null-pointer-checks ???
???????????????????????????????-freorder-blocks ?????-freorder-functions ???
???????????????????????????????-falign-functions ?????-falign-jumps ???
???????????????????????????????-falign-loops ?????-falign-labels ???
???????????????????????????????-ftree-vrp ???
???????????????????????????????-ftree-pre?
??
????????????????Please ??note ??the ??warning ??under ??`-fgcse ' ??about ??invoking ??`-O2 ' ??on?
????????????????programs ??that ??use ??computed ??gotos.?
??
`-O3 '?
????????????????Optimize ??yet ??more. ?????`-O3 ' ??turns ??on ??all ??optimizations ??specified ??by?
????????????????`-O2 ' ??and ??also ??turns ??on ??the ??`-finline-functions ',?
????????????????`-funswitch-loops ' ??and ??`-fgcse-after-reload ' ??options.?
??
`-O0 '?
????????????????Do ??not ??optimize. ?????This ??is ??the ??default.?
Os選項
http://hi.baidu.com/ah__fu/blog/item/cc9fd19b801948bdc9eaf4b3.html
在研究編譯驅動的makefile的時候,發現GCC的命令行里面有一個-Os的優化選項。
????遍查GCC文檔,發現了-O0, -O1, -O2, -O3,就是沒有發現-Os。
????祭出GOOGLE大法搜了一下,終于發現這篇文章說明了-Os的作用:
http://www.linuxjournal.com/article/7269
???原來-Os相當于-O2.5。是使用了所有-O2的優化選項,但又不縮減代碼尺寸的方法。
???詳細的說明如下:
Level 2.5 (-Os)
The special optimization level (-Os or size) enables all -O2 optimizations that do not increase code size; it puts the emphasis on size over speed. This includes all second-level optimizations, except for the alignment optimizations. The alignment optimizations skip space to align functions, loops, jumps and labels to an address that is a multiple of a power of two, in an architecture-dependent manner. Skipping to these boundaries can increase performance as well as the size of the resulting code and data spaces; therefore, these particular optimizations are disabled. The size optimization level is enabled as:
gcc -Os -o test test.c
In gcc 3.2.2, reorder-blocks is enabled at -Os, but in gcc 3.3.2 reorder-blocks is disabled.
補充:在GCC的官方文檔里又發現了關于-Os的說明:
http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html#Optimize-Options
?
-O0
-O0:?不做任何優化,這是默認的編譯選項。?
-O和-O1:
? ?對程序做部分編譯優化,對于大函數,優化編譯占用稍微多的時間和相當大的內存。使用本項優化,編譯器會嘗試減小生成代碼的尺寸,以及縮短執行時間,但并不執行需要占用大量編譯時間的優化。?
打開的優化選項:?
l?-fdefer-pop:延遲棧的彈出時間。當完成一個函數調用,參數并不馬上從棧中彈出,而是在多個函數被調用后,一次性彈出。?
l?-fmerge-constants:嘗試橫跨編譯單元合并同樣的常量(string?constants?and?floating?point?constants)?
l?-fthread-jumps:如果某個跳轉分支的目的地存在另一個條件比較,而且該條件比較包含在前一個比較語句之內,那么執行本項優化.根據條件是true或者false,前面那條分支重定向到第二條分支的目的地或者緊跟在第二條分支后面.?
l?-floop-optimize:執行循環優化,將常量表達式從循環中移除,簡化判斷循環的條件,并且optionally?do?strength-reduction,或者將循環打開等。在大型復雜的循環中,這種優化比較顯著。?
l?-fif-conversion:嘗試將條件跳轉轉換為等價的無分支型式。優化實現方式包括條件移動,min,max,設置標志,以及abs指令,以及一些算術技巧等。??
l?-fif-conversion2基本意義相同,沒有找到更多的解釋。?
l?-fdelayed-branch:這種技術試圖根據指令周期時間重新安排指令。?它還試圖把盡可能多的指令移動到條件分支前,?以便最充分的利用處理器的治理緩存。?
l?-fguess-branch-probability:當沒有可用的profiling?feedback或__builtin_expect時,編譯器采用隨機模式猜測分支被執行的可能性,并移動對應匯編代碼的位置,這有可能導致不同的編譯器會編譯出迥然不同的目標代碼。?
l?-fcprop-registers:因為在函數中把寄存器分配給變量,?所以編譯器執行第二次檢查以便減少調度依賴性(兩個段要求使用相同的寄存器)并且刪除不必要的寄存器復制操作。?
-O2:?是比O1更高級的選項,進行更多的優化。Gcc將執行幾乎所有的不包含時間和空間折中的優化。當設置O2選項時,編譯器并不進行循環打開()loop?unrolling以及函數內聯。與O1比較而言,O2優化增加了編譯時間的基礎上,提高了生成代碼的執行效率。?
O2打開所有的O1選項,并打開以下選項:?
l?-fforce-mem:在做算術操作前,強制將內存數據copy到寄存器中以后再執行。這會使所有的內存引用潛在的共同表達式,進而產出更高效的代碼,當沒有共同的子表達式時,指令合并將排出個別的寄存器載入。這種優化對于只涉及單一指令的變量,?這樣也許不會有很大的優化效果.?但是對于再很多指令(必須數學操作)中都涉及到的變量來說,?這會時很顯著的優化,?因為和訪問內存中的值相比?,處理器訪問寄存器中的值要快的多。?
l?-foptimize-sibling-calls:優化相關的以及末尾遞歸的調用。通常,?遞歸的函數調用可以被展開為一系列一般的指令,?而不是使用分支。?這樣處理器的指令緩存能夠加載展開的指令并且處理他們,?和指令保持為需要分支操作的單獨函數調用相比,?這樣更快。?
l?-fstrength-reduce:這種優化技術對循環執行優化并且刪除迭代變量。?迭代變量是捆綁到循環計數器的變量,?比如使用變量,?然后使用循環計數器變量執行數學操作的for-next循環。?
l?-fcse-follow-jumps:在公用子表達式消元時,當目標跳轉不會被其他路徑可達,則掃描整個的跳轉表達式。例如,當公用子表達式消元時遇到if...else...語句時,當條為false時,那么公用子表達式消元會跟隨著跳轉。???
l?-fcse-skip-blocks:與-fcse-follow-jumps類似,不同的是,根據特定條件,跟隨著cse跳轉的會是整個的blocks?
l?-frerun-cse-after-loop:在循環優化完成后,重新進行公用子表達式消元操作。?
l?-frerun-loop-opt:兩次運行循環優化?l?-fgcse:執行全局公用子表達式消除pass。這個pass還執行全局常量和copy?propagation。這些優化操作試圖分析生成的匯編語言代碼并且結合通用片段,?消除冗余的代碼段。如果代碼使用計算性的goto,?gcc指令推薦使用-fno-gcse選項。?
l-fgcse-lm:全局公用子表達式消除將試圖移動那些僅僅被自身存儲kill的裝載操作的位置。這將允許將循環內的load/store操作序列中的load轉移到循環的外面(只需要裝載一次),而在循環內改變成copy/store序列。在選中-fgcse后,默認打開。?
l?-fgcse-sm:當一個存儲操作pass在一個全局公用子表達式消除的后面,這個pass將試圖將store操作轉移到循環外面去。如果與-fgcse-lm配合使用,那么load/store操作將會轉變為在循環前load,在循環后store,從而提高運行效率,減少不必要的操作。?
l?-fgcse-las:全局公用子表達式消除pass將消除在store后面的不必要的load操作,這些load與store通常是同一塊存儲單元(全部或局部)?
l-fdelete-null-pointer-checks:通過對全局數據流的分析,識別并排出無用的對空指針的檢查。編譯器假設間接引用空指針將停止程序。?如果在間接引用之后檢查指針,它就不可能為空。?
l?-fexpensive-optimizations:進行一些從編譯的角度來說代價高昂的優化(這種優化據說對于程序執行未必有很大的好處,甚至有可能降低執行效率,具體不是很清楚)?
l?-fregmove:編譯器試圖重新分配move指令或者其他類似操作數等簡單指令的寄存器數目,以便最大化的捆綁寄存器的數目。這種優化尤其對雙操作數指令的機器幫助較大。?
l?-fschedule-insns:編譯器嘗試重新排列指令,用以消除由于等待未準備好的數據而產生的延遲。這種優化將對慢浮點運算的機器以及需要load?memory的指令的執行有所幫助,因為此時允許其他指令執行,直到load?memory的指令完成,或浮點運算的指令再次需要cpu。?l?
-fschedule-insns2:與-fschedule-insns相似。但是當寄存器分配完成后,會請求一個附加的指令計劃pass。這種優化對寄存器較小,并且load?memory操作時間大于一個時鐘周期的機器有非常好的效果。?
l?-fsched-interblock:這種技術使編譯器能夠跨越指令塊調度指令。?這可以非常靈活地移動指令以便等待期間完成的工作最大化。?
l?-fsched-spec-load:允許一些load指令進行一些投機性的動作。(具體不詳)相同功能的還有-fsched-spec-load-dangerous,允許更多的load指令進行投機性操作。這兩個選項在選中-fschedule-insns時默認打開。?
l?-fcaller-saves:通過存儲和恢復call調用周圍寄存器的方式,使被call調用的value可以被分配給寄存器,這種只會在看上去能產生更好的代碼的時候才被使用。(如果調用多個函數,?這樣能夠節省時間,?因為只進行一次寄存器的保存和恢復操作,?而不是在每個函數調用中都進行。)?
l?-fpeephole2:允許計算機進行特定的觀察孔優化(這個不曉得是什么意思),-fpeephole與-fpeephole2的差別在于不同的編譯器采用不同的方式,由的采用-fpeephole,有的采用-fpeephole2,也有兩種都采用的。?
l?-freorder-blocks:在編譯函數的時候重新安排基本的塊,目的在于減少分支的個數,提高代碼的局部性。?
l?-freorder-functions:在編譯函數的時候重新安排基本的塊,目的在于減少分支的個數,提高代碼的局部性。這種優化的實施依賴特定的已存在的信息:.text.hot用于告知訪問頻率較高的函數,.text.unlikely用于告知基本不被執行的函數。?
l?-fstrict-aliasing:這種技術強制實行高級語言的嚴格變量規則。?對于c和c++程序來說,?它確保不在數據類型之間共享變量.?例如,?整數變量不和單精度浮點變量使用相同的內存位置。?
l?-funit-at-a-time:在代碼生成前,先分析整個的匯編語言代碼。這將使一些額外的優化得以執行,但是在編譯器間需要消耗大量的內存。(有資料介紹說:這使編譯器可以重新安排不消耗大量時間的代碼以便優化指令緩存。)?
l?-falign-functions:這個選項用于使函數對準內存中特定邊界的開始位置。?大多數處理器按照頁面讀取內存,并且確保全部函數代碼位于單一內存頁面內,?就不需要叫化代碼所需的頁面。?
l?-falign-jumps:對齊分支代碼到2的n次方邊界。在這種情況下,無需執行傀儡指令(dummy?operations)?
l?-falign-loops:對齊循環到2的n次冪邊界。期望可以對循環執行多次,用以補償運行dummy?operations所花費的時間。?
l?-falign-labels:對齊分支到2的n次冪邊界。這種選項容易使代碼速度變慢,原因是需要插入一些dummy?operations當分支抵達usual?flow?of?the?code.?
l?-fcrossjumping:這是對跨越跳轉的轉換代碼處理,?以便組合分散在程序各處的相同代碼。?這樣可以減少代碼的長度,?但是也許不會對程序性能有直接影響。??
-O3:?比O2更進一步的進行優化。
在包含了O2所有的優化的基礎上,又打開了以下優化選項:?
l?-finline-functions:內聯簡單的函數到被調用函數中。由編譯器啟發式的決定哪些函數足夠簡單可以做這種內聯優化。默認情況下,編譯器限制內聯的尺寸,3.4.6中限制為600(具體含義不詳,指令條數或代碼size?)可以通過-finline-limit=n改變這個長度。這種優化技術不為函數創建單獨的匯編語言代碼,?而是把函數代碼包含在調度程序的代碼中。?對于多次被調用的函數來說,?為每次函數調用復制函數代碼。?雖然這樣對于減少代碼長度不利,?但是通過最充分的利用指令緩存代碼,?而不是在每次函數調用時進行分支操作,?可以提高性能。?
l?-fweb:構建用于保存變量的偽寄存器網絡。?偽寄存器包含數據,?就像他們是寄存器一樣,?但是可以使用各種其他優化技術進行優化,?比如cse和loop優化技術。這種優化會使得調試變得更加的不可能,因為變量不再存放于原本的寄存器中。?
l?-frename-registers:在寄存器分配后,通過使用registers?left?over來避免預定代碼中的虛假依賴。這會使調試變得非常困難,因為變量不再存放于原本的寄存器中了。?
l?-funswitch-loops:將無變化的條件分支移出循環,取而代之的將結果副本放入循環中。?
-Os:?
? ? ?主要是對程序的尺寸進行優化。打開了大部分O2優化中不會增加程序大小的優化選項,并對程序代碼的大小做更深層的優化。(通常我們不需要這種優化)Os會關閉如下選項:?-falign-functions?-falign-jumps?-falign-loops??-falign-labels???-freorder-blocks???-fprefetch-loop-arrays ?
? ? ? 優化介紹小結?O0選項不進行任何優化,在這種情況下,編譯器盡量的縮短編譯消耗(時間,空間),此時,debug會產出和程序預期的結果。當程序運行被斷點打斷,此時程序內的各種聲明是獨立的,我們可以任意的給變量賦值,或者在函數體內把程序計數器指到其他語句,以及從源程序中?精確地獲取你期待的結果.?
優化代碼有可能帶來的問題?
? ? ? 1.調試問題:正如上面所提到的,任何級別的優化都將帶來代碼結構的改變。例如:對分支的合并和消除,對公用子表達式的消除,對循環內load/store操作的替換和更改等,都將會使目標代碼的執行順序變得面目全非,導致調試信息嚴重不足。?
? ? ? 2.內存操作順序改變所帶來的問題:在O2優化后,編譯器會對影響內存操作的執行順序。例如:-fschedule-insns允許數據處理時先完成其他的指令;-fforce-mem有可能導致內存與寄存器之間的數據產生類似臟數據的不一致等。對于某些依賴內存操作順序而進行的邏輯,需要做嚴格的處理后才能進行優化。例如,采用volatile關鍵字限制變量的操作方式,或者利用barrier迫使cpu嚴格按照指令序執行的。
?
gcc 優化選項 -O1 -O2 -O3 -Os 優先級,-fomit-frame-pointer_Mr.Right的專欄-CSDN博客
gcc -O0 -O1 -O2 -O3 四級優化選項及每級分別做什么優化_Aikenlan的博客-CSDN博客
總結
以上是生活随笔為你收集整理的gcc 优化选项 -O1 -O2 -O3 -Os 优先级的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [lwip-users] memp_ma
- 下一篇: 结构体后面定义一个空数组的含义