Skip to content

Missed tail call optimization in branch #163811

@rockeet

Description

@rockeet
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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions