【问题标题】:Mixing SSE with AVX128 for shorter instructions?将 SSE 与 AVX128 混合使用以获得更短的指令?
【发布时间】:2020-09-26 02:36:21
【问题描述】:

根据我收集到的所有信息,混合 SSE 和 128 位 (E)VEX 编码指令不会降低性能。这表明将两者混合应该没问题。当 SSE 指令通常比 VEX 指令短 1 个字节时,这可能很有用。

但是,我从未见过任何人或任何编译器这样做。例如,在 Intel 的 AVX(128 位)MD5 实现中,various vmovdqa 可以替换为 movaps(或者 this vshufps 可以替换为较短的 shufps,因为 dest 和 src1 寄存器相同) .
避免 SSE 有什么特别的原因,还是我遗漏了什么?

【问题讨论】:

    标签: assembly x86 sse avx micro-optimization


    【解决方案1】:

    你说得对,如果从 vzeroupper 中得知 YMM 上限为零,混合 AVX128 和 SSE 不会有任何损失,如果不这样做会节省代码大小,这是一种错过的优化。

    另请注意,如果您不需要 REX 前缀,它只会节省代码大小。 2 字节 VEX 相当于 SSE1 的 REX + 0F。编译器确实尝试偏爱低寄存器以希望避免 REX 前缀,但我认为他们不会查看每条指令中使用哪些寄存器组合来最小化总 REX 前缀。 (或者如果他们确实尝试这样做,他们并不擅长)。人类可以花时间进行这样的计划。

    大部分时间它都很小,只是偶尔的一个字节的代码大小。这通常是一件好事,可以帮助前端。 (或者在 Intel CPU 上为 blendvps xmm, xmm, <XMM0> 保存一个微指令而不是 pblendvps xmm, xmm, xmm, xmm(pd 和 pblendvb 相同),如果您可以安排使用它而不需要另一个 movaps

    如果你弄错了,缺点是 SSE/AVX 转换惩罚(在 Haswell 和 Ice Lake 上),或者对 Skylake 的错误依赖。 Why is this SSE code 6 times slower without VZEROUPPER on Skylake?。如果 Zen2 做了类似的事情,IDK; Zen1 将 256 位操作拆分为 2 个微指令,不关心 vzeroupper。


    为了让编译器安全地执行此操作,他们必须跟踪更多内容,以确保在 YMM 寄存器的上半部分脏了时不会在函数内运行 SSE 指令。编译器无法将 AVX 代码生成限制为仅 128 位指令,因此他们必须开始跟踪可能会弄脏 YMM 上半部分的执行路径。

    但是,我认为他们无论如何都必须在整个函数的基础上这样做,才能知道何时在 ret 之前使用 vzeroupper(在不接受或按值返回 __m256/i/d 的函数中,这将表示调用者已经在使用宽向量)。

    但不需要vzerouppermovaps 是否性能安全是另一回事,因此以类似方式跟踪将是另一回事。找出所有可以安全避免 VEX 前缀的情况。

    不过,在某些情况下可能很容易证明它是安全的。如果编译器使用保守的算法,在分支可能有或可能没有脏的上层时有一些优化丢失,那就没问题了,在这种情况下总是使用 VEX,总是使用vzeroupper

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-29
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-07
      • 2019-03-11
      • 1970-01-01
      相关资源
      最近更新 更多