2016-07-31 4 views
2

У меня есть вектор восьми беззнаковых 8-битных чисел в диапазоне 0 .. 12 в xmm0. Я хочу, чтобы выполнить следующий перевод по каждому элементу e в векторе:Как перевернуть диапазон в SSE, сохраняя одно значение без изменений?

if (e != 12) 
    e = 11 - e; 

То есть, число 0, 1, ..., 11 заменены на 11, 10, ..., 0, тогда как 12 остается неизменным. Других ценностей не происходит, мне все равно, что с ними происходит.

Как я могу эффективно реализовать эту операцию с помощью набора инструкций SSE4?

ответ

5

Для SSE2 (вы не спрашивали, но ..), я предлагаю следующее, повторное использование маски из сравнения сделать забавное отрицание:

e = (e^mask) + (12 & mask) 

Что для истинной маски превращается в ~e + 12 = -e + -1 + 12 = 11 - e и для ложной маски это, очевидно, идентичность.

Или в векторном материал, (не тестировался)

movdqa xmm1, [vec12] 
pcmpgtb xmm1, xmm0 
pxor xmm0, xmm1 
pand xmm1, [vec12] 
paddb xmm0, xmm1 

Для SSSE3 и выше, вы можете использовать наш старый друг pshufb, так как при этом диапазон значений может быть 16-запись таблицы поиска: (не испытания)

movdqa xmm1, [table] 
pshufb xmm1, xmm0 

Если таблица выглядит (не тестировалось)

.db 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 12, "yolo" 
+2

Ого, я совсем забыл О пользователе pshufb! Для первого я подумал о выполнении ((12 - v) + 243) - 243), где добавление является насыщающим добавлением, которое переместит результат в нужные места. Но при всех массах для этого, ваш подход, скорее всего, быстрее. – fuz