gpt4 book ai didi

c - 在 GNU C 内联汇编中,单个操作数的 xmm/ymm/zmm 的大小覆盖修饰符是什么?

转载 作者:太空狗 更新时间:2023-10-29 16:34:17 27 4
gpt4 key购买 nike

在尝试回答 Embedded broadcasts with intrinsics and assembly 时,我正在尝试做这样的事情:

__m512 mul_bcast(__m512 a, float b) {
asm(
"vbroadcastss %k[scalar], %q[scalar]\n\t" // want vbcast.. %xmm0, %zmm0
"vmulps %q[scalar], %[vec], %[vec]\n\t"
: [vec] "+x" (a), [scalar] "+&x" (b)
: :
);
return a;
}

GNU C x86 Operand Modifiers doc 仅指定最大 q 的修饰符(DI (DoubleInt) 大小,64 位)。在 vector 寄存器上使用 q 将始终将其降低到 xmm(来自 ymmzmm)。例如标量寄存器:

 long scratch = 0;  // not useful instructions, just syntax demo
asm(
"movw symbol(%q[inttmp]), %w[inttmp]\n\t" // movw symbol(%rax), %ax
"movsbl %h[inttmp], %k[inttmp]\n\t" // movsx %ah, %eax
: [inttmp] "+r" (scratch)
:: "memory" // we read some index in symbol[]
);

问题:

在 vector 寄存器大小之间更改的修饰符是什么?

此外,输入或输出操作数是否有任何特定的大小限制?不同于通用 x 的东西,它最终可能是 xmm、ymm 或 zmm,具体取决于您放在括号中的表达式的类型。

题外话:
clang 似乎有一些 Yi/Yt 约束(不是修饰符),但我也找不到相关文档。 clang 甚至不会编译它,即使 vector 指令被注释掉,因为它不喜欢 +x 作为 __m512 vector 的约束。


背景/动机

我可以通过将标量作为输入操作数传递来获得我想要的结果,它被限制在与更广泛的输出操作数相同的寄存器中,但它比较笨拙。 (此用例的最大缺点是 AFAIK 匹配约束只能通过操作数编号引用,而不是 [symbolic_name],因此在添加/删除输出约束时很容易损坏。)

// does what I want, by using a paired output and input constraint
__m512 mul_bcast(__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;
}

关于 Godbolt compiler explorer


此外,我认为我试图解决的问题的整个方法将是死胡同,因为 Multi-Alternative constraints不要让您为不同的约束模式提供不同的 asm。我希望 xr 约束最终从寄存器发出 vbroadcastss,而 m 约束结束发射 vmulps (mem_src){1to16}, %zmm_src2, %zmm_dst(折叠广播负载)。使用内联 asm 这样做的目的是 gcc 还不知道如何将 set1() 内存操作数折叠到广播负载中(但 clang 知道)。

无论如何,这个具体问题是关于 vector 寄存器的操作数修饰符和约束。请关注这一点,但欢迎对另一个问题发表评论和回答。 (或者更好,只是评论/回答 Z Boson 关于嵌入式广播的问题。)

最佳答案

来自文件gcc/config/i386/i386.c GCC 来源:

       b -- print the QImode name of the register for the indicated operand.        %b0 would print %al if operands[0] is reg 0.       w --  likewise, print the HImode name of the register.       k --  likewise, print the SImode name of the register.       q --  likewise, print the DImode name of the register.       x --  likewise, print the V4SFmode name of the register.       t --  likewise, print the V8SFmode name of the register.       g --  likewise, print the V16SFmode name of the register.       h -- print the QImode name for a "high" register, either ah, bh, ch or dh.

类似于gcc/config/i386/contraints.md :

    ;; We use the Y prefix to denote any number of conditional register sets:    ;;  z   First SSE register.    ;;  i   SSE2 inter-unit moves to SSE register enabled    ;;  j   SSE2 inter-unit moves from SSE register enabled    ;;  m   MMX inter-unit moves to MMX register enabled    ;;  n   MMX inter-unit moves from MMX register enabled    ;;  a   Integer register when zero extensions with AND are disabled    ;;  p   Integer register when TARGET_PARTIAL_REG_STALL is disabled    ;;  f   x87 register when 80387 floating point arithmetic is enabled    ;;  r   SSE regs not requiring REX prefix when prefixes avoidance is enabled    ;;  and all SSE regs otherwise

此文件还定义了一个“Yk”约束,但我不知道它在 asm 语句中的效果如何:

    (define_register_constraint "Yk" "TARGET_AVX512F ? MASK_EVEX_REGS : NO_REGS"    "@internal Any mask register that can be used as predicate, i.e. k1-k7.")

请注意,这都是从最新的 SVN 修订版复制而来的。我不知道 GCC 的哪个版本(如果有)添加了您感兴趣的特定修饰符和约束。

关于c - 在 GNU C 内联汇编中,单个操作数的 xmm/ymm/zmm 的大小覆盖修饰符是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34459803/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com