При попытке ответить встроенные трансляции со встроенными функциями и сборкой я пытался сделать что-то вроде этого:
__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 о встроенных трансляциях.)