简体   繁体   English

编译器优化call-ret vs jmp

[英]Compiler optimization call-ret vs jmp

I am building one of the projects and I am looking at the generated list file.(target: x86-64) My code looks like: 我正在构建其中一个项目,我正在查看生成的列表文件。(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(){
}

When I see the assembly code, I find "jmp" instruction is used instead of "call-return" pair when calling func_2 and func_3. 当我看到汇编代码时,我发现在调用func_2和func_3时使用“jmp”指令而不是“call-return”对。 I am sure it is one of the compiler optimization and I have not explored how to disable it. 我确信它是编译器优化之一,我还没有探讨如何禁用它。 (GCC) The moment I add some volatile variables to func_2 and func_3 and increment them then "jmp" gets replaced by "call-ret" pair. (GCC)当我向func_2和func_3添加一些volatile变量并递增它们时,“jmp”被“call-ret”对替换。 I am bemused to see the behavior because those variables are useless and they don't serve any purpose. 我很难看到这种行为,因为这些变量是无用的,它们没有任何用途。 Can someone please explain the behavior? 有人可以解释一下这种行为吗?

Thanks 谢谢

If code jumps to the start of another function rather than calling it, when the jumped-to function returns, it will return back to the point where the outer function was called from, ignoring any more of the first function after that point. 如果代码跳转到另一个函数的开头而不是调用它,当跳转到的函数返回时,它将返回到调用外部函数的点,忽略该点之后的第一个函数。 Assuming the behaviour is correct (the first function contributed nothing else to the execution after that point anyway), this is an optimisation because it reduces the number of instructions and stack manipulations by one level. 假设行为是正确的(无论如何第一个函数对该点之后的执行没有贡献),这是一个优化,因为它将指令和堆栈操作的数量减少了一个级别。

In the given example, the behaviour is correct; 在给定的示例中,行为正确的; there's no local stack to pop and no value to return, so there is no code that needs to run after the call. 没有本地堆栈可以弹出,也没有返回值,所以没有代码需要在调用后运行。 ( return_1 , assuming it's not a macro for something, is a pure expression and therefore does nothing no matter its value.) So there's no reason to keep the stack frame around for the future when it has nothing more to contribute to events. return_1 ,假设它不是某个宏的东西,是一个纯粹的表达式,因此无论其值如何都不会做任何事情。)所以没有理由在未来没有任何事情可以促成事件时保持堆栈框架。

If you add volatile variables to the function bodies, you aren't just adding variables whose flow the compiler can analyse - you're adding slots that you've explicitly told the compiler could be accessed outside the normal control flow it can predict. 如果将volatile变量添加到函数体中,那么您不仅要添加编译器可以分析其流的变量 - 您还要添加已经明确告知编译器可以在其可以预测的正常控制流之外访问的插槽 The volatile qualifier warns the compiler that even though there's no obvious way for the variables to escape, something outside has a way to get their address and write to it at any time. volatile限定符警告编译器即使没有明显的方法让变量转义,外部的东西也可以随时获取它们的地址并写入它。 So it can't reduce their lifetime, because it's been told that code outside the function might still try to write to that stack space; 所以它不能减少它们的生命周期,因为它被告知函数外部的代码可能仍然试图写入该堆栈空间; and obviously that means the stack frame needs to continue to exist for its entire declared lifespan. 显然,这意味着堆栈框架需要在整个声明的生命周期内继续存在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM