为什么空函数不只是返回

Wil*_*ris 5 x86 assembly gcc compilation

如果我编译一个空的 C 函数

void nothing(void)
{
}
Run Code Online (Sandbox Code Playgroud)

在 MacOS 上使用gcc -O2 -S(和clang),它会生成:

_nothing:
    pushq   %rbp
    movq    %rsp, %rbp
    popq    %rbp
    ret
Run Code Online (Sandbox Code Playgroud)

为什么不gcc删除除 之外的所有内容ret?这似乎是一个简单的优化,除非它真的做了一些事情(对我来说似乎不是)。这种模式(开始时推/移动,最后弹出)在其他非空函数中也是可见的,其中rbp否则这些未使用。

在 Linux 上使用更新的gcc (4.4.5) 我只看到

nothing:
    rep
    ret
Run Code Online (Sandbox Code Playgroud)

为什么rep?该rep是在非空的功能缺失。

Mic*_*ael 4

为什么是代表?

这篇博文中解释了原因。简而言之,直接跳转到单字节ret指令会扰乱某些 AMD 处理器上的分支预测。nop并且不是在 之前添加ret,而是添加无意义的前缀字节以节省指令解码带宽。

非空函数中不存在代表。

引用我链接到的博客文章:“当 [ ]是任何类型的分支(条件 ( ) 或无条件 ( ) )的目标时rep ret,[ ] 比简单的更受欢迎”retjne/je/...jmp/call/...
在空函数的情况下,ret将会是 a 的直接目标call。在非空函数中,它不会。

为什么 gcc 不删除除 ret 之外的所有内容?

即使您已指定-O2. 至少对于 gcc,您可以使用-fomit-frame-pointer选项显式告诉编译器忽略它们。