2011-11-03 4 views
11

__m128i変数がSSE-2以前のプロセッサで0以外の値を持つかどうかをテストするにはどうすればよいですか?あなたが行うことができますSSE2で__m128i変数はゼロですか?

+0

ゼロ以外のビット、または8/16/32ビット整数要素を意味しますか? –

+0

@BrettHale:私はそれらがすべてゼロであるかどうかを調べています。 – Mehrdad

答えて

11

__m128i zero = _mm_setzero_si128(); 
if(_mm_movemask_epi8(_mm_cmpeq_epi32(x,zero)) == 0xFFFF) 
{ 
    //the code... 
} 

これは、対応する各intのあなたのビットオフセットは0、4、8 &になりますので、各バイトのためにマスクを返し、ゼロ対4つのint型のをテストします図12に示すように、上記のテストではビットがセットされている場合にキャッチされます。マスクを保持すると、必要に応じて細かい粒度のパーツで直接作業できます。

+2

+1、それは私より優れています。 :)私はあなたがそれを行うことができるか分からなかったので、私はmovemask命令を使用したことはありません。 XD – Mysticial

+0

+1私が見た最もコンパクトなソリューション、ありがとう! – Mehrdad

+3

それ以外の優れた答えにはバグがあります。すべてゼロをチェックしているならば、それは 'if(_mm_movemask_epi8(_mm_cmpeq_epi32(x、zero))== 0xFFFF)'でなければなりません。これは、 '_mm_cmpeq_epi32'がintを0に等しい場合はすべての0に設定するのではなく、' _mm_movemask_epi8'が引数の各バイトの最上位ビットに基づいて最初の16ビットを設定するためです。うまくいけば、著者は答えを編集することができます - 私は試しましたが、拒否されました。 – FarmerBob

1

完全性のために、SSE4では_mm_testz_si128を使用できます。

const bool isAllZero = _mm_testz_si128(a,a); 

すべてのビットがゼロであるときは、このであることに留意されたいです。

+1

これは実際にはわずかに高速で、テストするためにはすべてゼロのレジスタは必要ありません。 'ptest' /' jz'は2 + 1(macro-fuseではありません)です。 'pcmpeq'(1uop)/' pmovmsk'(1uop)/ 'と0xffff'(1uop)/' cmp 0xffff/je'(1uop)です。他のケース(*すべてゼロ要素ではなくゼロ要素)をテストしていた場合は、現在のIntelとAMD CPUでほぼ同じパフォーマンスになります: 'ptest' /' jnz'(3 uops)vs 'pcmpeq' /' pmovmsk'/'test/jnz'(3 uops)です。 –

+0

@PeterCordesその場合、レジスタをすべて1に設定し、 '_mm_testc_si128'を使用するのはどうでしょうか? 'const bool atLeastOneZero = _mm_testc_si128(a、allOnes)'のようなもの – Antonio

+1

もう一度、 'ptest'は少し速いです。 'ptest'を使わずに行うには、all-onesベクタに対して' pcmpeq'を実行し、まったく同じシーケンスを実行して、すべての要素が一致しているかどうかをチェックします。 'pcmpeq'でオールゼロまたはオールワンをチェックすることは、他のパターンに対して==をチェックするのと同じですが、定数がオンザフライで生成されやすいことを除いて(' pxor same、same'または 'pcmpeqw same、同じ)。 –

関連する問題