La forma más eficiente de verificar si todos los componentes __m128i son 0

Estoy usando intrínsecos SSE para determinar si un rectángulo (definido por cuatro valores int32 ) ha cambiado:

 __m128i oldRect; // contains old left, top, right, bottom packed to 128 bits __m128i newRect; // contains new left, top, right, bottom packed to 128 bits __m128i xor = _mm_xor_si128(oldRect, newRect); 

En este punto, el valor xor resultante será todo ceros si el rectángulo no ha cambiado. ¿Cuál es entonces la forma más eficiente de determinar eso?

Actualmente lo estoy haciendo:

 if (xor.m128i_u64[0] | xor.m128i_u64[1]) { // rectangle changed } 

Pero supongo que hay una forma más inteligente (posiblemente utilizando alguna instrucción SSE que aún no he encontrado).

Estoy apuntando a SSE4.1 en x64 y estoy codificando C ++ en Visual Studio 2013.

Puede utilizar la instalación PTEST a través del intrínseco _mm_testz_si128 (SSE4.1), de esta forma:

 #include "smmintrin.h" // SSE4.1 header if (!_mm_testz_si128(xor, xor)) { // rectangle has changed } 

Tenga en cuenta que _mm_testz_si128 devuelve 1 si el AND de bits de los dos argumentos es cero.

Irónicamente, la instrucción ptest de SSE 4.1 puede ser más lenta que pmovmskb de SSE2 en algunos casos. Sugiero usar simplemente:

 __m128i cmp = _mm_cmpeq_epi32(oldRect, newRect); if (_mm_movemask_epi8(cmp) != 0xFFFF) //registers are different 

Tenga en cuenta que si realmente necesita ese valor xor , tendrá que calcularlo por separado.

Para procesadores Intel como Ivy Bridge, la versión de PaulR con xor y _mm_testz_si128 traduce en 4 uops, mientras que la versión sugerida sin computar xor traduce en 3 uops (vea también este hilo ). Esto puede resultar en un mejor rendimiento de mi versión.