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

时间:2019-07-05 14:08:17

标签: assembly x86 x86-64 sse simd

我想将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可能会有所帮助,但是我的问题有更好的解决方案吗?

1 个答案:

答案 0 :(得分:5)

查看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,并按类型提供了方便的数据移动指令表。非常适合学习如何在高度非正交的SSE / AVX扩展中使用随机播放。


正如人们所指出的那样,标准方法是2x unpcklps将对合并为[00ba] [00dc]的向量,其中0是无关值或如果标量浮点数的高位元素恰好为零,则实际上为0.0。 (我的符号法遵循英特尔惯例,即在 left 中具有较高的元素,因此,左移会将数据以符号的形式向左移动,并以不同的元素宽度查看数据不会改变怎么写的。)

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

如果这不是很明显并且不为您所熟知,则应该使用具有内在函数的C语言编写代码,并查看经过优化的编译器输出以了解基本方法。 clang有一个很好的随机优化器,可以找到更好的方法将内部函数的逻辑实现为asm。


可能有更好的方法:

这3条指令都是随机的,在Intel Sandybridge系列处理器上,每个时钟吞吐量的CPU限制为1个(与端口5竞争)。

如果我们为blendps提供了SSE4.1(具有直接的混合控件),则我们可以将其用作最后一步,而不是随机播放。它可以在任何端口上运行。

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

如果您的输入向量实际上是零扩展且绝对没有高垃圾,则可以使用SSE1 orps而不是混合来获取[dcba]