Подтвердить что ты не робот

Наиболее эффективный способ проверить, все ли компоненты __m128i равны 0 [использование <= встроенных функций SSE4.1]

Я использую встроенные функции SSE, чтобы определить, изменился ли прямоугольник (определяемый четырьмя значениями int32):

__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);

На этом этапе полученное значение xor будет иметь все нули, если прямоугольник не изменился. Каков тогда самый эффективный способ определить это?

В настоящее время я делаю так:

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

Но я предполагаю, что есть более разумный способ (возможно, с использованием некоторой инструкции SSE, которую я еще не нашел).

Я нацеливаюсь на SSE4.1 на x64 и кодирую C++ в Visual Studio 2013.

Изменение: Вопрос не совсем так же, как переменная __m128i ноль? , поскольку это указывает "на процессорах SSE-2 и более ранних" (хотя Антонио действительно добавил ответ "для полноты", который касается 4.1 через некоторое время после того, как этот вопрос был опубликован и на него дан ответ).

4b9b3361

Ответ 1

Вы можете использовать инструкцию PTEST с помощью _mm_testz_si128 собственного (SSE4.1), например:

#include "smmintrin.h" // SSE4.1 header

if (!_mm_testz_si128(xor, xor))
{
    // rectangle has changed
}

Обратите внимание, что _mm_testz_si128 возвращает 1, если побитовый AND из двух аргументов равен нулю.

Ответ 2

Как ни странно, в некоторых случаях команда ptest из SSE 4.1 может быть медленнее, чем pmovmskb из SSE2. Я предлагаю просто:

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

Обратите внимание, что если вам действительно нужно это значение xor, вам придется вычислить его отдельно.

Для процессоров Intel, таких как Ivy Bridge, версия от PaulR с xor и _mm_testz_si128 переводится в 4 раза, а предлагаемая версия без вычислений xor переводится в 3 раза (см. также этот поток). Это может привести к большей пропускной способности моей версии.