vzeroall指令是否会将寄存器ymm16到ymm31清零?

10

vzeroall的文档似乎存在不一致性。散文描述如下:

该指令将所有XMM或YMM寄存器内容都清零。

然而,在此之下的伪代码表明,只有在64位模式下,寄存器ymm0ymm15会受到影响:

IF (64-bit mode)
    limit ←15
ELSE
    limit ← 7
FOR i in 0 .. limit:
    simd_reg_file[i][MAXVL-1:0] ← 0
在支持 AVX-512 的机器上,清除直到 ymm15 的内容并不等同于清除所有内容,因为存在 ymm16ymm31
这段文字描述了在使用 AVX-512 技术的机器上进行数据清除的情况,同时提醒读者在清除数据时需要注意所有相关的数据寄存器。最后一个问题询问原文中的表述是否准确。

5
据谷歌称,伪代码是正确的,只有0-15受到影响。Bochs实现也表示:“即使存在AVX-512,也仅清除16个寄存器”。 - Jester
1
@Jester,AMD手册也是这么说的。可能与支持AVX512的处理器不再需要为了性能原因清零寄存器的上半部分有关。在Broadwell之后,vzeroupper不再需要(包括所有AVX512处理器)。我认为他们决定不修改vzeroall和vzeroupper的行为,因为这些指令在这些处理器上不再需要使用,所以它们主要是出于遗留原因。 - Michael Petch
1
@MichaelPetch:在Skylake上,有时仍然需要使用vzeroupper;不使用它会使SSE指令变慢(假依赖):为什么没有VZEROUPPER的SSE代码在Skylake上比有的慢6倍?。但是,污染ymm/zmm16..31不能引起这个问题,因为它们对于传统的SSE是不可访问的。(我认为它们也不参与保存的上限状态转换,这显然是Ice Lake重新引入的)。此外,SKX对于一个脏zmm具有涡轮效应:动态确定流氓AVX-512指令执行的位置 - Peter Cordes
2
在新的CPU上不使用vzeroupper指令的影响可能会更加严重,这是因为合并uops和隐式扩展的影响(这就是Peter链接中提到的东西)。 - BeeOnRope
1
“高”16-31和“低”0-15寄存器之间的区别似乎是这样的:只有低寄存器才会发生脏数据:如果您只写入上部寄存器,则不会将CPU放入脏状态,因此不会发生脏上部状态。但是,一旦进入脏状态,所有寄存器都会受到影响,包括上部寄存器。这与我的原始理论有点不一致。我的原始理论是,隐式扩展不是(仅仅是)合并效应,因为它发生在不执行任何合并操作的VEX编码AVX指令中。 - BeeOnRope
显示剩余5条评论
1个回答

8
似乎是一个描述问题,如果您查看最新的SDM,您将看到描述已经最近更改,并且现在表示VZEROALL不会更改YMM16 ... YMM31。
请参见以下链接:最新的SDM 同时如下图所示:Intel latest SDM (Oct 2019)

谢谢!我确实检查了我的SDM副本,通常我会保持最新状态,但在这种情况下不够及时。 - BeeOnRope
1
我进行了一些谷歌搜索,根据您的问题,我认为我找到了LLVM中的一个错误,他们在实现VZEROALL时将其用于清零所有YMM寄存器,包括YMM16..、YMM31。
  • http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20170130/426045.html
- Matt. Stroh
1
@Matt.Stroh:那个错误的更改要么从未被采纳,要么已经被撤销。当前的clang9.0将使用ymm16来保存__m256_mm256_zeroall()周围:https://godbolt.org/z/HK7_Xy。只有当它知道zeroall不会触及ymm16时,这才有意义。clang3.9.1确实会溢出到内存,因此可能在该版本中进行了更改,或者可能只是没有进行高效的优化。嗯,clang(3.9和当前版本)不知道`__m128`可以在`_mm256_zeroupper()`之间保留在xmm0中。https://godbolt.org/z/DwMyMV - Peter Cordes

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