關於編譯器優化方面的知識

    一般編譯器能夠分紅前端(FrontEnd/FE)和後端(BackEnd/BE)兩個部分,其中前端負責將用戶的源代碼翻譯成一種編譯器的內部表示(Intermedium Representation/IR),咱們簡稱IR. 這個就是一般詞法分析,語法分析所作的事情。對於不一樣的源代碼語言,咱們須要不一樣的前端,可是咱們能夠經過使用公共的IR,使得對於不一樣的語言,可使用相同編譯器的後端。而編譯器的後端,如今一般分紅兩個部分,一部分負責同平臺無關的優化工做,咱們一般稱爲中間端(MiddleEnd/ME),另外部分負責同平臺相同的優化工做和代碼生成(一般指生成彙編語言或直接二進制機器代碼),咱們一般稱爲代碼生成部分(Code Generation/CG).前端

    一樣,對於不一樣的平臺(不一樣的CPU,不一樣的操做系統),咱們須要不一樣的代碼生成部分,可是整個編譯器的中間端能夠在不一樣的源代碼,不一樣的平臺之間共享。後端

    有一點須要注意的是,這裏說的不一樣語言,是指像C/C++/Fortran/Pascal之類的靜態編譯的語言,而不包含像Java/C#之類須要在運行時間再編譯的語言(這是由於這兩種編譯器的實現方法徹底不一樣),而對於Java/C#之類的語言,所用的編譯器就是另一個話題了,不過其中用到的大部分技術仍是相似的。而我將會把介紹的重點放在編譯器的中間端(ME).緩存

    關於介紹編譯器優化的書,我推薦你們能夠看一下美國的Steven S. Muchnick寫的Advanced Compiler Design and Implementation. 國內有影印版,中文名字叫《高級編譯器設計和實現》。可是有沒有翻譯成中文的版本我就不知道了。併發

    而現成的比較好的編譯器源代碼,我推薦open64,這個能夠在http://www.open64.net/上找到,這個編譯器的前身是sgi的編譯器pro64,後來移植到Itanium芯片上。根據open64網站上的信息,如今能夠用於Itanium (IA64), i386 (32x86通用芯片)X86_64(64x86通用芯片)。不過好像只支持Linux (Windows能夠試着安裝一下cygwin看看).對於語言,它能夠同時編譯C/C++/Fortran. 在我印象中,這個編譯器的前端用的是gcc的前端,也就是說必須安裝了gcc纔可以使用open64,可是聽說編譯出來代碼的性能比gcc要好不少。工具

   剛纔又想到一個問題,到底編譯器的定義是什麼?什麼樣的軟件纔可以稱爲編譯器呢?性能

   一般,編譯器應該是一個將一種面向用戶的"高級語言"翻譯成面向機器的"目標語言"的軟件。可是實際上,如今的編譯器範疇要遠遠大於上面的定義。優化

  好比如今的編譯器能夠支持源代碼到源代碼的編譯。好比open64裏面,印象中提供了一個叫ir2cir2f的工具,也就是能夠將open64中通過優化的IR從新翻譯成C語言或fortran語言(固然翻譯過程可能會有錯誤)。那麼將編譯器同這個ir2cir2f功能相結合,就能夠當作一個從源代碼到源代碼的編譯過程(中間能夠有優化)。上面過程能夠是同一種語言之間的等價變化,也能夠是不一樣語言之間的等價變換(不一樣語言之間的變化更難,一般因爲語言特性的不一樣,甚至於有些語句可能沒法翻譯回去)。網站

   而實際上,不少編譯器(特別是用於研究的編譯器)都是隻支持源代碼到源代碼的編譯過程的,咱們稱這種編譯器爲Source to Source Compiler.spa

  在另一方面,好比Intel推出Itanium的時候,就趕上一個問題。雖然Itanium提供了許多理論上很是優秀的功能,但是實際上,雖然Itanium硬件直接提供了對x86的支持,可是性能不好,而實際上存在的大部分軟件都是編譯成x86代碼,因此Itanium平臺上運行軟件的速度很是慢。Intel就提供了一種能夠在運行時將x86代碼從新編譯成Itanium代碼的軟件,這個軟件也能夠當作是編譯器的一種,一般稱爲Binary Translation.操作系統

這裏我想先討論下一類關於循環語句的一種優化,能夠統稱爲麼模變換。

這種循環變換理論上結果很是漂亮,惋惜我認爲不少C/C++寫的代碼因爲指針的存在,

編譯器沒法準確分析數據依賴關係,不少這樣的機會編譯器都沒法真正作掉。

而這種優化每每能夠提升代碼對緩存的使用,提升指令級併發度,以及提升線程級並行度。

咱們先分析一個最簡單的狀況。

1.  int a[N][M];

2. 

3.  for(i=0;i<M;i++)

4.    for(j=0;j<N;j++)

5.      a[j]=...;

複製代碼

相關文章
相關標籤/搜索