2012-03-04 62 views
6

我正在編寫一個編譯器,我必須輸出浮點值分支條件的代碼。例如,要編譯這種類型的代碼:使用Intel SSE執行分支的最佳方式是什麼?

if(a <= b){ 
    //1. DO something 
} else { 
    //2. Do something else 
} 

當a和b是浮點型變量時。我只需要跳到2,如果條件不是真的,否則會下降到1.我在這裏考慮在編譯器級別考慮1和2中的優化。

我需要一些適用於所有比較運算符>,> =,<,< =,==和!=

我發現進行比較的一種方法是使用CMPLTSD(以及其他關係運算符的等效指令)。但是有了這個,我必須使用一個SSE寄存器,特別是結果,然後我必須將它的值移到通用寄存器(例如eax)上,最後將其與0進行比較。

我還看到UCOMISD指令應該正確地設置標誌,但顯然它不按我想的方式工作。

那麼,處理這樣的代碼的最好方法是什麼?是否有比我擁有的第一個解決方案更好的說明?

最好,我的意思是,這個問題的一般解決方案。如果可能的話,我希望代碼的行爲與整數比較(cmp a,b; jge label)時的行爲相同。當然,我寧願用最快的指令來實現這一點。

+2

最好的辦法*取決於你在做什麼*。如在裏面,'// DO something'塊裏面是什麼? 「最好的方式」通常取決於看整張圖片,而不是試圖逐行翻譯你的代碼。 – jalf 2012-03-04 19:48:43

+0

我在帖子中添加了詳細信息來回答你的兩個問題。 – 2012-03-04 19:56:42

+1

如果你真的想分支,UCOMISD(實際上是SSE2)似乎是答案,它有什麼問題?無序的結果? – harold 2012-03-04 20:02:21

回答

7

ucomisd的條件代碼不對應於有符號整數比較代碼,但不對應於無符號整數(在奇偶標誌中帶有「無序」)。我承認這有點奇怪,但都清楚地記錄在案。 的代碼,如果你真的想分支可能是這樣的<=

ucomisd a,b 
    ja else  ; greater 
    jp else  ; unordered 
    ; code for //1 goes here 
    jmp end 
else: 
    ; code for //2 goes here 
end: 

對於<

jae else ; greater or equal 
jp else ; unordered 

我可以列出所有這些,如果你真的想,但你可以看看ucomisd的條件代碼並將它們匹配到您需要的跳轉。

+0

這確實很奇怪......但我想我會將它與文檔結合起來。非常感謝。 – 2012-03-04 20:28:05

1

重要:@哈羅德的回答幾乎是完全正確的,但有一個微妙的錯誤方面,這可能會讓你發瘋了非常重要的邊緣情況以後 - NaN的治療是向後從大多數語言(如C++)。

正如@harold所說的,無序比較結果存儲在奇偶標誌中。

但是,無序比較在任何操作數是NaN時爲真,詳見this stack overflow post。這意味着NaN將小於,等於和大於絕對每個數字包括NaN

所以,如果你希望你的語言以匹配C++的,其中與南任何比較返回假行爲,你想:

對於<=

ucomisd xmm0, xmm1 
jbe else_label 

對於<

ucomisd xmm0, xmm1 
jb else_label 

在以下gcc反彙編中確認,其中I return a >= b

144e:  66 0f 2e c8    ucomisd %xmm0,%xmm1 
1452:  0f 93 c0    setae %al 

這裏它使用setae這是修改註冊等效於jae。然後立即返回而不檢查奇偶標誌。

爲什麼它的ja而不是jg,@哈羅德的回答仍然是一個清晰和正確的解釋。

當然,你不必使用有序的比較,你可以用無序在以前的答案比較如圖所示,如果你想絕對是每個數比小於,大於等於NaN在你的程序/語言(即使NaN < NaN是真的!)。當然,正如你所看到的,它可能會慢一點,因爲它需要額外的檢查。

相關問題