C++ SSE 命令反转寄存器值

Posted

技术标签:

【中文标题】C++ SSE 命令反转寄存器值【英文标题】:C++ SSE commands invert register values 【发布时间】:2013-08-30 15:11:50 【问题描述】:

我有一个包含一些 int 值的数组([position%2=0] 处的值为负,[position%2=1] 处的值为正)。

我想以 4 步将这些值从数组加载到寄存器,但我希望它们反转(正转换为负,反之亦然)

__m128i v1;
for (int k = 0; k < limit; k += 4) 
        v1 = _mm_load_si128((__m128i *) & myArray[position + k]);

上面的 SSE 代码将值按原样加载到寄存器中:是否有命令取 v1 并将其反转?可以一步/命令完成吗?甚至可以直接从原始数组加载值吗?

任何帮助将不胜感激。提前致谢。

【问题讨论】:

如果您希望 -1 为 1 且 2 为 -2 则称为“否定”。反转是按位不,即反转值中的所有位,所以 -1 将变为 0 【参考方案1】:

假设你的整数元素是 32 位,那么你可以从 0 中减去,例如

v1 = _mm_load_si128(...);                   // load data
v1 = _mm_sub_epi32(_mm_set1_epi32(0), v1);  // negate all elements

【讨论】:

【参考方案2】:

另一种方法是:

__m128i v1 = _mm_xor_si128(
    _mm_load_si128((__m128i *)&myArray[position + k]), 
    _mm_cmpeq_epi8(v1, v1)
);

基本上我们正在这样做:x ^ -1 假设我们使用的是带有二进制补码的机器,所以 -1 是一个全1的序列......

注意以下内容,其中~ 表示反转,^ 表示异或。

~0 == 1 == (0 ^ 1)
~1 == 0 == (1 ^ 1)

_mm_cmpeq_epi8(a, a) 将设置全 1,而您可以使用 _mm_set1_epi32(-1),它实际上可能会更慢,因为它可能会产生内存访问,如果性能是一个问题,我建议进行分析...

【讨论】:

以上是关于C++ SSE 命令反转寄存器值的主要内容,如果未能解决你的问题,请参考以下文章

使用 SSE 将浮点值从 Assembler DLL 返回到 C++

内在函数和寄存器(SSE)

SSE 的整数/浮点值

用于灰度到 ARGB 转换的 C++ SSE2 或 AVX2 内在函数

克隆扩展 XMM 寄存器的 SSE 指令

在 SSE 寄存器中查找最常出现的元素