Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inefficient codegen for checking top bits of a 64-bit integer #62145

Open
dzaima opened this issue Apr 14, 2023 · 0 comments
Open

Inefficient codegen for checking top bits of a 64-bit integer #62145

dzaima opened this issue Apr 14, 2023 · 0 comments

Comments

@dzaima
Copy link

dzaima commented Apr 14, 2023

The code

#include<stdint.h>
#include<stdbool.h>
void ext1(void);
void ext2(void);
static bool check(uint64_t x) {
    return (x>>48) == 0xfff7;
}
void f(uint64_t a, uint64_t b) {
    if (check(a)) ext1();
    ext2();
    if (check(b)) ext1();
}

compiles (x86-64, -O3; compiler explorer) to

f:                                      # @f
        push    r15
        push    r14
        push    rbx
        mov     rbx, rsi
        movabs  r14, -281474976710656
        movabs  r15, -2533274790395904
        shr     rdi, 48
        cmp     edi, 65527
        jne     .LBB0_2
        call    ext1@PLT
.LBB0_2:
        call    ext2@PLT
        and     rbx, r14
        cmp     rbx, r15
        jne     .LBB0_3
        pop     rbx
        pop     r14
        pop     r15
        jmp     ext1@PLT                        # TAILCALL
.LBB0_3:
        pop     rbx
        pop     r14
        pop     r15
        ret

which uses (x>>48)==0xfff7 for one check call, and (x&0xffff000000000000) == 0xfff7000000000000 for the other. This ends up loading those large constants within the function prologue (which increases the prologue/epilogue even more due to pushing out non-volatile registers), but only uses them for one of the cases (meaning that those constants don't even need to be loaded during the prologue).

Simpler example, but without the prologue issue: compiler explorer

void f(uint64_t a, uint64_t b) {
    if (check(a) || check(b)) ext1();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants