assembly 将SSE与AVX128混合以缩短指令?

pw9qyyiw  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(144)

从我收集到的所有信息来看,混合SSE和128位(E)VEX编码指令并不会降低性能。这表明混合这两种指令应该是不错的。当SSE指令通常比VEX指令短1个字节时,这可能是有益的。
然而,我从未见过任何人或任何编译器这样做,举个例子,在Intel的AVX(128位)MD5实现中,各种vmovdqa可以替换为movaps(或者这个vshufps可以替换为较短的shufps,因为dest和src1寄存器是相同的)。
避免SSE有什么特殊的原因吗?或者我遗漏了什么?

polhcujo

polhcujo1#

您是对的,如果YMM上限已知为vzeroupper的零,则混合AVX 128和SSE不会有任何损失,并且在保存代码大小时不这样做是错过的优化。
还请注意,只有在不需要雷克斯前缀的情况下,它才能节省代码大小。对于SSE 1,2字节VEX等效于REX +0 F。编译器确实会尝试偏向低寄存器,希望避免REX前缀,但我认为他们不会考虑每条指令中使用了哪些寄存器组合,以最大限度地减少REX前缀总数。(或者如果他们真的尝试那样做,他们并不擅长)。人类可以花时间那样做计划。
大多数情况下,它都很小,只是偶尔的代码大小。这通常是件好事,可以帮助前端。(或者在Intel CPU上,通过AVX vblendvps xmm, xmm, xmm, xmm为SSE 4 blendvps xmm, xmm, <XMM0>节省一个uop(pd和pblendvb也是如此),如果您可以安排使用它,而不需要另一个movaps来处理XMM 0中的混合控制。请参见https://uops.info/
如果你做错了,它的缺点是SSE/AVX转换损失(Haswell和Ice Lake),或者对Skylake的错误依赖。* 为什么在Skylake上没有VZEROUPPER,这个SSE代码会慢6倍?*. IDK,如果Zen 2做了类似的事情;Zen 1将256位操作拆分为2个uop,并且不关心vzeroupper。
为了让编译器安全地执行此操作,他们必须跟踪更多的东西,以确保当YMM寄存器上半部分不干净时,不会在函数内部运行SSE指令。编译器无法将AVX代码生成限制为仅128位指令,因此他们必须开始跟踪可能污染YMM上半部分的执行路径。
然而,我认为他们必须在整个函数的基础上这样做,以知道何时在ret之前使用vzeroupper(在不按值接受或返回__m256/i/d的函数中,这意味着调用者已经在使用宽向量)。
但是不需要vzerouppermovaps是否是性能安全的是两件不同的事情,因此需要以类似的方式跟踪另一件事情,即找到避免使用VEX前缀是安全的每一种情况。
尽管如此,还是有可能很容易证明它是安全的。如果编译器使用保守算法,当分支可能会或可能不会弄脏upper时,它会错过一些优化,在这种情况下,总是使用VEX,总是使用vzeroupper

相关问题