【问题标题】:Compiler optimization call-ret vs jmp编译器优化 call-ret vs jmp
【发布时间】:2014-10-28 17:57:59
【问题描述】:

我正在构建其中一个项目,并且正在查看生成的列表文件。(目标: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”对。我确信这是编译器优化之一,我还没有探索如何禁用它。 (海合会) 当我向 func_2 和 func_3 添加一些 volatile 变量并递增它们时,“jmp”就会被“call-ret”对替换。 我很困惑地看到这种行为,因为这些变量是无用的,它们没有任何用途。 有人可以解释一下这种行为吗?

谢谢

【问题讨论】:

    标签: c linux gcc compiler-construction


    【解决方案1】:

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

    在给定的例子中,行为正确的;没有要弹出的本地堆栈,也没有要返回的值,因此在调用之后没有需要运行的代码。 (return_1,假设它不是某个东西的宏,它是一个纯粹的表达式,因此无论它的值如何都不做任何事情。)因此,当堆栈框架对事件没有任何贡献时,没有理由保留它以备将来使用。

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

    【讨论】:

      猜你喜欢
      • 2016-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-11
      • 2012-04-21
      • 2011-11-07
      • 1970-01-01
      相关资源
      最近更新 更多