Assembly 仅使用XMM寄存器的一部分进行数据传输

Assembly 仅使用XMM寄存器的一部分进行数据传输,assembly,x86,sse,Assembly,X86,Sse,我有一个汇编程序,它在内存中的数据结构上工作,该结构由3个浮点元组(3*32位)组成。我想知道是否可以使用xmm寄存器优化数据复制。 从内存中读取值不会有太大问题,因为我可以只加载4*32位,但有没有办法只将xmm寄存器的一部分写回内存? 我在ISA文档中发现的唯一一件事是,您可以使用writemask,但没有解释如何使用它。通常只有AVX512具有屏蔽存储,如vmovups[rdi]{k1},xmm0 AVX1具有,其工作方式基本相同,但带有矢量控制掩码。(例如,pcmpeqd xmm1,xm

我有一个汇编程序,它在内存中的数据结构上工作,该结构由3个浮点元组(3*32位)组成。我想知道是否可以使用xmm寄存器优化数据复制。 从内存中读取值不会有太大问题,因为我可以只加载4*32位,但有没有办法只将xmm寄存器的一部分写回内存?
我在ISA文档中发现的唯一一件事是,您可以使用writemask,但没有解释如何使用它。

通常只有AVX512具有屏蔽存储,如
vmovups[rdi]{k1},xmm0

AVX1具有,其工作方式基本相同,但带有矢量控制掩码。(例如,
pcmpeqd xmm1,xmm1
/
psrldq xmm1,4
)。但它需要多个UOP。如果目标扩展到另一个页面,它会执行错误抑制,但如果它真的会出现错误,则可能效率低下。如果16字节的目标不跨越页面边界,甚至不跨越缓存线边界,这也没关系。(它可能会触发虚假的缓存未命中,或者必须在缓存线拆分上重放存储uop,即使只有屏蔽部分接触到另一个缓存线。我忘记了,最近也没有检查。)

你不想要SSE2;它具有NT存储语义,因此在写入后将目标从缓存中逐出


如果知道源对象在页面末尾不正确,在没有屏蔽加载/存储的情况下,通常可以安全地加载额外的数据

你不太可能在没有踩到任何重要东西的情况下存储到目的地的尽头。(除非用虚拟元素填充结构以允许此操作,或者它位于数组中,并且无论如何都要存储下一个元素。)

您可以使用2个存储来写入12个字节,一个8字节,一个4字节。(或者两个重叠的8字节存储,如果这更容易洗牌的话)

如果要连续存储到一个结构数组,只需执行一个16字节存储并将其与下一个16字节存储重叠即可。只需注意最后一个元素:剥离最后的迭代

或者使用SSE4.1,取消打包HPD/MOVS可以成为

extractps  [rdi+8], xmm0, 2
(:您不能使用它将标量浮点提取到另一个XMM寄存器,但它对于FP存储到内存非常有用。)


如果您的代码曾经复制过一个副本,那么您可能也希望分别执行这两次加载,这样存储转发就可以工作了


对于8+4字节的加载/存储,您甚至可以使用诸如RAX和EDX之类的GP整数寄存器。(在重叠或4k别名的情况下,更喜欢先进行两次加载,然后进行两次存储,这样CPU就不必计算第二次加载是否与第一次存储重叠)。

通常只有AVX512具有屏蔽存储,如
vmovups[rdi]{k1},xmm0

AVX1具有,其工作方式基本相同,但带有矢量控制掩码。(例如,
pcmpeqd xmm1,xmm1
/
psrldq xmm1,4
)。但它需要多个UOP。如果目标扩展到另一个页面,它会执行错误抑制,但如果它真的会出现错误,则可能效率低下。如果16字节的目标不跨越页面边界,甚至不跨越缓存线边界,这也没关系。(它可能会触发虚假的缓存未命中,或者必须在缓存线拆分上重放存储uop,即使只有屏蔽部分接触到另一个缓存线。我忘记了,最近也没有检查。)

你不想要SSE2;它具有NT存储语义,因此在写入后将目标从缓存中逐出


如果知道源对象在页面末尾不正确,在没有屏蔽加载/存储的情况下,通常可以安全地加载额外的数据

你不太可能在没有踩到任何重要东西的情况下存储到目的地的尽头。(除非用虚拟元素填充结构以允许此操作,或者它位于数组中,并且无论如何都要存储下一个元素。)

您可以使用2个存储来写入12个字节,一个8字节,一个4字节。(或者两个重叠的8字节存储,如果这更容易洗牌的话)

如果要连续存储到一个结构数组,只需执行一个16字节存储并将其与下一个16字节存储重叠即可。只需注意最后一个元素:剥离最后的迭代

或者使用SSE4.1,取消打包HPD/MOVS可以成为

extractps  [rdi+8], xmm0, 2
(:您不能使用它将标量浮点提取到另一个XMM寄存器,但它对于FP存储到内存非常有用。)


如果您的代码曾经复制过一个副本,那么您可能也希望分别执行这两次加载,这样存储转发就可以工作了


对于8+4字节的加载/存储,您甚至可以使用诸如RAX和EDX之类的GP整数寄存器。(最好先进行两次加载,然后进行两次存储,以防重叠或4k混叠,这样CPU就不必计算第二次加载是否与第一次存储重叠)。

据我所知,writemask仅适用于AVX512。如果您发现它在别处被引用,请具体说明。对于复制单个元素,我怀疑您是否比简单的64+32位拷贝有任何优势。如果可能的话,你可以考虑把你的数据填充到4×32位。据我所知,WraveScript只适用于AVX512。如果您发现它在别处被引用,请具体说明。对于复制单个元素,我怀疑您是否比简单的64+32位拷贝有任何优势。如果可能的话,您可以考虑将数据填充到4×32位。如果您可以在“代码> > [ 0,2, 3 ] ] /<代码>中存储三个元素,而不是<代码> > [0, 1, 2,^ ]。您可以保护
unpckhpd
指令:--这当然与重叠加载/存储不兼容。@chtz:right一个
movhps
存储,它不需要随机uop,只是一个纯存储。但是
movhps
load确实需要一个端口5 uop来合并新的high-half。如果您要进行两次单独的加载,那么将它们加载到同一个寄存器中而不是使它们完全独立是没有什么意义的