При попытке ответить встроенные трансляции со встроенными функциями и сборкой я пытался сделать что-то вроде этого:
__m512 mul_broad(__m512 a, float b) {
int scratch = 0;
asm(
"vbroadcastss %k[scalar], %q[scalar]\n\t" // want vbr.. %xmm0, %zmm0
"vmulps %q[scalar], %[vec], %[vec]\n\t"
// how it done for integer registers
"movw symbol(%q[inttmp]), %w[inttmp]\n\t" // movw symbol(%rax), %ax
"movsbl %h[inttmp], %k[inttmp]\n\t" // movsx %ah, %eax
: [vec] "+x" (a), [scalar] "+x" (b), [inttmp] "=r" (scratch)
:
:
);
return a;
}
GNU C x86 Операндовые модификаторы doc задает только модификаторы до q
(размер DI (DoubleInt), 64 бит). Использование q
в векторном регистре всегда сводится к xmm
(от ymm
или zmm
).
Вопрос:
Какие модификаторы изменяются между размерами векторного регистра?
Кроме того, существуют ли ограничения определенного размера для использования с входными или выходными операндами? Что-то другое, чем общий x
, который может быть xmm, ymm или zmm в зависимости от типа выражения, которое вы помещаете в круглые скобки.
Не по теме:
clang, похоже, имеет некоторые ограничения Yi
/Yt
(не модификаторы), но я не могу найти документы на этом. clang даже не скомпилирует это, даже с комментариями векторных инструкций, потому что ему не нравится +x
как ограничение для вектора __m512
.
Фон/мотивация
Я могу получить результат, который я хочу, передав в скалярном виде входной операнд, который должен быть в том же регистре, что и более широкий выходной операнд, но он неуклюже. (Самый большой недостаток в этом случае - AFAIK, он должен использовать номер операнда, а не [symbolic_name]
, поэтому он может быть поврежден при добавлении/удалении ограничений вывода.)
// does what I want, by using a paired output and input constraint
__m512 mul_broad(__m512 a, float b) {
__m512 tmpvec;
asm(
"vbroadcastss %[scalar], %[tmpvec]\n\t"
"vmulps %[tmpvec], %[vec], %[vec]\n\t"
: [vec] "+x" (a), [tmpvec] "=x" (tmpvec)
: [scalar] "1" (b)
:
);
return a;
}
Кроме того, я думаю, что весь этот подход к проблеме, которую я пытался решить, будет тупиком, потому что Multi-Alternative constraints не позволяйте вам давать разные asm для разных шаблонов ограничений. Я надеялся, что ограничения x
и r
в конечном итоге испускают a vbroadcastss
из регистра, а ограничения m
в конечном итоге испускают vmulps (mem_src){1to16}, %zmm_src2, %zmm_dst
(сложенная широковещательная загрузка). Целью этого делать с inline asm является то, что gcc еще не знает, как сбрасывать операнды памяти set1()
в широковещательные нагрузки (но clang делает).
В любом случае, этот конкретный вопрос касается модификаторов операндов и ограничений для векторных регистров. Пожалуйста, сосредоточьтесь на этом, но комментарии и ответы в ответах приветствуются по другому вопросу. (Или лучше, просто прокомментируйте/ответьте на вопрос Z Boson о встроенных трансляциях.)