确定例程是否已应用gcc的尾调用优化

时间:2014-07-22 04:00:21

标签: gcc compiler-optimization tail-recursion

我需要确定共享对象中的一组例程是否应用了gcc的尾部调用优化。 需要一个C代码,最好使用API​​代替' nm'或者' objdump'系统命令。

任何有关更多信息的链接都会有所帮助

详细说明: 例如。原始C代码就像

void myFunc1(){
   ... // Do something
   myFunc2();
   return;
}

转储函数myFunc1的汇编程序代码:

   0x57ad50b0 <+0>:     push   %ebp
   0x57ad50b1 <+1>:     mov    %esp,%ebp
   0x57ad50b3 <+3>:     mov    0x8(%ebp),%eax
   0x57ad50b6 <+6>:     pop    %ebp
   0x57ad50b7 <+7>:     lea    0x8(%eax),%edx
   0x57ad50ba <+10>:    mov    (%eax),%eax
   0x57ad50bc <+12>:    jmp    0x57ab8010 <myFunc2>

我们可以看到最后一条指令不是&#34;调用myFunc2&#34;但只是&#34; jmp myFunc2&#34;。 由于这个原因,我们无法获得有关&#34; myFunc1&#34;的信息。从堆栈跟踪。 所以我们需要事先确定&#34; myFunc1&#34;可以解决这个问题,以便我们解决它。

1 个答案:

答案 0 :(得分:0)

最直接的方法是使用编译器转储

int bar (int x);

int
foo (int x)
{
  return bar(x);
}

编译:

gcc -O2 -S tailcall.c -fdump-tree-tailc-lineno-details

在转储文件tailcall.c.137t.tailc中,您将看到:

;; Function foo (foo, funcdef_no=0, decl_uid=1721, cgraph_uid=0)

Found tail call [tailcall.c : 6:3] _4 = bar (x_2(D)); [tail call]

接下来,您可以通过这种方式分析您的所有项目。 GCC将编写所有发现尾调用的地方。

但这种方式依赖于gcc版本。我的输出对gcc 4.8.x有效,但对于其他分支,tailcall树的数量,其名称或转储格式可能不同。

如果尾调用问题,那么只需使用-fno-optimize-sibling-calls选项

gcc -O2 -S tailcall.c -fno-optimize-sibling-calls

将产生没有兄弟呼叫的输出。