启用 AVX2 的处理器上的非法指令 vgatherdps

Posted

技术标签:

【中文标题】启用 AVX2 的处理器上的非法指令 vgatherdps【英文标题】:Illegal instruction vgatherdps on AVX2 enabled processor 【发布时间】:2016-09-19 10:48:47 【问题描述】:

我正在为 AVX2 指令开发代码生成器,并尝试在 AMD A10 8700 处理器上对其进行测试,根据规格,该处理器应该运行 AVX2。

但是,它会因 vgatherdps 指令中的非法指令而崩溃:

vmovdqu     yMM0,  [ r9+  PmainBase +  -256]; LDdqyy;0
lea         r9,    [      PmainBase +  -192];0
vpcmpeqw    ymm8, ymm8, ymm8;0
vgatherdps  YMM0,  [ r9+ yMM0*4 ] ,ymm8;0

cpuid 信息表明包含 avx2,因此 VGATHERDPS 应该是合法的。

有什么线索吗?

【问题讨论】:

它确实执行了一些 AVX2 指令,所以它被启用了。该集合的机器代码是什么? 为什么每行末尾都有;0 cmets?以及像yMM0 这样的大小写不一致?从格式/可读性的角度来看,基本上你的代码是一团糟。 (不过,与它的组装方式无关)。 【参考方案1】:

根据Intel's Instruction Reference:

如果任何一对索引、掩码或目标寄存器相同, 此指令导致 UD 错误。

您的目标寄存器和索引寄存器是相同的 (ymm0)。因此该指令是非法的。我很惊讶组装商没有拒绝它。所以我认为这是汇编程序中的一个错误。


这个限制背后的原因是收集指令实际上是写入两个寄存器。

    它将收集的结果写入目的地。 它将一个零掩码写回掩码寄存器,指示哪些通道成功。

在正常执行下,掩码寄存器将被零完全覆盖。但是如果发生故障,并不是所有的加载都会成功。所以指令可能只被部分执行。覆盖掩码寄存器的目的是告诉信号处理程序哪些通道成功,哪些通道失败。

索引寄存器不能与目标寄存器或掩码寄存器混为一谈,因为它会被覆盖,从而无法在从信号处理程序返回时恢复指令。

【讨论】:

OP 正在编写代码生成器,因此他可能没有通过汇编程序运行他的代码。此外,idx reg 不能匹配 dstmsk reg 有一个很好的理由。看vgatherdpsVEX.256的伪代码:首先msk寄存器中每个lane的MSB被splatted到lane的所有位,然后对于那些启用的通道,硬件会尝试加载数据并在成功时清除该通道中的掩码。因为msk 被无条件地完全覆盖,所以它不能为dstidx 加上别名,否则会发生写冲突。 无论哪种方式,您都无法解决此写入冲突:丢失msk,您无法判断哪个通道失败,丢失idx,您无法重试,丢失dst 和那么该指令的意义何在?即使msk 部分更新为dst 值,由于带内通信问题,您也会有歧义;可以想象,你成功读取了0xFFFFFFFF,但是如果这个值在掩码寄存器之内,你怎么判断0xFFFFFFFF是读取成功,还是失败呢?此外,idx 不能别名 msk,因为负索引是合法的。 最后,idx 不能为msk 别名,因为在vgather* 指令系列中,idx 可以是qword 或dword,而mskdst 通道大小总是匹配,如果dst 是双字而idx 是双字,那么只有寄存器的下半部分被填充,而上半部分为零。 “混乱”是因为它来自一个代码生成器,该代码生成器在案例和每条指令后面的一些 cmets 中对调试信息进行编码。代码适用于不反对语法的 Nasm。 ymm8 是掩码,出于显而易见的原因,它与 dest 不同。我没有意识到在 AVX2 上的 index 和 dest 不能重叠,而在改编代码生成器的 MIC 上似乎并非如此。 @IwillnotexistIdonotexist 哦。最初,我认为掩码只是有条件地归零。我的解释是成功的车道归零,失败的车道保持不变。如果索引与掩码混叠,则失败的通道不受影响。成功的车道归零。您将无法判断归零车道是成功还是从零开始,但在任何一种情况下都是无操作的。但你是对的,我没有考虑索引寄存器大小不同的情况。我将编辑修复后一段。【参考方案2】:

修复了机器描述,以便在收集指令和获取中使用不相交的寄存器集作为索引和目标

vmovdqu   yMM4,  [   PmainBase +          -256]; LDdqyy;0
lea r8,[   PmainBase +          -192];0
vpcmpeqw ymm8, ymm8, ymm8;0
vgatherdps  YMM0,[r8+ yMM4*4 ] ,ymm8;0

现在可以正常使用了。

【讨论】:

以上是关于启用 AVX2 的处理器上的非法指令 vgatherdps的主要内容,如果未能解决你的问题,请参考以下文章

使用 Intel Core i7 的 AVX 上的非法指令

在啥情况下,AVX2 收集指令会比单独加载数据更快?

MSVC /arch:[指令集] - SSE3、AVX、AVX2

Mac OS Sierra 上的 Apache:非法指令:4 $HTTPD

如何计算avx和avx2指令集的数量

如何使用 Ubuntu 20.04 64 位在 VirtualBox 6.1.16 中启用 AVX / AVX2?