【发布时间】:2018-07-21 06:48:31
【问题描述】:
是否有根据状态寄存器状态清除 32 位寄存器的无分支方式?可以使用额外的清除寄存器和CMOVcc 来实现,但对我来说,在 32 位模式下的 x86 上太贵了。可悲的是CMOVcc 没有立即操作数的版本。从内存中读取也是不好的变体。
x86 上有 SETcc(虽然,操作数是 1 个字节)但没有“CLEARcc”指令。
【问题讨论】:
-
贵怎么办?因为注册压力? cmov 本身在 32 位模式下并不慢。 (agner.org/optimize)。在 Aki 的 SBB/AND 答案中查看我的 cmets:如果您可以节省一个寄存器,则在标志设置之前对寄存器进行异或归零比 SBB/AND 便宜。
-
昂贵,因为 GCC 说“asm 操作数有不可能的约束”,因为缺少一次性寄存器。
-
@PeterCordes 你的 cmets 还在为 Sandy Bridge 拱门有效吗?
-
等等什么?您正在使用 inline asm?这是一个巨大的 inline-asm 块的一部分吗?也许编写一个完整的函数,以便您可以根据需要溢出/重新加载。或者如果这只是一个小sn-p,那么gcc.gnu.org/wiki/DontUseInlineAsm: 使用C
? :三元来鼓励gcc 去无分支。是的,xor-zeroing is fantastically cheap on Sandybridge,与 NOP 一样高效:前端(融合域)只需 1 uop,未融合域中不需要执行单元。 -
顺便说一句,您可以在全局范围内的 GNU C“基本”asm 语句中编写整个函数。例如在任何函数之外:
asm(".globl func\n\t""func:\n\t"...);然后您可以完全控制寄存器分配,并且可以使用堆栈(这在函数内部的 x86-64 内联 asm 中是不安全的:stackoverflow.com/questions/34520013/…。
标签: assembly x86 flags branch-prediction status-register