Можно ли использовать SSE (v2), чтобы сделать целое число шириной 128 бит?
Я хочу немного больше понять возможности SSE2 и хотел бы узнать, можно ли создать целое число шириной 128 бит, которое поддерживает сложение, вычитание, XOR и умножение? Спасибо, Эрклинг.
1 ответ
Решение
SSE2 не имеет флага переноса, но вы можете легко рассчитать перенос как carry = sum < a
или же carry = sum < b
как это Но что еще хуже, SSE2 также не имеет 64-битных сравнений, поэтому вы должны использовать некоторые обходные пути, как здесь
Вот непроверенный, неоптимизированный код C, основанный на идее выше.
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;
}
inline __m128i addi128(__m128i a, __m128i b)
{
__m128i sum = _mm_add_epi64(a, b);
__m128i mask = _mm_set1_epi64(0x8000000000000000);
if (lessthan(_mm_xor_si128(mask, sum), _mm_xor_si128(mask, a)))
{
__m128i ONE = _mm_setr_epi64(0, 1);
sum = _mm_add_epi64(sum, ONE);
}
return sum;
}
Как видите, код требует гораздо больше инструкций, и даже после оптимизации он все равно может быть намного длиннее, чем простая инструкция 2 add/adc в x86_64 (или 4 в x86)