2016-09-15 68 views
1

正在轉換,然後按位或將唯一的方法從兩個__m128d轉換爲單個__m128i如何有效地將兩個__m128d轉換爲MSVC中的一個__m128i?

這是完全可以接受的在在x64,Xcode的建立

m128d v2dHi = .... 
m128d v2dLo = .... 
__m128i v4i = _mm_set_epi64(_mm_cvtpd_pi32(v2dHi), _mm_cvtpd_pi32(v2dLo)) 

和拆卸顯示所使用_mm_cvtpd_pi32。但是,Visual Studio無法編譯這個,抱怨鏈接器錯誤。這在VS文檔中得到了支持,他說x64不支持_mm_cvtpd_pi32

我並不擔心它不可用,而是兩次轉換,一次轉換,然後是按位還是最快的方式?

回答

2

如果你有鏈接器錯誤,你可能會忽略關於未聲明的內部函數的警告。

你目前的代碼編譯可怕的asm的風險很高。如果它編譯爲向量移位和OR,它已經編譯爲次優代碼。 (更新:這不是它編譯的內容,IDK,你有這個想法。)

使用2x _mm_cvtpd_epi32獲得兩個__m128i向量,您需要在每個元素的低2個元素中輸入整數。使用_mm_unpacklo_epi64將這兩個低半部分合併成一個具有所有4個元素的向量。從clang3.8.1 on the Godbolt compiler explorer


編譯器輸出。 (我認爲Xcode默認使用clang)。

#include <immintrin.h> 

// the good version 
__m128i pack_double_to_int(__m128d a, __m128d b) { 
    return _mm_unpacklo_epi64(_mm_cvtpd_epi32(a), _mm_cvtpd_epi32(b)); 
} 
    cvtpd2dq  xmm0, xmm0 
    cvtpd2dq  xmm1, xmm1 
    punpcklqdq  xmm0, xmm1  # xmm0 = xmm0[0],xmm1[0] 
    ret 

// the original 
__m128i pack_double_to_int_badMMX(__m128d a, __m128d b) { 
    return _mm_set_epi64(_mm_cvtpd_pi32(b), _mm_cvtpd_pi32(a)); 
} 
    cvtpd2pi  mm0, xmm1 
    cvtpd2pi  mm1, xmm0 
    movq2dq xmm1, mm0 
    movq2dq xmm0, mm1 
    punpcklqdq  xmm0, xmm1  # xmm0 = xmm0[0],xmm1[0] 
     # note the lack of EMMS, because of not using the intrinsic for it 
    ret 

當SSE2和更高版本可用時,MMX幾乎完全沒用;只是避免它。有關指南,請參閱標記wiki。

+0

Xcode沒有優化它。反彙編顯示正在使用_mm_cvtpd_pi32,_mm_set_epi64正在使用mov來存儲這些值。 –

+0

是的,它的工作原理: _mm_unpacklo_epi64(_mm_cvtpd_epi32(v2dLo),_mm_cvtpd_epi32(v2dHi)) –

相關問題