将XMM寄存器设置为重复字节模式(广播一个恒定字节)

问题描述 投票:0回答:1

我知道我们可以做类似的事情来将字符移动到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,而不只是一个字节..

(编者注:这可以称为广播或摔角。这就是_mm_set1_epi8(0x20)内部函数所做的。)

assembly sse micro-optimization sse2
1个回答
2
投票

仅使用SSE2,通常最好从内存中加载完整模式。

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


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

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

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

[AVX512添加pmovsx,因此如果具有AVX512VL,则可以vpbroadcastb/w/d/e from an integer register / vpbroadcastb/w/d/e


对于SSE2,这样至少需要2条指令,包括ALU随机播放,可能不值得。

mov eax, 0x20202020

可以从一对vpbroadcastd xmm0, eax的全1开始,通过几个指令快速生成一些重复常数。请参阅 movd xmm0, [const_4B] pshufd xmm0, xmm0, 0 和Agner Fog的指南。

此模式确实不是

似乎易于生成。这是一种字节模式(不是word,dword或qword),并且SSE移位最多只能使用单词粒度。但是,如果我们知道跨字节边界移位的位为0,就可以了。例如
pcmpeqd xmm0,xmm0

这不太可能值得,除非您确实想避免该常量发生缓存丢失的可能性。平均而言,通常会提前产生负载。

© www.soinside.com 2019 - 2024. All rights reserved.