llvm optimizer turning musttail into tail

I've got some calls like:

musttail call void bitcast (i32 (i32, i8*, %Type*)* @MyMethod to void (i32, i8*)*)(i32 %0, i8* %1)
ret void

Into something like:
%8 = tail call i32 @MyMethod(i32 %0, i8* %1, %Type* null)
ret void

I realize I'm losing a parameter there, but this is an interface jump trick I use and relies on the end code being a 'jmp' (x86). I realize i can probably use noopt & noinline to do this trick, but I do want llvm to optimize and inline calls if it can prove it always calls a given method. Any way i can do this?

I've got some calls like:

musttail call void bitcast (i32 (i32, i8*, %Type*)* @MyMethod to void
(i32, i8*)*)(i32 %0, i8* %1)
ret void

This should have said: that llvm optimizes into something like:

This sounds buggy to me. What pass is doing this?

– Sean Silva

r287955 seems like it might be related.

– Sean Silva

Inst combine yes. However it shouldn’t drop this bit cast in the first place, since the last parameter isn’t available. (It only works because of this must tail)

Try using the “thunk” attribute: http://llvm.org/docs/LangRef.html#function-attributes

InstCombine has logic to avoid getting rid of the cast in such situations: https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/InstCombine/InstCombineCalls.cpp#L2821

I don’t think dropping from “must tail” to “tail” is a legal thing to do in the IR, isn’t there a bug in InstCombine here?

That looks like it should work, but seems to check the callee only, not the call itself, so :

   musttail call void bitcast (i32 (i32, i8*, %"Type"*)* @"Method" to void (i32, i8*)*)(i32 %0, i8* %1) #3

attributes #3 = { "thunk"="true" }

doesn't work, and I can't place this on the actual method, since that one isn't a thunk.

Aside from instcombine, the inliner will also transform musttail to tail.
The supported use cases for musttail are essentially:
- Avoiding unbounded stack growth for programming languages that require
tail recursion
- Perfect forwarding of parameters which cannot be copied (think C++
objects constructed in argument slots, aka inalloca)
- Perfect forwarding for thunks which are called with varying signatures
(these effectively forward the ellipsis of the caller)

The last case sounds the most like yours, in which case David's suggestion
is the right one.