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

Ale*_*lex 2 x86 assembly x86-64 micro-optimization

什么更快:

add DWORD PTR [rbp-0x4],1
Run Code Online (Sandbox Code Playgroud)

或者

 mov    eax,DWORD PTR [rbp-0x4]
 add    eax,1
 mov    DWORD PTR [rbp-0x4],eax
Run Code Online (Sandbox Code Playgroud)

我已经看到编译器生成的第二个代码,所以也许调用add寄存器要快得多?

Pet*_*des 5

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

在 Intel CPU 上,add [mem], imm解码为微融合加载+添加和微融合存储地址+存储数据,因此前端总共有 2 个融合域 uops。AMD CPU 始终将内存操作数与 ALU 操作分组在一起,而不将其称为“微融合”,这就是它们一直以来的工作方式。(https://agner.org/optimize/INC 指令与 ADD 1:有关系吗?)。


第一种方法不会将值留在 register 中,因此您不能将其用作++aif 表达式的值的一部分。仅针对对内存的副作用。


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

为什么 clang 使用 -O0 产生低效的 asm(对于这个简单的浮点和)?- 在调试模式下编译,又名-O0(默认)单独编译每个 C 语句,并将每个变量视为类似volatile,这非常可怕。

请参阅如何从 GCC/clang 程序集输出中去除“噪音”?关于如何让编译器制作有趣的 asm。 编写一个接受 args 并返回一个值的函数,这样它就可以在不优化或将常量传播到mov eax, constant_result.