Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I check if gcc is performing tail-recursion optimization?

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. 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.")

like image 717
A. Rex Avatar asked Jan 29 '09 02:01

A. Rex


People also ask

How do you know if something is tail-recursive?

A function is tail-recursive if it ends by returning the value of the recursive call. Keeping the caller's frame on stack is a waste of memory because there's nothing left to do once the recursive call returns its value.

Does GCC do tail call optimization?

Regarding functions call optimization, gcc can do tail-call elimination to save the cost of allocating a new stack frame, and tail recursion elimination to turn a recursive function to non-recursive iterative one.

Does C support tail recursion optimization?

Since many Scheme compilers use C as an intermediate target code, the tail recursion must be encoded in C without growing the stack, even if the C compiler does not optimize tail calls. Many implementations achieve this by using a device known as a trampoline, a piece of code that repeatedly calls functions.

Does C++ do tail recursion optimization?

Tail call optimisation isn't in the C++ standard. Apparently, some compilers, including MS Visual Studio and GCC, do provide tail call optimisation under certain circumstances (when optimisations are enabled, obviously).


1 Answers

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 

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 

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.

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.

like image 164
Rob Kennedy Avatar answered Oct 21 '22 17:10

Rob Kennedy