在同一个代码路径中混合使用旧版SSE编码指令和VEX编码指令是否可行?

12

在引入AVX的同时,英特尔将VEX编码方案引入了Intel 64和IA-32架构。该编码方案主要与AVX指令一起使用。我想知道是否可以混用VEX编码指令和现在所称的“传统SSE”指令。

我提出这个问题的主要原因是代码大小。考虑以下两个指令:

shufps xmm0, xmm0, 0
vshufps xmm0, xmm0, xmm0, 0

通常我使用第一个指令将标量值"广播"到XMM寄存器中的所有位置。现在,指令集表明这两个指令(在这种情况下)的唯一区别是使用VEX编码的指令会清除YMM寄存器的高位(>= 128)。假设我不需要那个高位,那么在这种情况下使用VEX编码的版本有什么优势?第一个指令占用4个字节(0FC6C000),第二个指令占用5个字节(C5F8C6C000)。

提前感谢所有的答案。


任何 YMM 寄存器的上半部分都被使用了吗? - harold
不,它不会。它们可以被清零或随机化或任何其他方式处理,我不在乎。 - Daniel Kamil Kozar
3
那就好了。在当前的实现中,如果上半部分已经被重置(VZEROUPPER),使用传统的SSE指令不会有任何惩罚。 - harold
@harold 这应该是一个答案。谢谢! - Daniel Kamil Kozar
是的,我想我会添加一些信息并将其转换为答案。 - harold
2个回答

12
在当前实现中,如果(至少)上半部分已被重置(VZEROUPPER或VZEROALL),则使用传统SSE指令不会受到惩罚。
Agner Fog:汇编优化子例程第128页所述,在使用一些上半部分时使用传统SSE指令会带来性能损失。这种惩罚在进入YMM寄存器在中间分裂的状态时发生一次,再次离开该状态时再次发生。
混合VEX编码的128位指令和传统SSE指令不是问题。

1
参见 为什么在 Skylake 上没有使用 VZEROUPPER 会使 SSE 代码慢6倍?,对比 Haswell 和 Ice Lake 机制,在使用传统 SSE 指令时,具有脏状态上限的不同惩罚,只有在转换时才有。 - Peter Cordes
1
根据英特尔的说法,在Golden Cove CPU(Alder Lake-P,Raptor Lake-P,Sapphire Rapids)中,与以前的CPU相比,这种惩罚已经增加。“为了提高功率效率,Golden Cove CPU微架构增加了混合Legacy SSE和VEX而不清除上部寄存器状态的成本。尽可能使用VEX编码指令来执行所有SIMD指令。” 第3.11.5节 英特尔软件优化手册。 - Vladislav Kogan

-1

这不安全。根据Intel软件开发手册VEX.128版本会将YMM寄存器的上半部分清零,而传统的SSE版本则不会。最糟糕的是:一些汇编器(如gas)在创建目标文件时可能会将SHUFPS转换为VSHUFPS(当应用-mavx标志时)。我在处理一个汇编文件时遇到了完全相同的问题。


1
gcc -mavx -c foo.s 仍按照编写的指令进行汇编。GAS 选项 -msse2avxas(1) man page)可以实现此功能,但除非您使用 -Wa,-msse2avx,否则它不是 gcc 选项。在我的系统上,GCC 不会传递该选项,并且默认情况下也不会启用它。我会很惊讶如果有任何发行版在您没有明确使用它时就将其传递给 GCC,但我认为这是可能的。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接