如何将 4 个 32 位浮点数存储到一个 128 位 xmm 寄存器中?

How to store 4 32 bit floats into one 128 bit xmm register?

我想将 4 个 32 位浮点数存储到 xmm0 中,其中每个浮点数都存储在一个 128 位寄存器中。 例如我有 4 个花车: xmm1: 10.2 xmm2:5.8 xmm3:9.3 xmm4: 12.7(每个只使用128位寄存器的32位) 并希望它们像这样存储到 xmm0 中: 10.2、5.8、9.3、12.7 这样它们就存储在它们旁边的 xmm0.

然后我还想在对 xmm0 进行一些数学运算后分别提取它们中的每一个(例如 mulps ..)

我试过使用 movlps 和 movhps,但它们只使用内存加载,而不是 128 位寄存器作为源。由于性能原因,我不想使用任何额外的内存。

PSLLDQ 可能会有所帮助,但是否有更好的解决方案来解决我的问题?

查看 compiler output for _mm_set_ps(f3,f2,f1,f0)_mm_setr_ps(f0,f1,f2,f3),选择曲调和 -march 选项。

或者看看 Agner Fog's optimization guide:他有一个关于 SSE/AVX 的章节,其中有一个方便的 table 的 data-movement 指令类型。非常适合学习如何在高度 non-orthogonal SSE/AVX 扩展中使用哪些随机播放。


正如人们所指出的,标准方法是 2x unpcklps 将对合并到 [00ba] [00dc] 的向量中,其中 0 是一个 don't-care 值或实际上 0.0 如果你的标量浮点数的上部元素恰好为零。 (我的表示法遵循图表中的英特尔约定,即高元素位于 左侧 ,因此左移将数据移动到表示法的左侧,并查看具有不同元素宽度的数据'改变你的写作方式。)

然后movlhps将一个xmm寄存器的低位qword复制到另一个xmm寄存器的高位qword(合并到现有值)。

如果这对您来说不是显而易见的 well-known,您应该使用 C 语言编写内在函数,并查看优化的编译器输出以了解基本方法。 clang 有一个非常好的 shuffle 优化器,可以找到更好的方法将你的内在逻辑实现到 asm 中。


可能有更好的方法:

这 3 条指令都是随机播放,在 Intel Sandybridge-family CPU 上每个时钟吞吐量限制为 1 个(竞争端口 5)。

如果我们有 SSE4.1 可用于 blendps(立即 blend-control),我们可以将其用作最后一步而不是随机播放。它可以 运行 在任何端口上。

我认为我们可以使用 shufps 来创建 [0c0a][d0b0] 的向量。 shufps输出的低2个元素来自第一个source=dst操作数,另一半来自另一个source.

如果您的输入向量实际上 zero-extended 并且绝对没有高垃圾,您可以使用 SSE1 orps 而不是混合来获得 [dcba]