Assembly 有条件清除寄存器的无分支方法

Assembly 有条件清除寄存器的无分支方法,assembly,x86,flags,branch-prediction,status-register,Assembly,X86,Flags,Branch Prediction,Status Register,是否有无分支的方式根据状态寄存器状态清除32位寄存器?它可以通过使用额外的清除寄存器和CMOVcc来实现,但在32位模式下的x86上对我来说太贵了。遗憾的是,CMOVcc没有带immideate操作数的版本。从内存中读取也是一个糟糕的变体 x86上有SETcc(虽然操作数是1字节),但没有“CLEARcc”指令。这可能会让您失望,但在这方面非常好。将它与值为0的变量ddZERO一起使用并不坏,尤其是在循环中 CMOVcc rTarget, ddZERO 如果满足cc条件,则将rTarget寄存

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


x86上有
SETcc
(虽然操作数是1字节),但没有“
CLEARcc
”指令。

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

CMOVcc rTarget, ddZERO
如果满足
cc
条件,则将
rTarget
寄存器重置为零。
否则(存在另一种情况),您可以在不匹配的条件下反转场景和
CMOVcc
。哪种选择更好取决于发生的频率


如果您有一个值为
0
的寄存器,则应改用该寄存器。但是,如果您不能使用(缓存的)内存位置来备用寄存器,那也没那么糟糕。此估计基于经验,在一级缓存内存位置使用常数的IIRC在循环中的延迟几乎可以忽略。

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

CMOVcc rTarget, ddZERO
如果满足
cc
条件,则将
rTarget
寄存器重置为零。
否则(存在另一种情况),您可以在不匹配的条件下反转场景和
CMOVcc
。哪种选择更好取决于发生的频率


如果您有一个值为
0
的寄存器,则应改用该寄存器。但是,如果您不能使用(缓存的)内存位置来备用寄存器,那也没那么糟糕。此估计基于经验,在一级缓存内存位置使用常数的IIRC在循环中的延迟几乎可以忽略。

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

CMOVcc rTarget, ddZERO

可以通过切换遮罩或反转进位标志来反转条件。零测试可以通过从被测寄存器中减去一或从零减去被测寄存器来实现。第一组携带iff寄存器为零;第二种形式的sets进位iff寄存器是非零的。

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


可以通过切换遮罩或反转进位标志来反转条件。零测试可以通过从被测寄存器中减去一或从零减去被测寄存器来实现。第一组携带iff寄存器为零;第二种形式的集合携带iff寄存器是非零的。

如果
xor
-zero/
cmov
太贵,
sbb
/
几乎没有更好的效果
sbb
在Intel pre broadwell(与cmov相同)上是2个UOP,对寄存器的旧值有错误依赖,但在AMD推土机系列(和Ryzen?)上除外,
sbb same,same
被识别为仅依赖于CF。此外,sbb/从标志到结果有3个周期的总延迟,因为和在关键路径上。唯一的优点是,在设置CF的指令之后才需要额外的寄存器。xor/cmov需要在标志设置指令之前进行xor调零。如果要反转掩码,可以使用
xor eax,eax
/set flags/
setc al
/
dec eax
。尽管额外的xor归零也很糟糕。取决于您所针对的uarch,但如果您想逆转这种情况,这将进一步有利于
cmov
,而不是创建掩码并使用
。(使用BMI2,您可以使用
和n
而不是
一步反转+和,因此这在Ryzen/挖掘机上非常好,在Broadwell/Skylake上可能也不错)如果
xor
-zero/
cmov
太贵,
sbb
/
几乎没有更好的效果
sbb
在Intel pre broadwell(与cmov相同)上是2个UOP,对寄存器的旧值有错误依赖,但在AMD推土机系列(和Ryzen?)上除外,
sbb same,same
被识别为仅依赖于CF。此外,sbb/从标志到结果有3个周期的总延迟,因为和在关键路径上。唯一的优点是,在设置CF的指令之后才需要额外的寄存器。xor/cmov需要在标志设置指令之前进行xor调零。如果要反转掩码,可以使用
xor eax,eax
/set flags/
setc al
/
dec eax
。尽管额外的xor归零也很糟糕。取决于您所针对的uarch,但如果您想逆转这种情况,这将进一步有利于
cmov
,而不是创建掩码并使用
。(使用BMI2,您可以使用
和n
而不是
来反转+和一步到位,所以在Ryzen/挖掘机上效果很好,在Broadwell/Skylake上可能也不错)价格如何?因为注册压力?cmov本身在32位模式下并不慢。(). 请参阅我对Aki的SBB/的评论,并回答:xor归零一个regis