SSE2 整数オーバーフローチェック 質問する

SSE2 整数オーバーフローチェック 質問する

PADDDSSE2 命令(つまり組み込み命令)を使用する場合_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 に減らすことができます。

注意:このソリューションは、以前のソリューションのベースは符号付き整数値用です。符号なし整数値の場合は、少し異なるアプローチが必要になります(@スティーブン・キャノン答え)。

おすすめ記事