PADDD
SSE2 命令(つまり組み込み命令)を使用する場合_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 でオーバーフローをチェックする他の方法はありますか?
ベストアンサー1
これはもう少し効率的なバージョンです@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)
}
オーバーフロー検出には、ハッカーの喜び27ページ:
sum = a + b;
overflow = (sum ^ a) & (sum ^ b); // overflow flag in sign bit
オーバーフロー ベクトルには、TRUE (オーバーフロー) の場合は -1、FALSE (オーバーフローなし) の場合は 0 という、より一般的な SIMD ブール値が含まれることに注意してください。符号ビットのオーバーフローのみが必要で、他のビットは「無視」する場合は、関数の最後の行を省略して、SIMD 命令の数を 5 から 4 に減らすことができます。
注意:このソリューションは、以前のソリューションのベースは符号付き整数値用です。符号なし整数値の場合は、少し異なるアプローチが必要になります(@スティーブン・キャノンの答え)。