2016-09-15 17 views
1

Преобразование, затем смещение, а затем побитовое - или единственный способ конвертировать из двух __m128d в один __m128i?Как эффективно конвертировать из двух __m128d в один __m128i в MSVC?

Это вполне приемлемо, чтобы Xcode в x64 построить

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

и разборки показывает _mm_cvtpd_pi32 используется. Однако Visual Studio не может скомпилировать это, жалуясь на ошибку компоновщика. Это поддерживается в документах VS, заявив, что _mm_cvtpd_pi32 не поддерживается на x64.

Я не слишком обеспокоен тем, что он недоступен, но это два преобразования, сдвиг, затем поразрядный или самый быстрый способ?

ответ

2

Если у вас есть ошибка компоновщика, вы, вероятно, игнорируете предупреждение о неоткрытой внутренней функции.

Ваш текущий код имеет высокий риск компиляции в ужасный asm. Если он скомпилирован в векторный смен и OR, он уже компилирует субоптимальный код. (Обновление: это не то, что он компилирует, IDK, где у вас есть эта идея.)

Используйте 2x _mm_cvtpd_epi32, чтобы получить два вектора __m128i с ints, которые вы хотите в двух элементах по два. Используйте _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 

MMX почти полностью бесполезен при наличии SSE2 и более поздних версий; просто избегайте этого. См. Wiki для для некоторых руководств.

+0

Xcode не оптимизировал его. Демонтаж показывает, что используется _mm_cvtpd_pi32, а _mm_set_epi64 просто использует mov для хранения значений. –

+0

Да, это работает: _mm_unpacklo_epi64 (_mm_cvtpd_epi32 (v2dLo), _mm_cvtpd_epi32 (v2dHi)) –