如何检查gcc是否执行尾递归优化? [英] How do I check if gcc is performing tail-recursion optimization?

查看:127
本文介绍了如何检查gcc是否执行尾递归优化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何判断gcc(更具体地说,g ++)是否正在优化特定函数中的尾递归 ? (因为它出现了几次:我不想测试gcc是否可以优化尾递归,我想知道它是否优化了尾递归函数。)

How do I tell if gcc (more specifically, g++) is optimizing tail recursion in a particular function? (Because it's come up a few times: I don't want to test if gcc can optimize tail recursion in general. I want to know if it optimizes my tail recursive function.)

如果您的答案是查看生成的汇编程序,我想知道我在找什么,以及我是否可以编写一个简单程序来检查汇编程序看看是否有优化。

If your answer is "look at the generated assembler", I'd like to know exactly what I'm looking for, and whether or not I could write a simple program that examines the assembler to see if there's optimization.

PS。我知道这是问题的一部分如果有的话, C ++编译器从5个月前开始进行尾递归优化?。但是,我不认为这个问题的这个部分得到了满意的回答。 (答案是:检查编译器是否进行了优化(我知道)的最简单方法是执行调用,否则会导致堆栈溢出 - 或者查看程序集输出。)

PS. I know this appears as part of the question Which, if any, C++ compilers do tail-recursion optimization? from 5 months ago. However, I don't think this part of that question was answered satisfactorily. (The answer there was "The easiest way to check if the compiler did the optimization (that I know of) is perform a call that would otherwise result in a stack overflow – or looking at the assembly output.")

推荐答案

让我们使用来自其他问题的示例代码。编译它,但是告诉gcc不要汇编:

Let's use the example code from the other question. Compile it, but tell gcc not to assemble:


gcc -std=c99 -S -O2 test.c

现在让我们看看结果的 test.s 文件中的 _atoi 函数(Mac OS 10.5上的gcc 4.0.1):

Now let's look at the _atoi function in the resultant test.s file (gcc 4.0.1 on Mac OS 10.5):

        .text
        .align 4,0x90
_atoi:
        pushl   %ebp
        testl   %eax, %eax
        movl    %esp, %ebp
        movl    %eax, %ecx
        je      L3
        .align 4,0x90
L5:
        movzbl  (%ecx), %eax
        testb   %al, %al
        je      L3
        leal    (%edx,%edx,4), %edx
        movsbl  %al,%eax
        incl    %ecx
        leal    -48(%eax,%edx,2), %edx
        jne     L5
        .align 4,0x90
L3:
        leave
        movl    %edx, %eax
        ret

编译器对此函数执行了尾部优化。我们可以看出,因为在该代码中没有 call 指令,而原始的C代码显然有一个函数调用。此外,我们可以看到 jne L5 指令,该指令在函数中向后跳转,指示C代码中没有明显循环时的循环。如果您在重新编译时关闭了优化,则会看到一行说 call _atoi ,并且您也看不到任何向后跳转。

The compiler has performed tail-call optimization on this function. We can tell because there is no call instruction in that code whereas the original C code clearly had a function call. Furthermore, we can see the jne L5 instruction, which jumps backward in the function, indicating a loop when there was clearly no loop in the C code. If you recompile with optimization turned off, you'll see a line that says call _atoi, and you also won't see any backward jumps.

您是否可以自动化这是另一回事。汇编代码的细节将取决于您正在编译的代码。

Whether you can automate this is another matter. The specifics of the assembler code will depend on the code you're compiling.

我认为,您可以通过编程的方式发现它。使函数打印出堆栈指针的当前值(在x86上注册ESP)。如果该函数为第一次调用打印的值与递归调用的值相同,那么编译器已执行尾部调用优化。这个想法需要修改你希望观察的功能,这可能会影响编译器选择优化函数的方式。如果测试成功(两次输出相同的ESP值),那么我认为可以合理地假设优化也将在没有使用仪器的情况下执行,但如果测试失败,我们将不知道失败是由于添加检测代码。

You could discover it programmatically, I think. Make the function print out the current value of the stack pointer (register ESP on x86). If the function prints the same value for the first call as it does for the recursive call, then the compiler has performed the tail-call optimization. This idea requires modifying the function you hope to observe, though, and that might affect how the compiler chooses to optimize the function. If the test succeeds (prints the same ESP value both times), then I think it's reasonable to assume that the optimization would also be performed without your instrumentation, but if the test fails, we won't know whether the failure was due to the addition of the instrumentation code.

这篇关于如何检查gcc是否执行尾递归优化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆