gpt4 book ai didi

assembly - 将 XMM 寄存器设置为重复字节模式(广播常量字节)

转载 作者:行者123 更新时间:2023-12-02 19:36:49 24 4
gpt4 key购买 nike

我知道我们可以这样做来将字符移动到 xmm 寄存器:

movaps xmm1, xword [.__0x20]

align 16
.__0x20 db 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20

但是由于这是一个内存过程,我想知道是否有更好的方法? (另外,我谈论的是 SSE2,而不是其他 SIMD 类型...)

我希望 xmm1 寄存器的每个字节都是 0x20 而不仅仅是一个字节..

(编者注:这可以称为广播或 splat。
这就是 _mm_set1_epi8(0x20) 内在函数的作用。)

最佳答案

仅使用 SSE2,从内存加载完整模式通常是最佳选择。

在您的 NASM 源中,您可以使用 times 16 db 0x20易于维护。


使用 SSE3,您可以使用 movddup 执行 8 字节广播加载。 。使用 AVX,您可以使用 vbroadcastss 进行 4 字节广播加载。 。 这些广播负载在现代 CPU 上非常好,在负载端口上运行,不需要 shuffle uop。即它们与 movaps 一样便宜。在支持它们的 CPU 上,除了一个或两个以上的代码大小。 vbroadcastf128 相同到 YMM 寄存器。

大多数编译器似乎没有意识到这一点,并且会通过 _mm_set1 进行常量传播即使这会导致 32 字节常量而不是 4 字节,即使只是 mov...在循环之前加载它,而不是将其折叠到 ALU 指令的内存操作数中。 (当 AVX512 可用时,这仍然可以通过广播加载实现。)Clang 有时确实会利用广播加载来获取简单常量。

AVX2 添加 vpbroadcastb/w/d/q ,但只有 dword 和 qword 是纯负载微指令。字节和字广播加载需要 ALU shuffle uop,因此对于恒定字节模式,您可能只想广播加载一个重复字节 4 次的双字。 (除非它是来自大型查找表的元素,然后使用字节或字广播负载或 pmovsx 符号扩展负载或其他方式来压缩该表)。

AVX512 添加 vpbroadcastb/w/d/e from an integer register这样你就可以mov eax, 0x20202020/vpbroadcastd xmm0, eax如果您有 AVX512VL。


使用 SSE2,它至少需要 2 条指令,包括 ALU 洗牌,就像这样,而且可能不值得。

    movd    xmm0, [const_4B]
pshufd xmm0, xmm0, 0

一些重复常量可以在几条指令中动态生成,从pcmpeqd xmm0,xmm0开始。 。请参阅What are the best instruction sequences to generate vector constants on the fly?和阿格纳·福格的指南。

这种模式似乎不容易生成。它是一种字节模式(不是字、双字或四字),并且 SSE 移位最多仅适用于字粒度。然而,如果我们知道跨字节边界移位的位是 0,那就没问题了。例如

   pcmpeqd  xmm0, xmm0     ; set1( -1 )
pabsb xmm0, xmm0 ; set1_epi8(1) SSSE3
pslld xmm0, 5 ; set1_epi8(1<<5)

; or with only SSE2, something even less efficient like shift / packsswb / shift

除非您确实想避免常量缓存未命中的可能性,否则这不太值得。平均而言,负载通常会领先。

关于assembly - 将 XMM 寄存器设置为重复字节模式(广播常量字节),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60920572/

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