_mm_cmpgt_epi64内部函数如何工作

时间:2018-10-14 17:59:25

标签: x86-64 sse simd intrinsics sse4

我正在使用_mm_cmpgt_epi64内部函数来实现128位加法,后来又实现256位加法。 看着这种内在的结果,有些让我感到困惑。

我不明白为什么计算出的蒙版是这样的。

const __m128i mask = _mm_cmpgt_epi64(bflip, sumflip);

这是我的调试器中的输出:

(lldb) p/x bflip
(__m128i) $1 = (0x00000001, 0x80000000, 0x00000000, 0x80000000)
(lldb) p/x sumflip
(__m128i) $2 = (0x00000000, 0x80000000, 0xffffffff, 0x7fffffff)
(lldb) p/x mask
(__m128i) $3 = (0xffffffff, 0xffffffff, 0x00000000, 0x00000000)

对于第一个64位通道(63:0),我很好。但是,为什么第二个车道(127:64)也不满?

在我看来0x8000000000000000> 0x7fffffffffffffff

1 个答案:

答案 0 :(得分:1)

您似乎正在以32位而不是64位的形式打印它,这很奇怪。

但是无论如何,这是signed two's complement整数比较,如手册中所述:http://felixcloutier.com/x86/PCMPGTQ.html

0x8000000000000000是最负的64位整数,而0x7fffffffffffffff是最大的正整数。

如果要进行无符号比较,则需要通过翻转两个符号位来对它们进行范围移位。从逻辑上讲,这是从0..2 ^ 64-1减去2 ^ 63到-2 ^ 63 .. 2 ^ 63-1。但是我们可以使用更高效的XOR来完成此操作,因为XOR是不带进位的加法,并且进位/借位不在寄存器的末尾。

const __m128i rangeshift = _mm_set1_epi64x(0x8000000000000000);
const __m128i mask = _mm_cmpgt_epi64(_mm_xor_si128(bflip, rangeshift), _mm_xor_si128(sumflip, rangeshift));

或使用AVX512F __mmask8 _mm512_cmp[eq|ge|gt|le|lt|neq]_epu64_mask( __m512i a, __m512i b)