为什么将参数反转为 CMPGT 比较函数会像 CMPLT 一样工作?

Why does inverting the parameters to a CMPGT comparison function work as a CMPLT?

我在为一个项目优化一个小型数学库的过程中使用 AVX2,但是,我偶然发现了一些小的不一致。

AVX2 不支持压缩 32b i 的 CMPLT 函数,这很不幸。创建此类操作的另一种方法是在 _mm256_cmpgt_epi32 函数中使用一种名为“属性 转置”的做法,显然。

参考:

_mm256_cmpgt_epi32(a,b)

预计 a > b 的计算将是所需的输入,但是,要实现我们不存在的 _mm256_cmplt_epi32() 函数,我们需要像这样写出原始输入的逆函数: _mm256_cmpgt_epi32(b,a).

我的问题是:为什么反转输入会将函数的操作更改为应该已经提供的操作(即 _mm256_cmplt_epi32)?

a<ba 小于 b)在数学上等同于 b>ab 大于 a)。符号向左或向右打开的视觉指示具有相同的含义,但 < 是小于运算符,而 > 是大于运算符。

要反转比较的操作数,镜像运算符。如果这不是很明显,请尝试一些小整数情况,例如 1 > 22 < 1,并使用相同的操作数,看看它是否适用于两个整数之间关系的所有 3 种可能情况(大于、等于或小于)。

整数比较没有任何 2 的补码环绕极端情况​​,这会使数学恒等式不起作用。将此与 FP cmppd xmm,xmm/mem, imm8 进行对比,因为浮点数有第 4 种可能性(无序)1.


内在函数已经可以提供ltgt整数比较(但不是gelepcmpgt 硬件指令。

不这样做的一个原因是提醒您只有右手操作数才能将负载折叠到内存源中。并且(没有 AVX)如果比较后还需要左侧,则需要复制左侧。或者只是为了减少列表中的内在函数,或者减少没有完全对应的 asm 指令的内在函数。

这些是提供更多比较 asm 指令可能有意义的原因,但无论出于何种原因,x86 直到 AVX2 之后才出现。 AVX-512 最终确实提供了比较指令,将谓词作为立即数而不是操作码的一部分(如 cmpps),从而提供了谓词的选择。 (vpcmpb/w/d/qvpcmpub/w/d/q 也最终提供了 无符号 整数比较。)


仅提供一个或两个谓词不是 x86 独有的:例如 MIPS 仅提供 slt / sltu 用于无分支标量整数比较-登记。这意味着如果需要 xori reg,reg,1 来反转 slt 结果,或者如果条件是 ==!= (How to do less than or equal in Assembly Language(MIPS)?).

在 MIPS 上,分支 总是最多一个 slt(或 sltu)和一个 bnezbeqz以你想要的方式分支,无论 slt 给你一个零还是一个。 (Greater than, less than equal, greater than equal in MIPS). Unlike RISC-V, MIPS doesn't have two-register blt by design, .

无论如何,MIPS 的 RISC 设计可能影响了 MMX 的设计者,当时 x86 的最初选择是仅提供 eq 和有符号 gt 整数比较。当时的晶体管预算小得多(Pentium-MMX 在 90 年代中期发布)。英特尔认为大多数热循环不会因为提供 <= 或无符号而加速很多,我猜,所以他们直到 AVX-512 才开始添加更灵活的整数比较。


脚注 1:
将此与 FP 比较进行对比,其中两个值之间有 4 种可能的关系,大于、等于、小于,或者 unordered 如果任一输入为 NaN。

这是 SSE did 设计 cmpps/cmppd 将谓词作为立即数的部分原因,允许更广泛的选择。但在 AVX 之前,即使是 FP 比较也仅限于前 7 个谓词,==<<=、无序、!=!<!<= 和“订购”。对于输入之间的 4 种可能关系中的每一种,The manual 对于每个谓词都有一个真实的 table 结果,并且说

The greater-than relations that the processor does not implement require more than one instruction to emulate in software and therefore should not be implemented as pseudo-ops. (For these, the programmer should reverse the operands of the corresponding less than relations and use move instructions to ensure that the mask is moved to the correct destination register and that the source operand is left intact.)

即使是FP,a > b也是b < a.[=60=完全一样的条件]

当晶体管预算较大时,SSE 的设计晚于 MMX,并且由 P6 而不是 P5 解码。 (对于非标量版本,第一代 SSE 实现为 2 微指令)。可能也不需要 1 个周期的延迟为比较腾出空间然后应用谓词。部分/所有这些原因可能是通过在立即谓词上花费额外的代码大小字节来使 FP 比较更加灵活的选择的一部分。也许还有 MMX only 具有 eqgt 比较在实践中不方便的情况。