Hi All, I am trying to perform tail call optimization on the code given at the end of this mail (it is also attached). To facilitate tail call optimization arguments of the functions are maintained in a structure (so that all functions have same signature). The command I used to compile is gcc -S -O2 -fno-inline struct-simple.c -o struct-simple.s I observe that gcc performs tail call optimization by converting the call to functions 'g' and 'h' as 'jmp' instructions in gcc version 4.4.7. However this optimization is not happening with gcc version 4.8.4. Could someone please explain the reason behind this? I learned that for gcc to perform tail call optimization it requires to satisfy a few constraints like (i) caller and callee should have same signature (ii) callee should not refer to a location in caller's stack frame. In some cases, even if the input code satisfies these constraints, I observe that the optimization is not performed. For example in the code shown below if we have a printf (commented now) inside function 'g' gcc fails to convert the call to 'h' as jump. So it would be great if someone can explain or mention some good reference to learn about the exact set of constraints needed to be satisfied for gcc to perform tail call optimization. #include <stdio.h> #include <stdlib.h> struct arglist_max { int i; int j; int k; int l; }; struct arglist_g { int a; int b; }; struct arglist_f { int i; int j; int k; int l; }; void h(struct arglist_max al) { struct arglist_g al_g = *((struct arglist_g *) &al); printf("%d %d\n", al_g.a, al_g.b); } void g(struct arglist_max al) { struct arglist_f al_f = *((struct arglist_f *) &al); struct arglist_g al_g; al_g.a = 10; al_g.b = 20; // The following printf if included the call to funciton // 'h' will not be coverted to a jump. //printf("%d %d\n", al_g.a, al_g.b); struct arglist_max al_max = *((struct arglist_max *) &al_g); h(al_max); } void f(struct arglist_max al) { struct arglist_f al_f; al_f.i = 10; al_f.j = 20; al_f.k = 30; al_f.l = 40; struct arglist_max al_max = *((struct arglist_max *) &al_f); g(al_max); } int main() { struct arglist_max main_al; f(main_al); } Thanks and Regards, -- Raghesh Aloor PhD Scholar PACE Lab, Dept. of CSE, IIT Madras http://www.cse.iitm.ac.in/~raghesh/
#include <stdio.h> #include <stdlib.h> struct arglist_max { int i; int j; int k; int l; }; struct arglist_g { int a; int b; }; struct arglist_f { int i; int j; int k; int l; }; void h(struct arglist_max al) { struct arglist_g al_g = *((struct arglist_g *) &al); printf("%d %d\n", al_g.a, al_g.b); } void g(struct arglist_max al) { struct arglist_f al_f = *((struct arglist_f *) &al); struct arglist_g al_g; al_g.a = 10; al_g.b = 20; // The following printf if included the call to funciton // 'h' will not be coverted to a jump. //printf("%d %d\n", al_g.a, al_g.b); struct arglist_max al_max = *((struct arglist_max *) &al_g); h(al_max); } void f(struct arglist_max al) { struct arglist_f al_f; al_f.i = 10; al_f.j = 20; al_f.k = 30; al_f.l = 40; struct arglist_max al_max = *((struct arglist_max *) &al_f); g(al_max); } int main() { struct arglist_max main_al; f(main_al); }