起因:
目前項目使用nios IDE作為開發平台,其使用的編譯器為gcc的交叉編譯器。在設定編譯條件時,在debug模式下生成的程序正常,但是在release模式下會出現LCD顯示的開端顯示不全,缺少一個字節或字的狀況。為了了解具體為什麼造成該問題,對兩種模式下的配置做了對比,編譯器皆為nios2-elf-gcc交叉編譯器,debug模式編譯器參數為:-DALT_DEBUG -O0 -g
–Wall。release模式編譯器參數為:
-DALT_RELEASE -O2 -g –Wall。
兩種模式下的參數簡單說明如下
-DALT_DEBUG:目前沒有明確資料顯示該項的具體作用,根據命名可認為與調試有關選項。且兩種模式下都有,暫時認為不會造成差異。
-O0: gcc編譯器默認優化等級。
-g:gdb調試器支持選項用於在編譯時生成相關調試信息。
-Wall:打開所有編譯器告警選項,即編譯器最嚴格告警模式。
-O2:gcc編譯高於O0低於O3的編譯優化選項。
通過對比可以發現兩種模式主要的不同在於編譯器優化程度不同,那麼編譯器在兩種優化下究竟做了什麼優化那?是否由這些問題造成的顯示丟失問題那??現在我們來看看gcc編譯器的優化參數到底做了什麼優化。(注:由於關於nios2-elf-gcc的文檔資料十分稀少,不能形成可分析的文檔,所以以通用的gcc作為分析,畢竟同出一源)
正文:
GCC編譯器優化選項介紹:
GCC編譯器在目前是不是用最多的編譯器也相去不遠,尤其在嵌入式領域很多編譯器都是基於GCC的cross
gcc版本。畢竟功能成熟而且有開放的源代碼。
這裡只介紹優化編譯的參數
-O用來開啟優化編譯選項。
-O0:默認模式,不做任何優化。
-O1:優化。該模式下對於一個大的函數或功能會花費更多的時間和內存。
在-O1下:編譯會嘗試減少代碼體積和代碼運行時間。但是並不執行會花費大量時間的優化操作。
在該模式下將打開一下優化選項:
-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
該模式下在不影響調試的狀況下還會打開‘-fomit-frame-pointer優化項。
同時該模式不會為Ada編譯器打開‘-ftree-sra’優化項,如需要則請使用命令參數輸入‘-ftree-sra’進行優化。
-O2:進一步優化.GCC執行幾乎所有支持的操作但不包括空間和速度之間權衡的優化。-O2優化等級下,並不執行循環展開和函數“內聯”【注1】優化操作。與-O1比較該優化-O2將會花費更多的編譯時間當然也會生成性能更好的代碼。-O2除了打開-O1的所有優化參數外還打開以下優化選項。
-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-o
-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
還要注意-fgcse下關於請求-O2優化等級的用於計算goto的程序。
-O3:更進一步優化。-O3打開-O2指定的所有優化操作並且打開:
-finline-functions
-funswitch-loops
-fgcse-after-reload
優化項。
-Os:針對程序空間大小優化(多用於嵌入式系統)。-Os使能-O2中除去會增加程序空間的所有優化參數。同時-Os還會執行更加優化程序空間的選項。
-Os會關閉以下優化選項:
-falign-functions
-falign-jumps
-falign-loops
-falign-labels
-freorder-blocks
-freorder-blocks-and-partition
-fprefetch-loop-arrays
-ftree-vect-loop-version
關於GCC編譯的優化選項一共有-O0(默認),-O1,-O2,-O3及-Os五個參數。各個參數優選內容如上所示。但是各個優化內容到底是指什麼那?繼續分析。
2.優化具體參數含義。(共計49項)
-fdefer-pop
推遲推出函數調用的參數,對於那些需要在函數調用後必須取出(pop)函數參數的機器而言,打開該項編譯器將把函數調用的參數壓入棧,等必要時幾個函數調用參數一起取出(pop)。這將節省處理時間。
-fdelayed-branch
如果對目標機支持這個功能,它試圖重新排列指令,以便利用延遲分支(delayed
branch)指令後面的指令空隙.
-fguess-branch-probability
使用啟發式算法預測分之指令,增加指令的命中率,提升運行效果。
-fcprop-registers
使用寄存器之間copy-propagation傳值;
因為在函數中把寄存器分配給變量, 所以編譯器執行第二次檢查以便減少
調度依賴性(兩個段要求使用相同的寄存器)並且刪除不必要的寄存器復制操作
-floop-optimize
通 過優化如何生成匯編語言中的循環, 編譯器可以在很大程序上提高應用程序的性能。 通常, 程序由很多大型且復雜的循環構成。 通過刪除在循環內沒有改變值的變量賦值操作, 可以減少循環內執行指令的數量, 在很大程度上提高性能。 此外優化那些確定何時離開循環的條件分支, 以便減少分支的影響。
-fif-conversion
if-then語句應該是應用程序中僅次於循環的最消耗時間的部分。
簡單的if-then語句可能在最終的匯編語言代碼中產生眾多的條件分支。 通過減少
或者刪除條件分支, 以及使用條件傳送 設置標志和使用運算技巧來替換他們, 編譯
器可以減少if-then語句中花費的時間量。
-fif-conversion2
這種技術結合更加高級的數學特性, 減少實現if-then語句所
需的條件分支。
-ftree-ccp
Perform sparse conditional constant propagation (CCP) on trees. This pass
only operates on local scalar variables and is enabled by default at ‘-O’ and
higher.
-ftree-dce
編譯器將消除無用的不會被執行的代碼(dead code)
-ftree-dominator-opts
Perform a variety of simple scalar cleanups (constant/copy propagation, redun-
dancy elimination, range propagation and expression simplification) based on a
dominator tree traversal. This also performs jump threading (to reduce jumps
to jumps). This flag is enabled by default at ‘-O’ and higher.
-ftree-dse
-ftree-ter
Perform temporary expression replacement during the SSA->normal phase. Sin-
gle use/single def temporaries are replaced at their use location with their defin-
ing expression. This results in non-GIMPLE code, but gives the expanders
much more complex trees to work on resulting in better RTL generation. This
is enabled by default at ‘-O’ and higher.
-ftree-lrs
Perform live range splitting during the SSA->normal phase. Distinct live ranges
of a variable are split into unique variables, allowing for better optimization
later. This is enabled by default at ‘-O’ and higher.
-ftree-sra
-ftree-copyrename
-ftree-fre
-ftree-ch
-funit-at-a-time
-fmerge-constants
-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-o
-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
-finline-functions
允許編譯器選擇某些簡單的函數在其被調用處展開,比較安全的選項,特別是在CPU二級緩存較大時建議使用。
-funswitch-loops
-fgcse-after-reload