-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Open
Description
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:
push r14
push rbx
push rax
mov rbx, rsi
movabs r14, -281474976710656
shr rdi, 48
cmp edi, 65527
jne .LBB0_2
call ext1@PLT
.LBB0_2:
call ext2@PLT
and rbx, r14
movabs rax, -2533274790395904
add rsp, 8
cmp rbx, rax
jne .LBB0_3
pop rbx
pop r14
jmp ext1@PLT
.LBB0_3:
pop rbx
pop r14
retwhich uses (x>>48)==0xfff7 for one check call, and (x & 0xffff000000000000) == 0xfff7000000000000 for the other. This ends up initializing large constants (one using up a non-volatile register, bloating prologue/epilogue), but only uses them for one of the cases (meaning that the non-volatile register could be entirely avoided by moving the movabs closer to its use).