Как работают __builtin_ia32_unpcklps / hps и __builtin_ia32_movlhps / hlps? - PullRequest
2 голосов
/ 15 мая 2019

Я ищу оптимизированные способы транспонирования матрицы на ЦП только с известным номером набора кеша и размером блока.Я обнаружил, что встроенные функции Intel содержат низкоуровневую транспонированную матрицу 4x4.Следующее:

#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3)           \
do {                                    \
  __v4sf __r0 = (row0), __r1 = (row1), __r2 = (row2), __r3 = (row3);    \
  __v4sf __t0 = __builtin_ia32_unpcklps (__r0, __r1);           \
  __v4sf __t1 = __builtin_ia32_unpcklps (__r2, __r3);           \
  __v4sf __t2 = __builtin_ia32_unpckhps (__r0, __r1);           \
  __v4sf __t3 = __builtin_ia32_unpckhps (__r2, __r3);           \
  (row0) = __builtin_ia32_movlhps (__t0, __t1);             \
  (row1) = __builtin_ia32_movhlps (__t1, __t0);             \
  (row2) = __builtin_ia32_movlhps (__t2, __t3);             \
  (row3) = __builtin_ia32_movhlps (__t3, __t2);             \
} while (0)

Функции, которые он использует, являются встроенными функциями компилятора GCC, которые используют команды сборки UNPCKHPS / LPS и MOVLHPS / HLPS x86.Это я понимаю, и я примерно понимаю, как эти команды будут работать вместе, чтобы транспонировать 4 строки.

Однако я хотел протестировать эти функции, поэтому я скопировал это в свой код и слегка его отредактировал.

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

#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3)           \
do {                                    \
  __v4sf __r0 = (row0), __r1 = (row1), __r2 = (row2), __r3 = (row3);    \
  __v4sf __t1 = __builtin_ia32_unpcklps (__r2, __r3);           \
  __v4sf __t2 = __builtin_ia32_unpckhps (__r0, __r1);           \
  __v4sf __t3 = __builtin_ia32_unpckhps (__r2, __r3);           \
  (row0) = __builtin_ia32_movlhps (__builtin_ia32_unpcklps (__r0, __r1), __t1);             \
  (row1) = __builtin_ia32_movhlps (__t1, __builtin_ia32_unpcklps (__r0, __r1));             \
  (row2) = __builtin_ia32_movlhps (__t2, __t3);             \
  (row3) = __builtin_ia32_movhlps (__t3, __t2);             \
} while (0)

Кто-нибудь знает, почему это произойдет?Обычно, если вы измените порядок вызовов функций (при условии, что они не работают с одним и тем же указателем) не может повлиять на выполнение.

...