C 編譯器優化(1)

     我打算在這裏記錄一下C Complier 的一些優化實現策略,本文主要考慮在C Complier 中如何優化到Codesize 最小,並不是打算產生出的代碼效率最高,因爲目前嵌入式設備的Flash 或着ROM 是“寸土寸金”。因此這樣的優化在 CComplier 階段就顯得很重要了。優化我打算寫一個系列的工作記錄,因此本文之後還會更深入的講解,這篇主要是講述  C Complier 如何做這個優化部分,以及優化部分能持續到什麼時候,以及如何構建優化的解決方案。

1.  C  Complier 的優化解決思路
 (1)目前 C Complier 的優化從建立語法樹,就可以開始優化的動作。
 (2)中間代碼的優化工作,這個部分主要是通過DAG圖來進行優化。
 (3)代碼產生出來之後,可以進行的局部優化(peephole)
 (4)整個工程在編譯之後,link 階段可以進行的多餘指令和變量的優化動作
以上的優化部分,都是在可以進行代碼調試的基礎上進行的,不是將代碼優化到VS 或者Gcc那種不能調試的程度,當然那種的難度就會更高。

2 .下面主要講述在 C Complier 之外的peephole 優化和 link階段的postlink 優化,然後再進入 C Complier 的內部分別描述各種優化的實施


3.peephole 優化的構建
  peephole 的構建,首先必須熟悉當前要使用的機器指令,同時對機器指令應該能達到寫相當精煉的ASM 程序。因爲我們的peephole 是基於在ASM 上進行優化。爲了能進行局部範圍的優化工作,那麼應該對指令的各種信息瞭如指掌。
(1) 指令集信息的收
      一般要收集的信息無非就是四種:
     1) 指令的操作數信息,比如有沒有操作數,操作數是工作寄存器(下面使用WR)還是RAM 空間(下面使用M), 如 指令R0 = 0x45;  拿這條指令來說 R0 是一個WR,0x45 是一個立即數 ,那麼對待這種類型的彙編指令你就要分析源操作數和目的操作數的信息是什麼? MOV AL, 0x45 是和這個指令基本一致,那麼我們就應該對這種指令分別記錄其源和目的操作數。
    2) 指令的語法信息: 如R0 = 0x45 這是一個簡單的賦值語句,那麼對待R0 = R0+ R1 + C 這是表示一個操作指令。
    3) 記錄指令的類型, 如PUSH 指令,有沒有改變FLAG Register 等。
   描述上述信息之後,大家可能就要問,爲什麼要收集這些信息。因爲我們的peephole 是針對這些文本進行處理的,如果我們不將這些信息收集起來,直接處理不但難度很大,而且我的 Complier 就沒有人用了,估計我也就失業了。
(2) 如何收集指令的信息
      因爲我們都是學過軟件工程的,在別人已經有現成的東西可以使用的時候,那麼我們就不必要從頭開發,同樣我們沒有必要從頭開發。因此我們分析彙編指令可以藉助YCC和LEX 自動化分析工具,那麼在這裏我們使用的是Visual Parser 4.0 以上的版本,網絡上可以download 到的。
    寫VP的parse 規則這個大家根據自己的指令形式進行寫,即可。就是將產生式書寫過程。
(3)優化pattern 的收集,那麼這個過程是C Complier 產生規則產生出來的代碼形成的規定格式,那麼只要出現這中格式,就可以進行優化,例如:
PUSH  SSF
R0 = R1 + R0
PUSH SSF
R0 =  SL R0--------------> 表示左移 R0一位後再賦值給R0
那麼出現這樣的情況其實SSF Register 是不要保存的。
還有PC 上這樣的指令
MOV al, temp
MOV temp, al
.........
其中出現沒有別的指令修改temp, 和al 的值的話,那麼第二句就可以刪掉了。當然我這裏是一個簡單的描述,任何人的 Complier 都應該是不同的。

peephole 的優化原則:

    peephole 的優化原則主要是在局部沒有發生跳轉和Call 的地方進行的多餘指令的刪除和替換操作,當然以上除多餘指令爲主要的目的,替換除非pattern 很穩定的時候,纔可以做,負責將會出錯 。另外peephole 不能在C 程序中的內嵌彙編上做優化,也不能對user 直接寫的ASM 文件中的內容做優化 ,因爲用戶寫的東西不能保證就是制定的pattern ,或者用戶就是爲了達到某種效果,故意寫的指令,這些我們都不得而知。


下一篇  peephole 具體實做。
 主要講如何分析peephole , 如何將狀態機用到 C Complier 的優化之中。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章