Как повернуть упакованные четырехслойные слова в регистр xmm? - PullRequest
0 голосов
/ 06 декабря 2018

Учитывая 128-битный регистр xmm, который упакован двумя четырьмя словами (то есть двумя 64-битными целыми числами):

     ╭──────────────────┬──────────────────╮
xmm0 │ ffeeddccbbaa9988 │ 7766554433221100 │
     ╰──────────────────┴──────────────────╯

Как мне выполнить вращение наотдельные четыре слова?Например:

prorqw xmm0, 32   // rotate right packed quadwords

     ╭──────────────────┬──────────────────╮
xmm0 │ bbaa9988ffeeddcc │ 3322110077665544 │
     ╰──────────────────┴──────────────────╯

Я знаю, что SSE2 обеспечивает:

  • PSHUFW: в случайном порядке слова (16 бит)
  • PSHUFD: в случайном порядке двойные слова (32 бита)

Хотя я не знаю, что делают инструкции, также нет четырехзначного (64-разрядного) варианта.

Бонусный вопрос

Как бы вы выполнили ROR регистра xmm - при условии, что упакованные данные других размеров?

  • Повернуть упакованные вправо двойные слова на 16 бит:

         ╭──────────┬──────────┬──────────┬──────────╮
    xmm0 │ ffeeddcc │ bbaa9988 │ 77665544 │ 33221100 │
         ╰──────────┴──────────┴──────────┴──────────╯
                            ⇓
         ╭──────────┬──────────┬──────────┬──────────╮
    xmm0 │ ddccffee │ 9988bbaa │ 55447766 │ 11003322 │
         ╰──────────┴──────────┴──────────┴──────────╯
    
  • Повернуть вправо в упакованном виде Слова на 8 бит:

         ╭──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────╮
    xmm0 │ ffee │ ddcc │ bbaa │ 9988 │ 7766 │ 5544 │ 3322 │ 1100 │
         ╰──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────╯
                            ⇓
         ╭──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────╮
    xmm0 │ eeff │ ccdd │ aabb │ 8899 │ 6677 │ 4455 │ 2233 │ 0011 │
         ╰──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────╯
    

Дополнительный бонусный вопрос

Как бы вы выполнили вышеуказанное, если бы это был 256-битный ymm регистр?

     ╭──────────────────────────────────┬──────────────────────────────────╮
ymm0 │ 2f2e2d2c2b2a29282726252423222120 │ ffeeddccbbaa99887766554433221100 │ packed doublequadwords
     ╰──────────────────────────────────┴──────────────────────────────────╯
     ╭──────────────────┬──────────────────┬──────────────────┬──────────────────╮
ymm0 │ 2f2e2d2c2b2a2928 │ 2726252423222120 │ ffeeddccbbaa9988 │ 7766554433221100 │ packed quadwords
     ╰──────────────────┴──────────────────┴──────────────────┴──────────────────╯
     ╭──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────┬──────────╮
ymm0 │ 2f2e2d2c │ 2b2a2928 │ 27262524 │ 23222120 │ ffeeddcc │ bbaa9988 │ 77665544 │ 33221100 │ packed doublewords
     ╰──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────┴──────────╯
     ╭──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────╮
ymm0 │ 2f2e │ 2d2c │ 2b2a │ 2928 │ 2726 │ 2524 │ 2322 │ 2120 │ ffee │ ddcc │ bbaa │ 9988 │ 7766 │ 5544 │ 3322 │ 1100 │ packed words
     ╰──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────╯

Bonus Reading

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Хотя я спрашивал о выполнении поворота вправо , одно подмножество ROR - это когда вы выполняете ROR двух 64-битных значений ровно 32 битами.Это заставляет ваш произвольный поворот превращаться в простой обмен старших и младших 32-битных:

enter image description here

Зная, что выВы просто выполняете 32-битный (то есть doubleword ) своп, вы можете использовать другую инструкцию:

  • pshufd : перемешать упакованные двойные слова

Кодировка инструкции хитрая, и Intel делает все возможное, чтобы запутать документацию .Идея состоит в том, что вы можете рассматривать 128-битный xmm как 32-битные двойные слова и передавать их туда, куда вам нравится:

enter image description here

Кодировка хитрая:

pshufd xmm0, xmm0, 0x02030001

Поскольку я толкаю четыре двойных слов, маска состоит из четырех частей:

02 03 00 01

Они расположены слева направо, сообщая вам индекс того, где должно быть перетасовано это 32-битное двойное словодо:

enter image description here

Если вы вращаете 64-битные четырехслойные слова, которые упакованы в регистр xmm, ровно на 32 бита, вы можетеиспользуйте:

pshufd xmm0, xmm0, 0x02030001 //rotate packed quadwords by 32-bits¹

RotateRight (16)

Что теперь делать, если:

  • вместо ROR(32) из 64-битных четырех слов, упакованных в xmm
  • Я хотел ROR(16)

enter image description here

Мы можем применить тот же трюк.Предположим, что 64-разрядные четверные слова разделены на 16-разрядные слова, и перемешайте их:

enter image description here

pshufw xmm0, xmm0, 0x0605040702010003 //shuffle packed words¹

За исключением того, что pshufw не может работать с регистрами xmm,Поэтому я остановился.

RotateRight (24)

А что если:

  • вместо ROR(32) 64-битных четырехсловупаковано в xmm
  • я хотел ROR(24)

enter image description here

Мы можем применять те же вещи.Предположим, что 64-разрядные четырехслойные слова разделены на 8-разрядные слова ....

pshufb xmm0, xmm0, что-то // перемешать упакованные байты

Хорошо, я подберу это завтра,Сейчас я устал.Я надеялся просто набрать одну строку кода;вместо этого это был четырехчасовой укол боли.Я просто предполагал, что у людей все эти основные операции будут задокументированы;ЦП работает около 3 лет.

RotateRight (1)

Да, позже.

Сноски

- Думаю.Я не уверен, что правильно понял кодировку.

0 голосов
/ 06 декабря 2018

Если число вращений кратно 8, вы можете использовать перемешивание байтов. SSSE3 pshufb с маской управления может обрабатывать любые другие кратные 8 в одной инструкции.

SSE2 pshufd может обрабатывать count = 32, меняя местами дваполовинки каждого qword: _MM_SHUFFLE(2,3, 0,1) или в asm pshufd xmm0, xmm0, 0b10_11_00_01 (NASM поддерживает _ в качестве необязательного разделителя, например C ++ 11 для числовых литералов.)

SSE2 pshuflw +pshufhw для счетчиков, кратных 16, неплохо для версии вашей функции без SSSE3, но вам нужны отдельные тасовки для низкого / высокого слова.(Управляющий байт imm8 содержит только четыре 2-битных поля.) Или с AVX2 для нечетных / четных слов в каждой дорожке.


Если число поворотов равно , а не , кратное 8 , есть AVX512F vprolq zmm0, zmm1, 13 и vprorq.Также доступно в версии с переменным количеством, с количеством элементов на элемент из другого вектора вместо непосредственного.vprolvq / vprorvq.Также доступно в степени детализации слова, но не в слове и не в байтах.


В противном случае только с SSE2 и числом, не кратным 16, вам нужно сдвиг влево + вправо + ИЛИ , чтобы на самом делереализовать в asm общий способ выражения поворота в C как (x << n) | (x >> (64-n)).( Лучшие практики для операций циклического сдвига (поворота) в C ++ указывают способы обхода потенциального C UB из числа сдвигов вне диапазона, что не является проблемой для встроенных функций или asm, поскольку поведение asmи Intel четко определяет внутреннюю: сдвиги SIMD насыщают счетчик сдвигов, а не маскируют его как скалярные сдвиги.)

SSE2 имеет сдвиги с гранулярностью 16 бит, так что вы можете сделать это напрямую.

Для детализации байтов вам потребуется дополнительная маскировка, чтобы обнулить биты, которые сдвигаются между байтами в слове. Эффективный способ вращения байта в регистре AVX .Или используйте трюки, такие как pmullw с вектором степени 2, позволяющие подсчитывать переменные на элемент.(Там, где AVX2 обычно имеет только сдвиги с переменным счетом для dword / qword).

...