Consider the following program:
------------- test.c ---------------
extern void bar(void);
__attribute__((__noinline__))
void foo(int *p) {
*p = 10;
}
void foobar() {
int i;
foo(&i);
bar();
}
------------------------------------TailCallElim will correctly identify the call to bar as a tail call (as foo is nocapture). However, it will not be tail call optimized as it fails isInTailCallPosition() due to the lifetime end marker for the variable i:
define void @foobar() {
entry:
%i = alloca i32, align 4
%0 = bitcast i32* %i to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0)
call void @foo(i32* nonnull %i)
tail call void @bar()
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0)
ret void
}On x86_64 this generates:
foobar: pushq %rax leaq 4(%rsp), %rdi callq foo callq bar popq %rax retq
After this patch we get:
foobar: pushq %rax leaq 4(%rsp), %rdi callq foo popq %rax jmp bar # TAILCALL