Assembly 在配备Neon的ARMv7a上,支持64位带符号比较的CMGT最有效的方法是什么?

Assembly 在配备Neon的ARMv7a上,支持64位带符号比较的CMGT最有效的方法是什么?,assembly,arm,simd,webassembly,neon,Assembly,Arm,Simd,Webassembly,Neon,这一问题最初是为公众提出的。由于每个算法都与ARMv7a+NEON对相同操作的支持重叠,因此问题被更新为包括ARMv7+NEON版本。应评论员的要求,这里提出这个问题是为了表明这确实是一个单独的主题,并提供可能更适合ARMv7+NEON的替代解决方案。这些问题的最终目的是找到理想的实现方法,以便考虑WebAssembly SIMD。从最初的帖子中,在ARMv7+NEON上实现的最佳x64/SSE2算法如下所示: (a[32:63]==b[32:63])和(b[0:63]-a[0:63])对于前3

这一问题最初是为公众提出的。由于每个算法都与ARMv7a+NEON对相同操作的支持重叠,因此问题被更新为包括ARMv7+NEON版本。应评论员的要求,这里提出这个问题是为了表明这确实是一个单独的主题,并提供可能更适合ARMv7+NEON的替代解决方案。这些问题的最终目的是找到理想的实现方法,以便考虑WebAssembly SIMD。

从最初的帖子中,在ARMv7+NEON上实现的最佳x64/SSE2算法如下所示:

(a[32:63]==b[32:63])和(b[0:63]-a[0:63])
对于前32位相等和
a[0:31]>b[0:31]
的每种情况,生成一个
0xffffff……
掩码。在所有其他情况下,例如当前32位不相等或
a[0:31]
时,它返回
0x0
。如果前32位不重要,而下32位重要,则这具有将每个整数的下32位作为掩码传播到上32位的效果。对于其余的情况,它将对前32位进行比较,并将它们合并在一起。例如,如果a[32:63]>b[32:63],那么无论最低有效位是什么,a都肯定大于b。最后,它将每个64位掩码的上32位旋转/洗牌/转置到下32位,以生成完整的64位掩码


这是一个示例性实现。

有符号64位饱和减法

假设我使用
\u mm\u subs\u epi16
进行的测试是正确的,并转换为1:1到

这显然是模拟
pcmpgtq
的最快方法


自由章 给出以下公式:

// return (a > b) ? -1LL : 0LL; 
int64_t cmpgt(int64_t a, int64_t b) {
    return ((b & ~a) | ((b - a) & ~(b ^ a))) >> 63; 
}

int64_t cmpgt(int64_t a, int64_t b) {
    return ((b - a) ^ ((b ^ a) & ((b - a) ^ b))) >> 63;
}

考虑用<代码> VSR.S64 < /代码>替换<代码> VTrn 32代码>代码。<代码> VBSL < /代码>的费用是什么,是否应该替换<代码> {和/或} /代码>?我不确定。我似乎无法让llvm mca与ARMv7一起正常工作。关于Webassembly的问题是,这些解决方案中的任何一个是否比规模化更有效。你有办法找到答案吗?x64似乎没有64位的饱和减法运算,也没有便携式psraq。然而,有没有这样的解决方案比最好的sse2解决方案更快或更可行?@DanWeber,对于sse2,我唯一能想到的就是滥用浮点指令<代码>\u mm\u cmpge\u pd()
等。NEONv7签名支持的官方提案中引用了该答案。
// return (a > b) ? -1LL : 0LL; 
int64_t cmpgt(int64_t a, int64_t b) {
    return ((b & ~a) | ((b - a) & ~(b ^ a))) >> 63; 
}

int64_t cmpgt(int64_t a, int64_t b) {
    return ((b - a) ^ ((b ^ a) & ((b - a) ^ b))) >> 63;
}