如何连接两个 SSE 寄存器的低半部分?

How to concatenate the low halves of two SSE registers?

我有两个 SSE 寄存器,我想用另一个的低半部分替换一个的高半部分。和往常一样,最快的方式。

我想这是可行的,方法是将其中一个寄存器移位 8 个字节,然后 alignr 连接起来。

有单指令解决方案吗?

您可以使用 punpcklqdq 将两个寄存器的低半部分合并为一个寄存器中的 hi:lo。这与 movlhps FP 指令以及 unpcklpd 的作用相同,但在关心 FP 与整数混洗以绕过延迟的 CPU 上的整数域中运行。


额外阅读:组合两个寄存器的不同部分

palignr 仅适用于将 hi:xxxxxx:lo 组合以生成 lo:hi(即反转)。您可以使用 FP shuffle(movsd 的寄存器-寄存器形式)得到 hi:lo(通过移动 xxx:lo 的低半部分来替换 hi:xxx 中的低垃圾) .没有它,你会想要使用 punpckhqdq 将一个寄存器的高半部分带到低半部分,然后使用 punpcklqdq 组合两个寄存器的低半部分。

在 Intel Nehalem 以外的大多数 CPU 上,整数数据上的浮点混洗通常很好(在向量整数 ALU 指令之间使用时很少或没有额外延迟)。在 Nehalem 上,您可能会在浮点洗牌中进出两个周期的额外延迟(总共 4 个周期的延迟),但如果它是循环携带的依赖链的一部分,这只是吞吐量的一个大问题。有关详细信息,请参阅 Agner Fog's guides

Agner 的优化汇编指南还有一整节 SSE/AVX 指令表,这些指令对于寄存器内或寄存器之间的各种数据移动很有用。请参阅 标签 wiki 以获得 link,下载 PDF,阅读第 130 页的第 13.7 "Permuting data" 部分。

要将 FP 混洗与内在函数一起使用,您必须使用 _mm_castsi128_ps_mm_castps_si128 来打乱您的代码,它们是不发出任何指令的重新解释转换。