Intel x86汇编中高效将XMM寄存器低两位32位浮点数扩展为全寄存器重复值的最优方法
高效实现XMM寄存器低两位单精度浮点数的重复扩展
对于你需要将xmm1从[-, -, a, b](高两位32位无效,低两位为单精度浮点数a、b)转换为[a, a, b, b]的需求,单条shufps指令就能完成,这是最高效的实现方式——不需要额外寄存器,且在现代x86 CPU上是单周期执行的。
核心实现代码
shufps xmm1, xmm1, 0xA0 ; 将xmm1转换为[a, a, b, b]
指令细节解释
shufps指令专门用于重新排列XMM寄存器中的单精度浮点数元素,其第三个操作数是一个8位立即数,用来指定每个目标元素的源索引:
- 立即数的二进制格式为
[src3][src2][src1][src0],每个srcX是2位的索引(对应XMM寄存器的4个32位元素,索引0是最低位元素,3是最高位元素) - 在你的场景中:
- 目标最高位两个元素(索引3、2)需要取原寄存器的
a(对应原索引2) - 目标最低位两个元素(索引1、0)需要取原寄存器的
b(对应原索引0) - 所以立即数的二进制是
10100000,对应十六进制0xA0
- 目标最高位两个元素(索引3、2)需要取原寄存器的
其他备选方案(效率略低)
如果出于某些限制不能使用shufps,也可以用组合指令实现,但效率远不如单条shufps:
方案1:使用
movd+movddup(需要SSE3支持)movd eax, xmm1 ; 提取b到eax寄存器 movd xmm2, eax ; 将b加载到xmm2的低32位 movddup xmm2, xmm2 ; 复制b到xmm2的高64位,得到[b, b] psrldq xmm1, 4 ; xmm1右移4字节,此时低32位为a movd eax, xmm1 ; 提取a到eax寄存器 movd xmm3, eax ; 将a加载到xmm3的低32位 movddup xmm3, xmm3 ; 复制a到xmm3的高64位,得到[a, a] movlhps xmm1, xmm3 ; 将xmm3的低64位(a,a)复制到xmm1的高64位,最终得到[a,a,b,b]这个方案需要占用额外通用寄存器和XMM寄存器,且多条指令串行执行,性能差距明显。
方案2:使用
unpcklps+shufps的组合,但本质上还是多指令操作,没有性能优势。
注意事项
如果你的元素索引顺序和假设不同(比如a是原寄存器的索引1,b是索引0),只需要调整shufps的立即数即可:
- 若原
xmm1是[-, -, b, a](低两位是a、b),要得到[a,a,b,b],则立即数应为0x50(二进制01010000,对应索引1、1、0、0)
内容的提问来源于stack exchange,提问作者trollinator
相关产品推荐
相关产品推荐

