llvm/llvm-project
Ver no GitHub[DAG][X86] Use shrdq to insert into a bitfield
Open
#112.488 aberto em 16 de out. de 2024
backend:X86good first issuemissed-optimization
Métricas do repositório
- Stars
- (26.378 stars)
- Métricas de merge de PR
- (Mesclagem média 1d 2h) (1.000 fundiu PRs em 30d)
Description
Consider inserting a value into a "manually managed" bit field (that is, without using : 10 in a struct):
uint64_t updateTop10Bits(uint64_t A, uint64_t B) {
uint64_t Mask = (1ULL << 54) - 1;
return (A & Mask) | (B << 54);
}
This takes the lower 10 bits from B and inserts into the top 10 bits of A.
clang -O3 -march=skylake generates:
movb $54, %al
bzhiq %rax, %rdi, %rax
shlq $54, %rsi
orq %rsi, %rax
retq
We could left-shift the destination to remove the 10 bits and then perform a double-precision right-shift like so:
movq %rdi, %rax ; Copy A into RAX.
shlq $10, %rax ; Shift RAX left by 10 bits.
shrdq $10, %rsi, %rax ; Shift RAX right by 10 bits while taking 10 bits from B.
retq
The LLVM IR for the C++ code snippet above is:
define dso_local noundef i64 @updateTop10Bits(unsigned long, unsigned long)(i64 noundef %A, i64 noundef %B) local_unnamed_addr {
entry:
%and = and i64 %A, 18014398509481983
%shl = shl i64 %B, 54
%or = or disjoint i64 %shl, %and
ret i64 %or
}