VPCMPB 的操作数

Operands for VPCMPB

我在 Intel intrinsics guide 上看到可以不用 immediate 使用 vpcmpb 来达到相等比较的效果:https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=AVX_512&expand=6816,804,804,4867,351,804,4222,914&text=vpcmpb

我尝试编写以下汇编指令:vpcmpb %zmm30, %zmm0, %k1(g++语法),比较等于zmm30zmm0,将结果写入k1。但是,汇编程序抱怨操作数的数量错误。这是怎么回事?

执行此操作有 3 个有效的机器操作码:

在 asm source 中,assemblers 允许您使用 vpcmpleb k, zmm, zmm 作为更有意义的方式来编写 vpcmpb k, z, z, 2,如推荐的在 Intel 的第 2 卷手册中的 Table 5-17 中。即谓词作为助记符的一部分,暗示直接。

table 包含一行 VPCMPEQ* reg1, reg2, reg3 -> VPCMP* reg1, reg2, reg3, 0,但较短的非立即形式在实际 assemble 中优先于 vpcmpeqb k, zmm, zmm rs.

NASM 源与 objdump -S -drwC -Mintel 反汇编混合。 (用 gas .intel_syntax noprefix 组装的结果相同):

                                vpcmpeqb k1, zmm0, zmm1
   0:   62 f1 7d 48 74 c9       vpcmpeqb k1,zmm0,zmm1    # 74 opcode

                                vpcmpb k1, zmm0, zmm1, 0
   6:   62 f3 7d 48 3f c9 00    vpcmpeqb k1,zmm0,zmm1    # 3f opcode

                                vpcmpequb k1, zmm0, zmm1
   d:   62 f3 7d 48 3e c9 00    vpcmpequb k1,zmm0,zmm1   # 3e opcode

                                vpcmpub k1, zmm0, zmm1, 0
  14:   62 f3 7d 48 3e c9 00    vpcmpequb k1,zmm0,zmm1   # 3e opcode

有趣的是,NASM/GAS将assemble如vpcmpb k1, zmm0, zmm1, 0所写,以立即数的形式出现。但是 objdump 会将 assemble 返回到 vpcmpeqb k1,zmm0,zmm1,与非立即操作码相同,因此这是 disassemble/reassemble 往返会改变机器的情况之一代码。 (当然不是指令的架构效果)

NASM / GAS 不会为您将 vpcmpequb 优化为 vpcmpeqb,因此在比较整数相等时始终避免使用无符号版本。


内在函数指南中存在错误

如果您使用 asm 编写,请查看 asm 参考手册(HTML 摘录 https://www.felixcloutier.com/x86/vpcmpb:vpcmpub 或从中删除的英特尔原始 PDF),而不是 Intrinsics 指南。尤其是当你 运行 对某些东西所说的和 and/or CPU 似乎在做什么的工具之间存在任何神秘或分歧时!

众所周知,内在函数指南存在错误(尽管人们在 Intel 的论坛上报告这些错误后它们确实得到了修复)。特别有可能在对使用 C/C++ 内在函数的正确性不重要的部分看到错误。

Intel 的 asm 手册也不是不可能有错误,但不会像遗漏已经发布的指令集的指令的整个机器操作码形式那样严重。

如果没有明确的立即数,在真正的 asm 源代码中或作为机器代码的描述,vpcmpb k, zmm, zmm 永远不会有效,所以是的,这绝对是内在函数指南中的一个错误。


具有反向操作数列表的 vpcmpeqb %zmm, %zmm, %k asm 语法和 $immediate 是“AT&T 语法”。它恰好是 .s / .S 文件默认使用的一种 GAS,但您可以使用 .intel_syntax noprefix.

对单个指令使用内联汇编通常没有意义 - 编译器通常可以很好地处理内在函数,尽管对于 AVX-512 掩码内容可能并非总是如此。