Clarification on gcc tail call optimization

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);
}

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux