歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> SHELL編程 >> Linux開發工具(gcc,gdb,make,shell)——三級優化分別做了什麼(一)

Linux開發工具(gcc,gdb,make,shell)——三級優化分別做了什麼(一)

日期:2017/3/3 11:34:54   编辑:SHELL編程

GNU編譯器提供-O選項供程序優化使用:

-O 提供基礎級別的優化

-O2 提供更加高級的代碼優化,會占用更長的編譯時間

-O3 提供最高級的代碼優化

-O4 不優化,這是默認值

不同的優化級別使用的優化技術也可以單獨的應用於代碼。 可以使用-f命令行選項引用每個

單獨的優化技術。

1, 編譯器優化級別1

在優化的第一個級別執行基礎代碼的優化。 這個級別試圖執行9種單獨的優化功能:

-fdefer-pop: 這種優化技術與匯編語言代碼在函數完成時如何進行操作有關。 一般

情況下, 函數的輸入值被保存在堆棧中並且被函數訪問。 函數返回時, 輸入值還在

堆棧中。 一般情況下, 函數返回之後, 輸入值被立即彈出堆棧。這樣做會使堆棧中

的內容有些雜亂。

-fmerge-constans: 使用這種優化技術, 編譯器試圖合並相同的常量. 這一特性有

時候會導致很長的編譯時間, 因為編譯器必須分析c或者c++程序中用到的每個常量,

並且相互比較他們.

-fthread-jumps: 使用這種優化技術與編譯器如果處理匯編代碼中的條件和非條件

分支有關。 在某些情況下, 一條跳轉指令可能轉移到另一條分支語句。 通過一連串

跳轉, 編譯器確定多個跳轉之間的最終目標並且把第一個跳轉重新定向到最終目標。

-floop-optimize: 通過優化如何生成匯編語言中的循環, 編譯器可以在很大程序上

提高應用程序的性能。 通常, 程序由很多大型且復雜的循環構成。 通過刪除在循環

內沒有改變值的變量賦值操作, 可以減少循環內執行指令的數量, 在很大程度上提高

性能。 此外優化那些確定何時離開循環的條件分支, 以便減少分支的影響。

-fif-conversion: if-then語句應該是應用程序中僅次於循環的最消耗時間的部分。

簡單的if-then語句可能在最終的匯編語言代碼中產生眾多的條件分支。 通過減少

或者刪除條件分支, 以及使用條件傳送 設置標志和使用運算技巧來替換他們, 編譯

器可以減少if-then語句中花費的時間量。

-fif-conversion2: 這種技術結合更加高級的數學特性, 減少實現if-then語句所

需的條件分支。

-fdelayed-branch: 這種技術試圖根據指令周期時間重新安排指令。 它還試圖把

盡可能多的指令移動到條件分支前, 以便最充分的利用處理器的治理緩存。

-fguess-branch-probability: 就像其名稱所暗示的, 這種技術試圖確定條件分支最可

能的結果, 並且相應的移動指令, 這和延遲分支技術類似。 因為在編譯時預測代碼的安排,

所以使用這一選項兩次編譯相同的c或者c++代碼很可能會產生不同的匯編語言代碼, 這取決

於編譯時編譯器認為會使用那些分支。 因為這個原因, 很多程序員不喜歡采用這個特性, 並且

專門地使用-fno-guess-branch-probability選項關閉這個特性

-fcprop-registers: 因為在函數中把寄存器分配給變量, 所以編譯器執行第二次檢查以便減少

調度依賴性(兩個段要求使用相同的寄存器)並且刪除不必要的寄存器復制操作。

2, 編譯器優化級別2

結合了第一個級別的所有優化技術, 再加上一下一些優化:

-fforce-mem: 這種優化再任何指令使用變量前, 強制把存放再內存位置中的所有變量都復制到寄存器

中。 對於只涉及單一指令的變量, 這樣也許不會有很大的優化效果. 但是對於再很多指令(必須數學操作)

中都涉及到的變量來說, 這會時很顯著的優化, 因為和訪問內存中的值相比 ,處理器訪問寄存器中的值要

快的多。

-foptimize-sibling-calls: 這種技術處理相關的和/或者遞歸的函數調用。 通常, 遞歸的函數調用

可以被展開為一系列一般的指令, 而不是使用分支。 這樣處理器的指令緩存能夠加載展開的指令並且

處理他們, 和指令保持為需要分支操作的單獨函數調用相比, 這樣更快。

-fstrength-reduce: 這種優化技術對循環執行優化並且刪除迭代變量。 迭代變量是捆綁到循環計數器

的變量, 比如使用變量, 然後使用循環計數器變量執行數學操作的for-next循環。

-fgcse: 這種技術對生成的所有匯編語言代碼執行全局通用表達式消除歷程。 這些優化操作試圖分析

生成的匯編語言代碼並且結合通用片段, 消除冗余的代碼段。如果代碼使用計算性的goto, gcc指令推薦

使用-fno-gcse選項。

-fcse-follow-jumps: 這種特別的通用子表達式消除技術掃描跳轉指令, 查找程序中通過任何其他途徑都不

會到達的目標代碼。 這種情況最常見的例子就式if-then-else語句的else部分。

-frerun-cse-after-loop: 這種技術在對任何循環已經進行過優化之後重新運行通用子表達式消除例程。

這樣確保在展開循環代碼之後更進一步地優化還編代碼。

-fdelete-null-pointer-checks: 這種優化技術掃描生成的匯編語言代碼, 查找檢查空指針的代碼。編譯

器假設間接引用空指針將停止程序。 如果在間接引用之後檢查指針, 它就不可能為空。

-fextensive-optimizations: 這種技術執行從編譯時的角度來說代價高昂的各種優化技術,但是它可能

對運行時的性能產生負面影響。

-fregmove: 編譯器試圖重新分配mov指令中使用的寄存器, 並且將其作為其他指令操作數, 以便最大化

捆綁的寄存器的數量。

-fschedule-insns: 編譯器將試圖重新安排指令, 以便消除等待數據的處理器。 對於在進行浮點運算時有

延遲的處理器來說, 這使處理器在等待浮點結果時可以加載其他指令。

-fsched-interblock: 這種技術使編譯器能夠跨越指令塊調度指令。 這可以非常靈活地移動指令以便等待

期間完成的工作最大化。

-fcaller-saves: 這個選項指示編譯器對函數調用保存和恢復寄存器, 使函數能夠訪問寄存器值, 而且不必

保存和恢復他們。 如果調用多個函數, 這樣能夠節省時間, 因為只進行一次寄存器的保存和恢復操作, 而

不是在每個函數調用中都進行。

-fpeephole2: 這個選項允許進行任何計算機特定的觀察孔優化。

-freorder-blocks: 這種優化技術允許重新安排指令塊以便改進分支操作和代碼局部性。

-fstrict-aliasing: 這種技術強制實行高級語言的嚴格變量規則。 對於c和c++程序來說, 它確保不在數據

類型之間共享變量. 例如, 整數變量不和單精度浮點變量使用相同的內存位置。

-funit-at-a-time: 這種優化技術指示編譯器在運行優化例程之前讀取整個匯編語言代碼。 這使編譯器可以

重新安排不消耗大量時間的代碼以便優化指令緩存。 但是, 這會在編譯時花費相當多的內存, 對於小型計算機可能

是一個問題。

-falign-functions: 這個選項用於使函數對准內存中特定邊界的開始位置。大多數處理器按照頁面讀取內存,

並且確保全部函數代碼位於單一內存頁面內, 就不需要叫化代碼所需的頁面。

-fcrossjumping: 這是對跨越跳轉的轉換代碼處理, 以便組合分散在程序各處的相同代碼。 這樣可以減少

代碼的長度, 但是也許不會對程序性能有直接影響。

3, 編譯器優化級別3

它整合了第一和第二級別中的左右優化技巧, 還包括一下優化:

-finline-functions: 這種優化技術不為函數創建單獨的匯編語言代碼,而是把函數代碼包含在調度程序的

代碼中。 對於多次被調用的函數來說, 為每次函數調用復制函數代碼。 雖然這樣對於減少代碼長度不利, 但是

通過最充分的利用指令緩存代碼, 而不是在每次函數調用時進行分支操作, 可以提高性能。

-fweb: 構建用於保存變量的偽寄存器網絡。 偽寄存器包含數據, 就像他們是寄存器一樣, 但是可以使用各種

其他優化技術進行優化, 比如cse和loop優化技術。

-fgcse-after-reload: 這中技術在完全重新加載生成的且優化後的匯編語言代碼之後執行第二次gcse優化,

幫助消除不同優化方式創建的任何冗余段。

Copyright © Linux教程網 All Rights Reserved