消除分支能改善效能,原因如下:
降低預測失誤的概率
減少必需的分支目標緩衝區 (BTB) 專案數;永遠不執行的條件分支不消耗 BTB 資源。
以下是消除分支的四種基本方法:
調整程式碼結構,使基本指令塊相鄰。
展開循環,詳見循環展開主題中的討論。
使用 cmov 指令。
使用 setcc 指令。
彙編/編譯器編碼規則 1。(影響度 MH,通用性 H)調整程式碼結構,使基本指令塊相鄰,以消除不必要的分支。
彙編/編譯器編碼規則 2。(影響度 M,通用性 ML)儘可能使用 setcc 與 cmov 指令去消除無法預測的條件分支。對於可預測的分支,請勿這樣做。此外,請勿使用這些指令去消除所有無法預測的條件分支。因為使用這些指令將由於會執行條件分支的兩條路徑而產生額外的執行開銷;所以僅當計算事件的增量小於分支預測失誤的預期開銷時,才應使用這些指令。
考慮下面這行 C 程式碼,其中有個條件取決於這些常數中的一個:
X = (A < B) ?CONST1 : CONST2;
此程式碼有條件地比較兩個值:A 與 B。如果條件為真,則 X 設定為 CONST1;否則它設定為 CONST2。如果這兩個值之間沒有關係,則與上述 C 程式碼等價的彙編程式碼序列將可能包含無法預測的分支。
在奔騰(R) II 及後續的處理器上,消除分支的另一種方法是使用 cmov 與 fcmov 指令。
cmov 與 fcmov 指令在奔騰 II 及後續的處理器上均有提供,但在奔騰處理器以及早期的 32 位英特爾(R) 體系結構的處理器上則沒有提供。如果應用程式還需要在較早的處理器上執行,請務必使用 cpuid 指令檢查處理器是否支援這些指令。程式碼常常可以通過適當跳轉,使得控制權可以從一個基本指令塊轉到下一個,而不必執行分支。