在内存位置上调用 "add "是否比在寄存器上调用它然后移动值要快?

问题描述 投票:0回答:2

哪个更快。

add DWORD PTR [rbp-0x4],1

还是

 mov    eax,DWORD PTR [rbp-0x4]
 add    eax,1
 mov    DWORD PTR [rbp-0x4],eax

我已经看到了编译器生成的第二段代码,所以也许调用了 add 在一个寄存器上添加DWORD PTR更快?

assembly x86 x86-64
2个回答
5
投票

它们都解码到了相同数量的后端uops,但是内存-目的地址 add 在现代的IntelAMD CPU上,通过前端以较少的融合域uops获取这些uops。

在英特尔CPU上。add [mem], imm 解码为一个微融合的load+add和一个微融合的store-address+store-data,所以前端总共有2个融合域的uops。 AMD CPU总是将内存操作数与ALU操作分组,而不称之为 "微融合",这只是他们一直以来的工作方式(https:/agner.orgoptimizeINC指令与ADD 1。这重要吗?).


第一种方式 不在寄存器中留值所以你不能把它作为一部分。++a 如果使用了该表达式的值。 只对内存的副作用。


使用 [rbp - 4] 而在内存中增量一个局部代码,听起来像是未经优化的调试模式代码,你应该 是在寻找什么是高效的。 优化后的代码通常使用 [rsp +- constant] 来寻址locals,并且(除非变量为 volatile)不会是马上又把它存储回内存中。

为什么clang用-O0产生低效的asm(对于这种简单的浮点和)? - 在调试模式下编译,也就是 -O0 (默认值)分别编译每条C语句,并将每个变量视为类似于 volatile,这是完全可怕的。

如何去除GCCclang汇编输出中的 "噪音"? 对于如何让编译器做出asm,很有意思。 编写一个函数,接受args并返回一个值,这样它就可以做一些事情,而不需要优化掉或将常量传播给 mov eax, constant_result.


2
投票

在寄存器中添加可能 更快(因为寄存器在芯片上),但是,由于你必须加载和存储数据,你不可能看到改进。

冗长的方法甚至可能是 较慢 因为CPU可能有机会优化较短的代码。此外,较短的代码 readmodifywrite有原子性,就看你怎么编码了。它当然不会浪费 eax 寄存器。

一句话,较长的代码不太可能有足够的改进(如果有的话)来证明可读性的影响。

但你不必猜测(甚至不必问我们)--芯片制造商提供了大量关于指令时序的细节。比如说 英特尔的优化手册.

© www.soinside.com 2019 - 2024. All rights reserved.