SSE2 整数溢出检查
SSE2 integer overflow checking
当使用SSE2指令(如PADDD
(即_mm_add_epi32
内联的)时,有没有办法检查是否有任何操作溢出?
我认为也许在溢出后可能会在MXCSR控制寄存器上设置一个标志,但我没有看到这种情况发生。例如,_mm_getcsr()
在以下两种情况下打印相同的值 (8064):
#include <iostream>
#include <emmintrin.h>
using namespace std;
void main()
{
__m128i a = _mm_set_epi32(1, 0, 0, 0);
__m128i b = _mm_add_epi32(a, a);
cout << "MXCSR: " << _mm_getcsr() << endl;
cout << "Result: " << b.m128i_i32[3] << endl;
__m128i c = _mm_set_epi32((1<<31)-1, 3, 2, 1);
__m128i d = _mm_add_epi32(c, c);
cout << "MXCSR: " << _mm_getcsr() << endl;
cout << "Result: " << d.m128i_i32[3] << endl;
}
有没有其他方法可以检查SSE2的溢出?
以下是@hirschhornsalz sum_and_overflow
函数的一个更有效的版本:
void sum_and_overflow(__v4si a, __v4si b, __v4si& sum, __v4si& overflow)
{
__v4si sa, sb;
sum = _mm_add_epi32(a, b); // calculate sum
sa = _mm_xor_si128(sum, a); // compare sign of sum with sign of a
sb = _mm_xor_si128(sum, b); // compare sign of sum with sign of b
overflow = _mm_and_si128(sa, sb); // get overflow in sign bit
overflow = _mm_srai_epi32(overflow, 31); // convert to SIMD boolean (-1 == TRUE, 0 == FALSE)
}
它使用来自 Hacker's Dehappy 第 27 页的溢出检测表达式:
sum = a + b;
overflow = (sum ^ a) & (sum ^ b); // overflow flag in sign bit
请注意,溢出向量将包含更传统的 SIMD 布尔值:-1 表示 TRUE(溢出),0 表示 FALSE(无溢出)。如果您只需要符号位中的溢出,而其他位是"不关心",则可以省略函数的最后一行,从而将 SIMD 指令的数量从 5 个减少到 4 条。
注意:此解决方案以及它所基于的先前解决方案适用于有符号整数值。无符号值的解决方案需要稍微不同的方法(请参阅佳能@Stephen答案)。
由于您有 4 个可能的溢出,因此控制寄存器很快就会耗尽位,特别是如果您想要进位、符号等,甚至对于由 16 个字节组成的向量加法:-)
相等且结果符号位与输入符号位不同,则设置溢出标志。
此函数手动计算sum = a+b
和溢出。对于每个溢出0x80000000都会在overflow
中重新出现。
void sum_and_overflow(__v4si a, __v4si b, __v4si& sum, __v4si& overflow) {
__v4si signmask = _mm_set1_epi32(0x80000000);
sum = a+b;
a &= signmask;
b &= signmask;
overflow = sum & signmask;
overflow = ~(a^b) & (overflow^a); // overflow is 1 if (a==b) and (resultbit has changed)
}
注意:如果您没有 gcc,则必须将^
&
+
运算符替换为适当的 SSE 内部函数,如 _mm_and_si128()
、_mm_add_epi32()
等。
编辑:我刚刚注意到带有掩码的and
当然可以在函数的最后完成,节省两个and
操作。但是编译器很可能足够聪明,可以自己完成。
我注意到您也要求为未签名的解决方案;幸运的是,这也很容易:
__v4si mask = _mm_set1_epi32(0x80000000);
sum = _mm_add_epi32(a, b);
overflow = _mm_cmpgt_epi32(_mm_xor_si128(mask, a), _mm_xor_si128(mask, sum));
通常要检测无符号溢出,您只需检查 sum < a
或 sum < b
. 但是,SSE 没有无符号比较; xor
-ing 参数与 0x80000000
允许您使用有符号比较来获得相同的结果。
基础 PADDD 指令不会触及任何标志。
因此,要对此进行测试,您必须编写其他代码,具体取决于您要执行的操作。
注意:由于缺乏 epi32 内涵,您有点受阻
- 优化正在杀死我在 clang 6 中的整数溢出检查
- 从双精度转换为整数的显式类型是否始终检查整数溢出?
- 结构上溢出的整数加法
- 检查整数是否增加了C++
- 如何检查整数是否包含数字 0 和 1
- 如何检查整数是否发生过或在读取C 的输入文件时发生了字符
- 检查整数是否是 8 的倍数
- 为什么 C 和 C++ 没有内置方法来检查整数溢出?
- 整数溢出和整数限制
- 从整数列表中交叉检查整数运行时错误
- SSE2 整数溢出检查
- 检查整数是否具有整数立方根
- C++正在检查整数
- 如何在C++中检查整数单链表的对称性
- 函数检查整数类型是否适合可能不同(整数)类型的值
- 用于检查整数是否包含给定十六进制模式的c++代码
- 有效地检查整数的奇偶性
- Cin读取数字并检查整数
- 什么时候需要检查整数溢出
- 在qt中NULL检查整数