天天看點

自己動手構造編譯系統:編譯、彙編與連結2.1.6 編譯優化

<b>2.1.6  編譯優化</b>

  

      現代編譯器一般都包含優化器,優化器可以提高生成代碼的品質,但會使代碼生成過程變得複雜。一般主流的工業化編譯器會按照如圖2-9所示結構進行設計。

  現代編譯器設計被分為前端、優化器和後端三大部分,前端包含詞法分析、文法分析和語義分析。後端的指令選擇、指令排程和寄存器配置設定實際完成代碼生成的工作,而優化器則是對中間代碼進行優化操作。實作優化器,必須設計編譯器的中間代碼表示。中間代碼的設計沒有固定的标準,一般由編譯器設計者自己決定。

圖2-9  現代編譯器結構

  由于中間代碼的存在,使得文法制導翻譯的結果不再是目标機器的代碼,而是中間代碼。按照我們自己設計的中間代碼形式,上述例子生成的中間代碼可能是如下形式:

tmp=var1+100

var2=tmp

  即使優化器沒有對這段代碼進行處理,編譯器的後端也能正确地把這段中間代碼翻譯為目标機制指令。根據指令選擇和寄存器配置設定算法,得到的目标機器指令可能如下:

mov eax,[var1]

add eax,100

mov [var2],eax

  編譯器後端在指令選擇階段會選擇更“合适”的指令實作中間代碼的翻譯,比如使用“add eax,100”實作tmp=var1+100的翻譯。在寄存器配置設定階段會盡可能地将變量儲存在寄存器内,比如tmp一直儲存在eax中。

  中間代碼的抽象程度一般介于進階語言和目标機器語言之間。良好的中間代碼形式使得中間代碼生成、目标代碼生成以及優化器的實作更加簡單。我們設計的優化器實作了常量傳播、備援消除、複寫傳播和死代碼消除等經典的編譯優化算法。先通過一個簡單的執行個體說明中間代碼優化的工作。

var1=100;

var2=var1+100;

  将上述進階語言翻譯為中間代碼的形式如下:

var1=100

  常量傳播優化使編譯器在編譯期間可以将表達式的結果提前計算出來,是以經過常量傳播優化後的中間代碼形式如下:

tmp=200

var2=200

  死代碼消除優化會把無效的表達式從中間代碼中删除,假如上述代碼中隻有變量var2在之後會被使用,那麼var1和tmp都是無效的計算。是以,消除死代碼後,最終的中間代碼如下:

  再經過後端将之翻譯為彙編代碼如下:

mov [var2],200

   由于本書篇幅及作者水準所限,在不能實作所有的編譯優化算法的情況下,選擇若幹經典的優化算法來幫助讀者了解優化器的基本工作流程。

  至此,我們簡單介紹了進階語言源檔案轉化為目标機器的彙編代碼的基本流程。本書設計的編譯器支援多檔案的編譯,是以編譯器會為每個源檔案單獨生成一份彙編檔案,然後通過彙編器将它們轉換為二進制目标檔案。彙編過程中涉及目标機器的指令格式和可執行檔案的内容,為了便于了解彙編器的工作流程,需要提前準備與作業系統和硬體相關的知識。

繼續閱讀