【发布时间】:2016-06-10 04:47:32
【问题描述】:
将 xmm0 寄存器移动到 eax 和 edx 的短 x86 指令序列是什么?
【问题讨论】:
-
除非必要,否则不要在不同的域之间移动
将 xmm0 寄存器移动到 eax 和 edx 的短 x86 指令序列是什么?
【问题讨论】:
你想要 xmm0 的哪些部分?
movd eax, xmm0
pextrd edx, xmm0, 1 ; SSE4.1
将 xmm0 的低 64 位获取到 edx:eax。如果您需要所有 4 个部分,请考虑存储到内存并重新加载:存储转发到加载具有更多延迟,但比随机播放具有更好的吞吐量(总 uops 更少),特别是如果您可以将它们用作内存源操作数而不仅仅是 mov。
(但是如果你想要一个水平和什么的,通常do that with SIMD shuffles像pshufd/paddd两次将4个元素减少到2然后到1。虽然movd eax, xmm0/movdqa [esp], xmm0存储和3个标量在这种情况下,add eax, [esp + 4/8/12] 实际上对于总 uops 或延迟来说还不错,不像标量 FP,其中延迟更高,并且无论如何您都希望在 XMM reg 中得到结果。)
在 64 位代码中,movq rax, xmm0 / shld rdx, rax, 32 可能优于 pextrd,并且不需要 SSE4.1。
更普通的mov rdx, rax / shr rdx, 32 可能比 SHLD 更有效,即使它在 Intel CPU 上花费更多微指令。 shld 在 AMD CPU 上很慢,在 Zen 上是 8 uops。 (https://uops.info/)
BMI2 rorx rdx, rax, 32 是一种复制和移位的好方法,并且在所有支持它的 CPU 上都很有效。当然,RDX 的高半部分可能不为零,但这很好。
另一个选择是movd/movq,如果您没有接近他们竞争的单个端口的吞吐量瓶颈。在大多数 CPU 上,它们实际上不能并行运行,因此 movd/movq 竞争一个端口仍然会花费第二个端口的延迟。在具有 mov-elimination(Zen 或 IvyBridge)的现代 CPU 上,零延迟的mov rdx, rax 更好。但这确实会使您在 EAX 和 EDX 中的值零扩展为 RAX 和 RDX。
movq rdx, xmm0
movd eax, xmm0 ; or schedule this first if you can use EAX right away
shr rdx, 32
请参阅x86 标签 wiki 以获取指令集参考和其他内容。
请参阅Agner Fog's excellent Optimizing Assembly guide,了解使用说明的提示。
【讨论】:
movd?
pshufd + movd,或任何其他方便的随机播放将您想要的元素带到低 64 位或 32 位。