SSE2 は、いくつかの 64 ビット整数演算を直接サポートしています。
両方の要素を 0 に設定します。
__m128i z = _mm_setzero_si128();
両方の要素を 1 に設定します。
__m128i z = _mm_set1_epi64x(1); // also works for variables.
__m128i z = _mm_set_epi64x(hi, lo); // elements can be different
__m128i z = _mm_set_epi32(0,1,0,1); // if any compilers refuse int64_t in 32-bit mode. (None of the major ones do.)
下位 64 ビットを設定/ロードし、__m128i にゼロ拡張します
// supported even in 32-bit mode, and listed as an intrinsic for MOVQ
// so it should be atomic on aligned integers.
_mm_loadl_epi64((const __m128i*)p); // movq or movsd 64-bit load
_mm_cvtsi64x_si128(a); // only ICC, others refuse in 32-bit mode
_mm_loadl_epi64((const __m128i*)&a); // portable for a value instead of pointer
に基づくもの_mm_set_epi32
は、一部のコンパイラによって混乱にコンパイルされる可能性があるため、_mm_loadl_epi64
MSVC と ICC、および gcc/clang で最善の策と思われ、実際には 32 ビット モードでのアトミック 64 ビット ロードの要件に対して安全である必要があります。 . Godbolt コンパイラ エクスプローラで参照してください
各 64 ビット整数を垂直方向に加算/減算します。
__m128i z = _mm_add_epi64(x,y)
__m128i z = _mm_sub_epi64(x,y)
http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse2_integer_arithmetic.htm#intref_sse2_integer_arithmetic
左方移動:
__m128i z = _mm_slli_epi64(x,i) // i must be an immediate
http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse2_int_shift.htm
ビット演算子:
__m128i z = _mm_and_si128(x,y)
__m128i z = _mm_or_si128(x,y)
http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse2_integer_logical.htm
SSE にはインクリメントがないため、 で定数を使用する必要があります1
。
pcmpeqq
SSE4.1と SSE4.2までは 64 ビットのサポートがないため、比較は困難です。pcmpgtq
ここに平等のためのものがあります:
__m128i t = _mm_cmpeq_epi32(a,b);
__m128i z = _mm_and_si128(t,_mm_shuffle_epi32(t,177));
これにより、各 64 ビット要素が0xffffffffffff
(別名-1)
、それらが等しい場合) に設定されます。0
またはとして使用する場合1
はint
、 を使用して引き出して_mm_cvtsi32_si128()
追加でき1
ます。(ただしtotal -= cmp_result;
、変換して追加する代わりに実行できる場合もあります。)
Less-Than: (完全にはテストされていません)
a = _mm_xor_si128(a,_mm_set1_epi32(0x80000000));
b = _mm_xor_si128(b,_mm_set1_epi32(0x80000000));
__m128i t = _mm_cmplt_epi32(a,b);
__m128i u = _mm_cmpgt_epi32(a,b);
__m128i z = _mm_or_si128(t,_mm_shuffle_epi32(t,177));
z = _mm_andnot_si128(_mm_shuffle_epi32(u,245),z);
0xffffffffffff
の対応する要素a
が より小さい場合、これにより、各 64 ビット要素が に設定されb
ます。
これは、bool を返す「equals」と「less-than」のバージョンです。下位 64 ビット整数の比較結果を返します。
inline bool equals(__m128i a,__m128i b){
__m128i t = _mm_cmpeq_epi32(a,b);
__m128i z = _mm_and_si128(t,_mm_shuffle_epi32(t,177));
return _mm_cvtsi128_si32(z) & 1;
}
inline bool lessthan(__m128i a,__m128i b){
a = _mm_xor_si128(a,_mm_set1_epi32(0x80000000));
b = _mm_xor_si128(b,_mm_set1_epi32(0x80000000));
__m128i t = _mm_cmplt_epi32(a,b);
__m128i u = _mm_cmpgt_epi32(a,b);
__m128i z = _mm_or_si128(t,_mm_shuffle_epi32(t,177));
z = _mm_andnot_si128(_mm_shuffle_epi32(u,245),z);
return _mm_cvtsi128_si32(z) & 1;
}