[llvm-commits] Trampoline changes

Duncan Sands baldrick at free.fr
Fri Sep 28 13:26:01 PDT 2007


Hi Chris,

> >>> My hope was that some of these trampoline calls could be eliminated
> >>> using this optimization.  But for...
> >>
> >> It would be pretty straight-forward to implement an IPO pass that
> >> turns trampoline pointers into fat pointers in cases like this.
> >
> > that's a very interesting idea.  It sounds hard to an LLVM minnow like
> > myself though :)
> >
> >> It sounds like it could be a big win for the container library,  
> >> because
> >> the container (if the routines get marked internal) would
> >> automatically be converted to take fat pointers, even if there are
> >> multiple different trampolines being passed in.
> >
> > Yes, it would be pretty nice.  But how feasible is it?  Surely it will
> > only work well if we can find out all or at least most of the  
> > places that
> > the trampoline function pointer gets passed to.
> 
> It is very feasible and would be pretty straight-forward.  Consider  
> this code in C:
> 
> static void foo(funcptr_t P) {
>    P();
> }
> 
> void a() {
>    tmp = maketrampoline(somefunc1, somedata);
>    foo(tmp);
> }
> void b() {
>    tmp = maketrampoline(somefunc2, somedata);
>    foo(tmp);
> }
> void c() {
>    tmp = maketrampoline(somefunc3, somedata);
>    foo(tmp);
> }

this would probably suffice for a decent percentage of cases.  However things
get more complicated once you have multiple trampolines (because of multiple
nested functions) and multiply nested functions (functions nested inside other
nested functions).  The multiple trampoline problem is kind of dumb: the first
thing that is done to the result of the init_trampoline call is that it is stored
in a local variable.  Since init_trampoline is IntrWriteMem (because it stashes
somefunc and somedata in the trampoline) if there are two init_trampoline calls
in a row then, when the result of the first one is read from memory in order to
be used, LLVM won't recognise it as the result of an init_trampoline call anymore,
because it thinks it might have been clobbered by the other call (IntrWriteMem
causes LLVM to be very pessimistic).  The other problem (nested functions nested
within other nested functions) is that gcc passes the trampoline pointer to
child functions in a struct (the frame struct).  So if you want to handle this
case then you have to track where this struct is being passed to and do more
complicated analysis.

> The idea is to transform it into:
> 
> static void foo(funcptr2_t P1, void *Data) {
>    P1(Data);
> }
> 
> void a() {
>    tmp = maketrampoline(somefunc1, somedata);  // probably dead now.
>    foo(somefunc1, somedata);
> }
> void b() {
>    tmp = maketrampoline(somefunc2, somedata);  // probably dead now.
>    foo(somefunc2, somedata);
> }
> void c() {
>    tmp = maketrampoline(somefunc3, somedata);  // probably dead now
>    foo(somefunc3, somedata);
> }
> 
> The checks involved would be:
> 
> 1. The function (foo) has to have internal linkage.

Right.

> 2. The function is only called by direct calls, no taking the address  
> of foo etc.

Yup.

> 3. It takes some function pointer as an argument.

Yes, it becomes much harder if the function pointer is passed in in
another way, for example in a struct.

> 4. all call sites (which you know are direct) pass in a function  
> pointer obtained from llvm.trampoline

And the functions the trampolines were made from have their "nest"
parameter at the same position (this is the case for code coming
from gcc, where it is always the first parameter).

Also
5. Within foo, you need to check that nothing too complicated is
done to P1, for example it isn't stored in a global or passed to
some other function.
 
> In this case, you can handle it, transforming it as above.  The nice  
> thing about this is that the xform doesn't increase code size, so  
> it's always a win, regardless of how large foo is.

Well, you do have to push another parameter when calling foo, and
when foo calls P1 :)
 
> If you wanted to do this, this should go into the arg promotion pass,  
> which already does much of this analysis.

It's a very nice idea - I'm not sure how many cases it would capture
though.

Best wishes,

Duncan.



More information about the llvm-commits mailing list