窺孔最佳化

窺孔最佳化,顧名思義,是一種很局部的最佳化方式,編譯器僅僅在一個基本塊或者多個基本塊中,針對已經生成的代碼,結合CPU自己指令的特點,通過一些認為可能帶來性能提升的轉換規則,或者通過整體的分析,通過指令轉換,提升代碼性能。別看這些代碼轉換很局部,很小,但可能會帶來很大的性能提升。 這個窺孔,你可以認為是一個滑動視窗,編譯器在實施窺孔最佳化時,就僅僅分析這個視窗內的指令。每次轉換之後,可能還會暴露相鄰視窗之間的某些最佳化機會,所以可以多次調用窺孔最佳化,儘可能提升性能。

窺孔最佳化特點

(1)

最佳化對象

最佳化對象既可以是中間代碼級,也可以是目標代碼級。(2)每次處理的只是一組相鄰指令,相當於將一 組相鄰指令暴露在一個最佳化視窗中(正如“窺孔”的含義)。 (3)對最佳化對象進行線性掃描。(4)最佳化後產生的結果可能 會給後面的代碼提供進一步最佳化的機會。(5)窺孔最佳化程式通常很小,只需很少的記憶體,執行速度很快。

窺孔最佳化的常用技術

窺孔最佳化可以在四個方面尋找最佳化機會:冗餘指令刪除,包括冗餘的load和store指令以及死代碼(不會執行的代碼);控制流最佳化;強度削弱;利用特有指令。

刪除冗餘load和store

比如這段彙編代碼:

sh $0,6($sp)

sh $0, 4($sp)

sh $0, 2($sp)

sh $0, 0($sp)

ldc1 $f1, 0($sp)

完全可以使用指令xor $f1,$f1,$f1這樣可以省掉5次訪存操作,性能的提升非常明顯。上面sh是store 16bit到某個地址,ldc1是load 64bit到某個暫存器。xor是異或指令。

但是這種指令序列的轉換和合成有個前提,必須保證這些指令按照順序執行,即這些指令之間,不能有其他標號,即入口。也就是說這些指令必須在一個基本塊中。當然,你也可以在編譯器較前面階段的最佳化中,針對該操作,做變換。這樣到了窺孔最佳化時,就不再會有這樣的代碼了。

刪除死代碼

有些代碼可能用於不會被執行到,這樣在窺孔最佳化階段,如果發現這樣的代碼,就可以直接刪除。典型的方式是最佳化雙跳轉,即第一條跳轉指令的目的地址還是一條跳轉指令時,可以刪除後一條跳轉指令,並修改第一條跳轉指令的目標地址。另外,對於不可能進入的分支也可以使用這種方式刪除。

控制流最佳化

中間代碼生成階段,很可能經常產生一些跳轉到跳轉指令,跳轉到分支跳轉、分支跳轉到跳轉之類的指令,都可以在窺孔最佳化中想辦法解決掉,當然你也可以在中間代碼中最佳化它們。一些分支被刪除後,可能還存在一些不會被到達的標號(label),也可以順便刪除之,這樣就會提升基本塊的大小,增加最佳化機會。

強度削弱

即利用代價較小的指令或操作替代代價較大的指令或操作,從而提升性能。比如x=x+0, x=x*1之類的操作就能直接避免,x=x*2,x=x/2之類的操作可以使用左移或右移實現。x^2之類的指數運算可以削弱為x*x的乘法運算,浮點數除以常數的運算可以轉換為浮點數乘以常數的倒數。這些都是最佳化方式。

充分利用特有指令

CPU都會提供一些特殊指令完成特殊操作,比如DSP晶片中可能有複雜的數位訊號處理指令,龍芯中有乘加指令以及一些向量擴展指令。還有一些CPU可能提供自增、自減、取絕對值指令。這些都能在窺孔最佳化中生成。提升程式的運行性能。

相關詞條

相關搜尋

熱門詞條

聯絡我們