-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Open
Description
struct C {
int x;
//~C();
};
bool foo();
void bar();
C C_get_impl();
C C_get() {
return C_get_impl(); // OK, both gcc & clang tail call
}
C C_get_cond() {
if (__builtin_expect(foo(), 1)) {
return C_get_impl(); // gcc tail call, clang missed
} else {
C r = C_get_impl();
bar();
return r;
}
}
struct D {
int x;
~D(); // has destructor
};
D D_get_impl();
D D_get() {
return D_get_impl(); // clang tail call, gcc missed
}
D D_get_cond() {
if (__builtin_expect(foo(), 1)) {
return D_get_impl(); // both gcc & clang missed tail call
} else {
D r = D_get_impl();
bar();
return r;
}
}
clang(trunk) generate code(https://godbolt.org/z/T7hxThzax):
C_get():
jmp C_get_impl()@PLT
C_get_cond():
push rbx
call foo()@PLT
mov ebx, eax
call C_get_impl()@PLT
test bl, bl
je .LBB1_1
pop rbx
ret
.LBB1_1:
mov ebx, eax
call bar()@PLT
mov eax, ebx
pop rbx
ret
D_get():
jmp D_get_impl()@PLT
D_get_cond():
push rbp
push r14
push rbx
mov rbx, rdi
call foo()@PLT
mov ebp, eax
mov rdi, rbx
call D_get_impl()@PLT
test bpl, bpl
je .LBB3_1
.LBB3_2:
mov rax, rbx
pop rbx
pop r14
pop rbp
ret
.LBB3_1:
call bar()@PLT
jmp .LBB3_2
mov r14, rax
mov rdi, rbx
call D::~D()@PLT
mov rdi, r14
call _Unwind_Resume@PLT
DW.ref.__gxx_personality_v0:
.quad __gxx_personality_v0