2016-09-15 7 views
1

다음 두 비트를 __m128i으로 변환하는 유일한 방법은 bitwise-or'ing 변환입니다.MSVC에서 두 개의 __m128d를 하나의 __m128i로 효율적으로 변환하는 방법은 무엇입니까?

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

구축 64 엑스 코드에 완벽하게 허용하고 해체 _mm_cvtpd_pi32가 사용되고 나타낸다. 그러나 Visual Studio에서는 링커 오류에 대해 불만을 토하여이를 컴파일 할 수 없습니다. 이것은 VS 문서에서 _mm_cvtpd_pi32이 x64에서 지원되지 않는다고 말하면서 지원됩니다.

나는 그것이 사용할 수 없다고 너무 걱정하지 않지만 두 번의 전환, 교대, 조금씩 또는 가장 빠른 방법입니까?

답변

2

링커 오류가 발생하는 경우 신고되지 않은 내장 함수에 대한 경고를 무시한 것입니다.

현재 코드는 끔찍한 asm 컴파일의 위험이 있습니다. 벡터 이동 및 OR로 컴파일 된 경우 이미 하위 최적 코드로 컴파일됩니다. (업데이트 : 그것이 컴파일 된 것이 아닌 IDK의 아이디어입니다.)

2x _mm_cvtpd_epi32을 사용하여 각각 2 개의 하위 요소에 원하는 int를 갖는 두 개의 __m128i 벡터를 얻습니다. _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 

MME는 SSE2 이상을 사용할 수있는 경우 거의 쓸모가 없습니다. 그냥 피하십시오. 일부 가이드는 태그 위키를 참조하십시오.

+0

Xcode가 최적화하지 않았습니다. 디스 어셈블리하면 _mm_cvtpd_pi32가 사용되고, _mm_set_epi64는 mov를 사용하여 값을 저장합니다. –

+0

그래, 작동 : _mm_unpacklo_epi64 (_mm_cvtpd_epi32 (v2dLo), _mm_cvtpd_epi32 (v2dHi)) –