如何在 XMM 寄存器之间交换值?

Posted

技术标签:

【中文标题】如何在 XMM 寄存器之间交换值?【英文标题】:How to exchange values between XMM registers? 【发布时间】:2013-06-18 05:51:55 【问题描述】:

是否有一个或两个用于在 XMM 寄存器之间交换值的 x86 指令;类似于 XCHG 指令?不能使用内存、临时寄存器或 XOR 副本。

【问题讨论】:

XOR 交换的算术版本呢?但是为什么你什么都不能用呢? How do you move 128-bit values between XMM registers?的可能重复 @BrettHale 他必须为此使用暂存器 如果您考虑一下,要使 xchg 工作,它必须首先在某处使用偷偷摸摸的寄存器或内存位置来交换值。如果你可以“什么都不用”,那么只有 xor 会这样做。看起来他们从未为 xmm 寄存器集提供此功能 @ady 完全没有意义,xchg 的问题在于,如果它有一个内存操作数,它就有一个隐式锁。这不是交换的固有问题。两个 xmm 寄存器之间的交换会很好。他们甚至可以通过寄存器重命名来实现它,使其成为 0 延迟(他们为fxch 这样做,所以为什么不这样做)。我怀疑它不存在的原因是它没有足够的必要——你可以只使用一个临时寄存器.. 【参考方案1】:

这是arithmetic swap 的完全未经测试的代码:

vpsubd xmm0, xmm1
vpaddd xmm1, xmm0
vpsubd xmm0, xmm1, xmm0

与 xor 不同,减法不是可交换的,因此您最终会遇到不幸的最后一行,如果没有 avx,您将无法真正做到(嗯,您可以,但是使用暂存器,然后您最好使用移动)。

在大多数处理器上使用暂存寄存器会更快(我想 P4 除外,但没人关心 P4,对吧?)。在较旧的处理器上,因为前两个移动可以并行执行,在最新的处理器上,因为它们在前端处理 xmm reg-reg 移动,使用寄存器重命名。寄存器重命名和纯粹用重命名处理指令都不是新技巧,自从 Pentium Pro 和fxch 开始使用重命名时,通常使用重命名来实现。使用寄存器重命名实现 xmm reg-reg 移动是一个相当新的技巧,它在 Ivy Bridge、Haswell、Bulldozer 和 Piledriver 中使用。

通常,您可以通过将循环展开 2 来摆脱循环中的交换。不在循环中的交换很少需要,更不会成为瓶颈。

【讨论】:

【参考方案2】:

xchg 操作的真正价值在于它在同步原语、自旋锁等中的使用。由于其隐含的lock 前缀,它可能会造成严重的惩罚。当然没有人会使用 SSE 实现同步原语,但是交换有什么优点吗?有时它可能有用,但在 32 位模式下有 8 个 SSE 寄存器,在 64 位模式下有 16 个,为什么简单地使用 SSE 暂存寄存器?我不知道是否有任何 x86-64 处理器在其 SIMD 单元中使用寄存器重命名等(以消除错误的依赖关系)。

您已经排除了使用 xorps(或 _mm_xor_ps 内在函数)的可能性,这在现代处理器上通常是一个无用的技巧 - 当然对于通用寄存器,您已经排除了内存的使用。恐怕你所有的可能性都用尽了。总结一下:没有。

【讨论】:

只有当操作数之一是内存位置时才会发生隐式锁定。【参考方案3】:

使用PXOR指令是在XMM寄存器之间交换内容的最短、最快的方式。此代码在 xmm0 和 xmm1 之间交换内容。

  pxor  xmm0, xmm1
  pxor  xmm1, xmm0
  pxor  xmm0, xmm1

那么,哪里可以看出问题呢?

【讨论】:

以上是关于如何在 XMM 寄存器之间交换值?的主要内容,如果未能解决你的问题,请参考以下文章

如何将浮点常量值移动到xmm寄存器中?

XMM 寄存器值

如何使用 libsimdpp 复制 XMM 寄存器通道的下部

xmm 寄存器 sse x64 里面的值

如何在 xmm 寄存器中旋转压缩四字?

将单个浮点数移动到 xmm 寄存器