директивы ассемблера (16-битные блоки) вместо

ли (быстрый) способ выполнить биты, обратные 32-битным значениям int в регистре avx2? Например.

_mm256_set1_epi32(2732370386); 
<do something here>
//binary: 10100010110111001010100111010010 => 1001011100101010011101101000101
//register contains 1268071237 which is decimal representation of 1001011100101010011101101000101
 harold20 сент. 2017 г., 11:04
Старый способ (обратные байты, обратные группы по 4 сpshufb, Или результаты) обобщает на AVX2, я не могу сразу найти обман
 Paul R20 сент. 2017 г., 11:33
Вы можете просто использовать любой из стандартных хаков с перестановкой битов, чтобы инвертировать байты и затем перемешать байты (см., Например,Восторг Хакера а такжеэтот список).
 John Smith20 сент. 2017 г., 11:02
@JohnZwinck, это на самом деле не имеет значения: как только у меня появится идея, как это сделать, я могу перетасовать 32-битные значения в регистр любым удобным для меня способом.
 John Zwinck20 сент. 2017 г., 11:00
Вы хотите инвертировать биты одного int32 в целочисленном регистре AVX2, или вы хотите инвертировать биты каждого из 8 таких целых чисел?

Ответы на вопрос(1)

Основная идея здесь состоит в том, чтобы использоватьpshufbДвойное использование параллельного поиска в 16-элементной таблице для обращения битов каждого куска. Реверсивные байты очевидны. Поменять порядок двух полубайтов в каждом байте можно, встраивая его в таблицы поиска (сохраняет сдвиг) или явно сдвигая полубайт нижней части (сохраняет LUT).

Как то так в общем, не проверял

__m256i rbit32(__m256i x) {
    __m256i shufbytes = _mm256_setr_epi8(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12);
    __m256i luthigh = _mm256_setr_epi8(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15, 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15);
    __m256i lutlow = _mm256_slli_epi16(luthigh, 4);
    __m256i lowmask = _mm256_set1_epi8(15);
    __m256i rbytes = _mm256_shuffle_epi8(x, shufbytes);
    __m256i high = _mm256_shuffle_epi8(lutlow, _mm256_and_si256(rbytes, lowmask));
    __m256i low = _mm256_shuffle_epi8(luthigh, _mm256_and_si256(_mm256_srli_epi16(rbytes, 4), lowmask));
    return _mm256_or_si256(low, high);
}

В типичном контексте в цикле эти нагрузки должны быть сняты.

странноClang использует 4 шаффлаДублирует первую случайность.

 wim20 сент. 2017 г., 12:02
@ LưuVĩnhPhúc Решение в вашей ссылке переворачивает байты вместо 32-битных.
 phuclv20 сент. 2017 г., 11:42
есть решение для AVX2Вот
 Peter Cordes20 сент. 2017 г., 13:32
Gcc7.2 тоже довольно умный мозг. Получаетсяlutlow в отдельную константу памяти, но она сдвигает ее после загрузки. (Не использовав его ни для чего другого). Я думаю, что он только что создал копиюluthigh но используя.value директивы ассемблера (16-битные блоки) вместо.byte.
 harold20 сент. 2017 г., 11:47
@ LưuVĩnhPhúc хорошо, да, я искал только теги SSE

Ваш ответ на вопрос