编译器优化call-ret vs jmp

时间:2014-10-28 17:58:00

标签: c linux gcc compiler-construction

我正在构建其中一个项目,我正在查看生成的列表文件。(target:x86-64)我的代码如下:

int func_1(var1,var2){
       asm_inline_(
       )
       func_2(var1,var2);
       return_1;      
}
void func_2(var_1,var_2){
     asm __inline__(
     )
     func_3();
}
/**** Jump to kernel ---> System call stub in assembly. This func in .S file***/
void func_3(){
}

当我看到汇编代码时,我发现在调用func_2和func_3时使用了“jmp”指令而不是“call-return”对。我确信它是编译器优化之一,我还没有探讨如何禁用它。 (GCC)   当我向func_2和func_3添加一些volatile变量并递增它们时,“jmp”被“call-ret”对替换。   我很难看到这种行为,因为这些变量是无用的,它们没有任何用途。   有人可以解释一下这种行为吗?

由于

1 个答案:

答案 0 :(得分:3)

如果代码跳转到另一个函数的开头而不是调用它,当跳转到的函数返回时,它将返回到调用外部函数的点,忽略了在该点之后的第一个函数。假设行为是正确的(无论如何,第一个函数对该点之后的执行没有贡献),这是一个优化,因为它将指令和堆栈操作的数量减少了一个级别。

在给定的示例中,行为 正确;没有本地堆栈可以弹出,也没有返回值,所以没有代码需要在调用后运行。 (return_1,假设它不是一个宏的东西,是一个纯粹的表达式,因此无论它的价值如何都不会做任何事情。)因此,没有任何理由保持堆栈框架的未来,因为它没有更多的贡献事件

如果将volatile变量添加到函数体中,那么您不仅要添加编译器可以分析其流的变量 - 您要添加 slots ,您已明确告知编译器可以被访问外部它可以预测的正常控制流程。 volatile限定符警告编译器即使没有明显的方法让变量转义,外部的东西也可以随时获取它们的地址并写入它。所以它不能减少它们的生命周期,因为它被告知函数外部的代码可能仍会尝试写入该堆栈空间;显然,这意味着堆栈框架需要在整个声明的生命周期内继续存在。