在 x86 ASM 中测试零通常哪个更快:"TEST EAX, EAX" 与"TEST AL, AL"?



通常更快地测试Al中的字节的零/非零?

  • TEST EAX, EAX
  • TEST AL, AL

假设以前的"MOVZX EAX, BYTE PTR [ESP+4]"指令加载了一个字节参数,其剩余的EAX的剩余时间为零,从而阻止了我已经知道的组合额罚款。

so al = eax,并且没有部分注册罚款。

直观地检查Al可能会让您认为它的速度更快,但是我敢打赌,对于字节访问> 32位寄存器还有更多的惩罚问题。

感谢任何信息/详细信息,谢谢!

代码大小相等,所有x86 cpus afaik的性能也是如此。

Intel CPU(带有部分注册的重命名(在撰写EAX后肯定没有阅读Al的罚款。其他CPU也没有阅读低字节登记册。

阅读ah将对英特尔CPU受到惩罚,就像一些额外的延迟一样。(在Haswell/Skylake上的部分寄存器表现如何?写作似乎对RAX有错误的依赖,而AH不一致(

一般而言32位操作数大小和8位操作数尺寸(低8个不是高8个(是相等的速度,除了写作 8位寄存器。由于测试仅读取寄存器,因此这不是问题。即使是add al, bl也很好:该指令已经对两个寄存器都有输入依赖性,并且在sandybridge-family a rmw to remw to of寄存器的低字节上并不能单独重命名。(Haswell和后来不要单独重命名低字节寄存器(。

选择您喜欢的操作数尺寸。8位和32位基本上相等。选择只是人类可读性的问题。如果您要在32位整数之后使用该值,请进行32位。如果在逻辑上仍然是8位值,并且您仅将movzx用作X86等于ARM ldrb或MIPS lbu,则使用8位是有意义的。

cmp al, imm等指令有代码尺寸的优势,可以使用NO-MODRM短形式编码。cmp al, 0仍然比上的旧CPU(CORE 2(上的test al,al差,其中CMP/JCC宏融合不如Test/JCC宏融合灵活。(测试CMP Reg,0 vs或reg,reg,Reg?(

的寄存器是否为零。(

这些说明之间存在一个区别:test al,al SF 根据Al的高位(可以是非零(。test eax,eax将始终清除SF。如果您只关心ZF,那就没有区别了,但是如果您在SF中使用高点用于以后的分支或CMOVCC/SETCC,则可以避免执行第二个test


在内存中测试字节的其他方法:

如果您使用setcc或cmovcc而不是JCC分支来消费标志结果,则宏融合在下面的讨论中无关紧要。

如果您稍后还需要寄存器中的实际值,则movzx/test/jcc几乎可以肯定是最好的。否则,您可以考虑与内存预测相比。

cmp [mem], immediate只要地址模式不是rip - 相关性,就可以将微熔点微型融合到英特尔上的负载 cmp uop中。(在Sandybridge家庭中,即使在Haswell和更高版本上,索引的地址模式也会不限制:请参阅微型融合和寻址模式(。Agner Fog没有提及AMD是否具有将CMP/JCC与内存操作数融合的限制。

;;; no downside for setcc or cmovcc, only with JCC on Intel
;;; unknown on AMD
    cmp byte [esp+4], 0       ; micro-fuses into load+cmp with this addressing mode
    jnz   ...                 ; breaks macro-fusion on SnB-family

我没有AMD CPU来测试当CMP为mem, immediate时,Ryzen还是任何其他AMD仍然融合CMP/JCC。一般而言,现代AMD cpus do 一般而言do cmp/jcc和test/jcc融合。(但不添加/sub/and/jcc融合,例如snb-family(。

cmp mem,imm/jcc (vs. movzx/test+jcc(:

  • 字节中的较小的代码尺寸
  • 主流英特尔上相同数量的前端/融合域UOPS(2(。如果无法实现cmp 的微融合,例如,这将是3个前端UOPS,例如具有RIP相关的地址模式 立即。或在带有索引的地址模式的Sandybridge家庭上,它将在解码后不受3个UOPS的影响,但在发出后端之前。

    优势:这仍然是Silvermont/Goldmont/KNL或非常古老的CPU,而没有宏观融合。MOVZX/TEST/JCC比这是宏融合的主要优点,因此它落在CPU上,而这不会发生。

  • 3个后端UOP(未连接域=执行端口和调度程序中的空间(,因为cmp-IMMediate无法在Intel Sandybridge-Family-Family CPU上使用JCC宏观插件(在Skylake上测试(。UOPS是负载,CMP和单独的分支UOP。(movzx/test+jcc的2 vs. 2(。后端UOPS通常不是直接的瓶颈,但是如果负载暂时没有准备好,它占用了RS中的更多空间,从而限制了越来越远的阶段执行。

cmp [mem], reg/jcc can acro 微型福利 微型fuse中的单个比较 分支UOP,因此它是极好的。如果您需要以后的功能中的任何内容零寄存器,请先进行XOR-Zero,然后将其用于内存上的单uop比较 分支。

    movzx  eax, [esp+4]       ; 1 uop (load-port only on Intel and Ryzen)
    test   al,al                     ; fuses with jcc
    jnz    ...                ; 1 uop

这仍然是前端的2个UOP,但后端也只有2个。测试/JCC宏观融合在一起。不过,它的代码大小。

如果您不分支,而是使用cmovccsetcc的标志结果,则使用cmp mem, imm没有弊端。只要您不使用RIP相关的地址模式(当也有即时时,它总是会阻止微融合(或索引地址模式。

最新更新