有条件地清除寄存器的无分支方式

Branchless way to conditionally clear register

是否有根据状态寄存器状态清除32位寄存器的无分支方式?它可以使用额外的清除寄存器和 CMOVcc 来实现,但对我来说在 32 位模式下的 x86 上太贵了。遗憾的是 CMOVcc 没有带有即时操作数的版本。从内存中读取也是不好的变体。

x86.

上有 SETcc(尽管操作数是 1 个字节)但没有“CLEARcc”指令

这可能会让您失望,但是 CMOVcc 在这方面非常好。将它与值为 0 的变量 ddZERO 一起使用并没有那么糟糕,尤其是在循环中。

CMOVcc rTarget, ddZERO
如果满足 cc 条件,

rTarget 寄存器重置为零。
否则(有一个否则)你可以在不匹配的条件下反转场景和 CMOVcc。哪个选择更好取决于出现的频率。

如果您有一个值为 0 的寄存器,您应该改用它。但是,如果您不能使用(缓存的)内存位置来节省寄存器,那也不错。这个估计是基于经验和 IIRC 在 L1 缓存内存位置使用常量在循环中几乎可以忽略不计的延迟。

在大多数 ISA 中基本上有一种通用方法提供分支设置或清除寄存器:从进位标志生成全零或全一掩码:sbb reg,reg 当进位为零时清除掩码并设置掩码设置进位时。后跟 and dst, reg 将清除目标寄存器,或保持不变。

可以通过切换掩码或反转进位标志来反转条件。零测试可以通过从被测寄存器中减一,或者从零中减去被测寄存器来实现。第一组进位 iff 寄存器为零;第二种形式设置进位 iff 寄存器为非零。