gpt4 book ai didi

performance - 在x86 ASM中测试“零”通常更快:“测试EAX,EAX”与“测试AL,AL”?

转载 作者:行者123 更新时间:2023-12-03 00:56:13 25 4
gpt4 key购买 nike

通常,测试AL中的字节是否为零/非零更快?


TEST EAX, EAX
TEST AL, AL


假设之前的"MOVZX EAX, BYTE PTR [ESP+4]"指令将零扩展的字节参数加载到EAX的其余部分,以防止我已经知道的合并值损失。

因此,AL = EAX,读取EAX时没有部分寄存器的处罚。

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

任何信息/细节表示赞赏,谢谢!

最佳答案

代码大小相等,所有x86 CPU AFAIK的性能也相等。

英特尔CPU(具有部分寄存器重命名)在编写EAX之后读取AL肯定不会受到任何惩罚。其他CPU也没有读取低字节寄存器的代价。

读AH将对Intel CPU造成不利影响,例如额外的延迟。 (How exactly do partial registers on Haswell/Skylake perform? Writing AL seems to have a false dependency on RAX, and AH is inconsistent

通常,除了误相关性或以后写入8位寄存器的部分寄存器读取惩罚外,32位操作数大小和8位操作数大小(低8位不高8位)的速度相同。由于TEST仅读取寄存器,所以这不是问题。甚至add al, bl都很好:指令已经在两个寄存器上都具有输入依赖性,并且在Sandybridge系列上,到寄存器低字节的RMW不会单独重命名。 (Haswell和以后的版本无论如何都不会分别重命名低字节寄存器)。

选择您喜欢的任何操作数大小。 8位和32位基本相等。选择只是人类可读性的问题。如果以后要将该值作为32位整数使用,请使用32位。如果在逻辑上仍然是8位值,并且您仅将movzx用作ARM ldrb或MIPS lbu的x86等效项,则使用8位是有意义的。

诸如cmp al, imm的指令具有代码大小的优势,这些指令可以使用no-modrm短格式编码。在某些旧CPU(Core 2)上,cmp al, 0仍然比test al,al差,后者的cmp / jcc宏融合不如test / jcc宏融合灵活。 (Test whether a register is zero with CMP reg,0 vs OR reg,reg?



这些指令之间有一个区别:test al,al根据AL的高位(可以为非零)设置SF。 test eax,eax将始终清除SF。如果只关心ZF,那没有什么区别,但是如果您将SF中的高位用于以后的分支或cmovcc / setcc,则可以避免执行第二个test



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

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

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

只要寻址模式不是相对于RIP的,cmp [mem], immediate就可以微熔接到Intel的load + cmp uop中。 (在Sandybridge系列上,即使在Haswell及更高版本上,索引寻址模式也将取消分层:请参见Micro fusion and addressing modes)。 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 CPU通常会执行cmp / jcc和test / jcc融合。 (但不像SnB系列那样添加/ sub /和/ jcc融合)。

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


较小的代码大小(以字节为单位)
主流英特尔上具有相同数量的前端/融合域(2)。如果无法实现 cmp +负载的微融合,则这将是3个前端微指令。具有相对RIP的寻址模式+立即。或在具有索引寻址模式的Sandybridge系列中,它将在解码后但在发布到后端之前分层为3 oups。

优势:在Silvermont / Goldmont / KNL或没有宏融合的非常老的CPU上,这仍然是2。 movzx / test / jcc相对于此的主要优势是宏融合,因此它在不发生这种情况的CPU上落后。
3个后端uops(未融合的域=调度程序(也称为RS)中的执行端口和空间),因为 cmp -immediate不能与Intel Sandybridge系列CPU上的JCC宏融合(在Skylake上测试)。这些微指令分别是load,cmp和一个单独的分支uop。 (相对于 movzx / test+jcc的2)。后端uoop通常不是直接的瓶颈,但是如果负载一段时间没有准备好,它将占用RS中的更多空间,从而限制了这种无序执行所能看到的距离。


cmp [mem], reg / jcc可以将宏+微型保险丝组合成单个compare + branch uop,因此非常好。如果以后需要对函数进行任何操作都需要清零寄存器,请先对其进行异或归零,然后将其用于内存中的单位比较+分支。

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


前端仍然是2块,后端也只有2块。将test / jcc宏融合在一起。不过,它花费了更多的代码大小。

如果您不是分支机构,而是将FLAGS结果用于 cmovccsetcc,则使用 cmp mem, imm没有不利之处。只要您不使用相对于RIP的寻址模式(在有立即数的情况下始终会阻止微融合)或索引寻址模式,它就可以微熔。

关于performance - 在x86 ASM中测试“零”通常更快:“测试EAX,EAX”与“测试AL,AL”?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57315503/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com