测试 256 位 YMM AVX 寄存器为零的最有效/惯用方法

Posted

技术标签:

【中文标题】测试 256 位 YMM AVX 寄存器为零的最有效/惯用方法【英文标题】:Most efficient/idiomatic way to test a 256-bit YMM AVX register for zero 【发布时间】:2014-05-29 16:35:06 【问题描述】:

我有一个 x86_64 例程,如果成功,它最终会在 YMM 寄存器中以零结束,如果 YMM 寄存器我想返回非零值。

我有办法通过清除另一个 YMM 寄存器,针对那个寄存器对我的寄存器进行 VPTEST 测试,然后如果未设置 CF,则有条件地递增返回寄存器(在我的情况下为 RAX):

"    xor    %%rax,   %%rax              \n" // clear RAX

"    vxorpd %%ymm0,  %%ymm0,    %%ymm0  \n" // clear YMM0
"    vptest %%ymm1,  %%ymm0             \n" // compare YMM1 to zero

"    jc     endcheck                    \n" // branch over if no residue
"    inc    %%rax                       \n" // inc RAX otherwise

"endcheck:                              \n" // result is now in RAX

这似乎有点不透明。有没有更好的方法,或者更惯用或更易读的方法?

【问题讨论】:

您不需要两个 YMM 寄存器,其中一个已被清除 - 只需 vptest %%ymm1, %%ymm1 @PaulR,谢谢,这有帮助。然后我在这种情况下使用jz 来识别零。 另外你应该支持无分支代码,你可以使用SETC/SETNC甚至ADC/SBB 这里没有扩展程序集,为什么要把它放在这样的字符串中? 【参考方案1】:

结合上面的cmets,可以分三行组装完成:

"xor         %%rax,      %%rax    \n" // clear RAX
"vptest      %%ymm1,     %%ymm1   \n" // if YMM1 zero, set ZF
"setnz       %%al                 \n" // set byte in RAX if not zero

这似乎更清晰,更符合我的想法。

【讨论】:

以上是关于测试 256 位 YMM AVX 寄存器为零的最有效/惯用方法的主要内容,如果未能解决你的问题,请参考以下文章

AVX2:AVX 寄存器中 8 位元素的 CountTrailingZeros

ASM x86_64 AVX:xmm 和 ymm 寄存器差异

有效地将 YMM 寄存器的低 64 位设置为常数

AVX 指令 vxorpd 和 vpxor 之间的区别

有没有办法将 8bitX32 ymm 寄存器右/左洗牌 N 个位置(c++)

从填充为 0 的数组加载到 256 位 AVX2 寄存器