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

Is calling `add` on a memory location faster than calling it on a register and then moving the value?

什么更快:

add DWORD PTR [rbp-0x4],1

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

我看过编译器生成的第二个代码,所以也许在寄存器上调用 add 会快得多?

添加到寄存器可能 更快(因为寄存器在芯片上)但是,由于您无论如何都必须加载和存储数据,所以您不太可能看到一个改进。

冗长的方法甚至可能 更慢 因为 CPU 可能有机会优化较短的代码。此外,较短的代码 可能 对 read/modify/write 具有原子性,具体取决于您的编码方式。肯定不会浪费eax寄存器。

最重要的是,更长的代码不太可能足以改进(如果有的话)来证明可读性下降是合理的。

但您不必猜测(甚至不必问我们)- 芯片制造商提供了大量有关指令时序的详细信息。例如,Intel's optimisation manual.

它们都解码为相同数量的后端微指令,但内存目标 add 在现代 Intel/AMD CPU 上以更少的融合域微指令通过前端获取这些微指令.

在 Intel CPU 上,add [mem], imm 解码为微融合加载+添加和微融合存储地址+存储数据,因此前端总共有 2 个融合域微指令。 AMD CPU 始终将内存操作数与 ALU 操作分组,而不调用它 "micro-fusion",这就是它们一直以来的工作方式。 (https://agner.org/optimize/ and ).


第一种方法 不会将值留在寄存器中 ,因此如果表达式的值是用过的。仅针对内存的副作用。


使用 [rbp - 4] 并在内存中递增一个本地代码,闻起来像未优化/调试模式代码,您应该 查看 优化的代码通常使用 [rsp +- constant] 来寻址局部变量,并且(除非变量是 volatile)不会立即将其再次存储回内存中。

Why does clang produce inefficient asm with -O0 (for this simple floating point sum)? - 在调试模式下编译,又名 -O0(默认)分别编译每个 C 语句,并像 volatile 一样对待每个变量,这太可怕了。

请参阅 了解如何让编译器生成有趣的 asm。 编写一个接受 args 和 returns 值的函数,这样它可以做一些事情而无需优化或将常量传播到 mov eax, constant_result.