FP 比较像 SSE2 _mm_cmpeq_pd 可以用来比较 64 位整数吗?

Can FP compares like SSE2 _mm_cmpeq_pd be used to compare 64 bit integers?

FP 可以像 SSE2 _mm_cmpeq_pd / AVX _mm_cmp_pd 那样比较 64 位整数吗?

这个想法是模拟类似于 _mm_cmpeq_epi8_mm_cmpeq_epi16_mm_cmpeq_epi32.

的缺失 _mm_cmpeq_epi64

问题是我不确定比较是按位比较还是专门处理浮点数,比如 NAN 值总是不相等。

AVX 意味着 SSE4.1 pcmpeqq 可用,在这种情况下你应该只使用 _mm_cmpeq_epi64.

FP比较对待NaN != NaN,而-0.0 == +0.0,如果MXCSR中设置了DAZ,则将任何小整数视为零。 (因为指数 = 0 意味着它代表非正规,并且非正规零模式将它们视为输入中的零,以避免对任何微体系结构上的任何操作(包括比较)可能的速度惩罚。IIRC,现代微体系结构没有用于比较的次正规输入的惩罚,但仍然用于一些其他操作。在任何情况下,使用 -ffast-math 构建的程序在启动时为主线程设置 FTZ 和 DAZ。)

所以 FP 比较对于整数来说并不是真正有用的,除非你知道 bits [62:52] (inclusive) 的一些但不是全部都会被设置。


使用 pcmpeqd (_mm_cmpeq_epi32) 比破解一些 FP 位操作要重要得多。 (虽然 @chtz 在评论中建议你可以用 xorpd42.0 == (42.0 ^ (a^b)),只要编译器不优化常量并与 0.0 进行比较。这是一个没有 -ffast-math 的 GCC 错误)。

如果您想要至少一个匹配这样的条件,那么您需要确保 64 位元素的两半都匹配,例如 movmskps 结果上的 mask & (mask<<1),这可以编译为 lea / test。 (您可以 mask & (mask<<4) 得到 pmovmskb 结果,但这效率稍低,因为 LEA 复制和移位只能移动 0..3。)

当然,“全匹配”不关心元素大小,因此您可以在任何比较结果上使用 _mm_movemask_epi8,并对照 0xFFFF.

进行检查

如果您想将它用于与 and/andnot/or 的混合,您可以 pshufd / pand 在 64 位元素中交换两半。 (如果您提供的是 pblendvbblendvpd,那就意味着 SSE4.1 可用,因此您应该使用 pcmpeqq。)

要模拟的更昂贵的是 SSE4.2 pcmpgtq,尽管我认为 GCC and/or clang 确实知道如何在自动矢量化时模拟它。