Optimization 无分支避免被零除

Optimization 无分支避免被零除,optimization,assembly,Optimization,Assembly,假设我有一段代码 double test(double value, double denom) { return (denom == 0 ? 0 : value/denom); } 它被编译为: movapd %xmm0, %xmm2 xorpd %xmm0, %xmm0 ucomisd %xmm0, %xmm1 jnp .L8 .L5: movapd %xmm2, %xmm0 divsd %xmm1, %xmm0 re

假设我有一段代码

double test(double value, double denom) {
  return (denom == 0 ? 0 : value/denom);
}
它被编译为:

    movapd  %xmm0, %xmm2
    xorpd   %xmm0, %xmm0
    ucomisd %xmm0, %xmm1
    jnp .L8
.L5:
    movapd  %xmm2, %xmm0
    divsd   %xmm1, %xmm0
    ret
    .p2align 4,,10
    .p2align 3
.L8:
    jne .L5
    rep
    ret
是否有一些巧妙的方法来避免分支?所讨论的Arch是X86-64。
例如,PPC有select指令,X86-64 ISA中是否有等效指令?

分支预测机制目前相当不错

除非你有一些非零频率的零因子,否则分支预测器会发现jnp在统计上不会分支,只是在没有任何性能损失的情况下通过


您是否测量过这一点,并且看到了由于忽略测试而导致的性能损失?

假设您关闭了异常,那么掩盖结果很简单:

xorpd %xmm2, %xmm2
cmpneqsd %xmm1, %xmm2
divsd %xmm1, %xmm0
andpd %xmm2, %xmm0
ret

不适用于
xmm
寄存器。如果您有一台机器,您可以使用通常的掩蔽技巧,或者可能使用
blendvps
,但我的感觉是,您最好使用分支。在x86中,条件移动仅适用于整数寄存器作为备用,您甚至应该进行此测试吗?返回零作为零除数的结果是非常容易误导的。@500 InternalServerError这是当前的逻辑,我只是在研究优化。是的,不幸的是,零和非零的Denom有相当好的混合,并且分支似乎需要一些时间。如果您在没有一堆零除数的情况下尝试,会发生什么?如果您得到一个真正的混合,然后分支预测器可能会失败,您需要某种类型的谓词移动,或者干脆禁用浮动陷阱。