仅将整数SSE寄存器中的高位或低位64位快速移动到另一个寄存器,最快的方法是什么?使用SSE 4.1,可以通过单个指令(
_mm_blend_epi16
)完成。但是老版本的SSE怎么办?移位和解包?AND和OR?movsd
是否有旁路延迟?
密切相关的问题:两个__m128i的64位部分的最佳混洗方式
_mm_blend_epi16
)完成。但是老版本的SSE怎么办?移位和解包?AND和OR?movsd
是否有旁路延迟?
密切相关的问题:两个__m128i的64位部分的最佳混洗方式
将src的低64位移动到dst中,保留dst的高64位:
movsd dst, src
将src的高64位移动到dst,保留dst的低64位:
shufps dst, src, E4h
绕过延迟通常只会增加延迟,而不是分派、执行或退役资源,因此只有在比较其他方面相等的序列时才需要考虑(即如果存在一个保留在整数域中的单指令等效项,则更喜欢使用它进行整数运算)。
Agner Fog的汇编优化指南中有一组非常好的数据移动指令表(第13.3节)。
如果要将两个寄存器中的数据合并为一个,您可以选择以下选项:
MOVLHPS # SSE. Low qword unchanged, high qword from low of source
MOVHLPS # SSE. Low qword from high of source, high qword unchanged
MOVSD # SSE2. Low qword from source (register only), high qword unchanged
# memory-source-only insns:
MOVLPS/D # SSE1/2. Low qword from memory, high qword unchanged
MOVHPS/D # SSE1/2. High qword from memory, low qword unchanged
SHUFPD # SSE2. Low qword from any position of destination. high qword from any position of source
PUNPCKLQDQ # SSE2. Low qword unchanged, high qword from low of source
PUNPCKHQDQ # SSE2. Low qword from high of destination, high qword from high of source
MOVQ # SSE2. Low qword from source, high qword set to zero
PBLENDW # SSE4.1
PINSRQ # SSE4.1 (only takes the low64 of src)
以下是从Agner Fog的表格中复制粘贴的说明,版权归他所有。
因此,shufpd
看起来是从另一个寄存器插入high64的最佳选择。其他选项需要它在src的low64中(例如punpcklqdq
或movlhps
)。
MOVSD
,Intel Intrinsic Guide 表示未对齐的内存是可以的。_mm_load_sd
和 _mm_store_sd
都声明了 "mem_addr
不需要对齐到任何特定边界". 我猜编译器为内在函数的用户做了一些额外的工作。 - jww我不知道最快的方法,也许最简单的方法就是:
_mm_unpacklo_epi64(_mm_setzero_si128(), x)
[0, x0]
_mm_unpackhi_epi64(_mm_setzero_si128(), x)
[0, x1]
_mm_move_epi64(x)
[x0, 0]
_mm_unpackhi_epi64(x, _mm_setzero_si128())
[x1, 0]
movsd
最初的表现与psrldq/punpcklqdq
或pshufd/punpcklqdq
一样快,但它减少了代码大小,并允许重新排序指令以获得小幅度的性能提升。看来我过于担心旁路延迟了。 - nwellnhofsrc
移动到高位的dest
,同时保留低位的src
?我在 UBsan 中捕获到了未对齐加载错误,所以我需要找到其他替代_mm_loaddup_pd
的方法。 - jwwmovlhps
。 - Stephen Canon