<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/112488>112488</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Use shrdq to insert into a bitfield
</td>
</tr>
<tr>
<th>Labels</th>
<td>
backend:X86,
missed-optimization
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
kazutakahirata
</td>
</tr>
</table>
<pre>
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
}
```
https://godbolt.org/z/fdcWqMnvW
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyMVV2v2jgQ_TXmZQRynBCShzzwIaSVbrVSt9327cqJJ8TFscF2aLm_fmVDKNBu26urhHjOOfacscfcObnTiBWZr8h8M-GD74yt9vxt8HzPO2m555PaiHO1NtpJgRakdmi91DvgcOJqQJDaG-BAGOu5HrhSZ-i55jsUhDGopYdWohJAWOE77kE6wtbwVfrODB4GF7RITkm6hISSnILUQS6nztuh8SHESpIuCd0QOj5zev2Pn4PUPs9ePQwHwT1-MIeErqR3hBW30DLMevtaEVYCWawufPgeeMfdHki6CctNPr68AEnXJF3DPAuMKSQkvZEs-sHqgFwCYXnkXnTXYXD1wL3xyGLz0yQuzw-ddOD5Hh34DkGZr2ghocFHB601fXBmFWziWlyr4S41CHhvDje0aQM2TDN78q5RXO9g-ncK057bpiPpxu3Piu8xCO9Qo-Ue3a9Nh-tfb051eBOWhURD6nOuHjH1WyePETO3_NsVZIUcf_Fvj3jXqeOzpnXyEWRsxIyxZymL_vgLoz8hNGZQAhS2fuo62frooEDnpeZeGg3egMXenDBGRl-D8b5DDQe0rbE9cBBmqBVODxYb6QLTyl03qiq5R3DmN2725nQcs7k35posSVewNoczLC_Ffr_8PPtfzxL6Az8K_BPX8375OSYN9XnM6QcpK47PUvcWP6nFbO_k4GsnFYZtHA73w-5dzf6sPB86hJeXf9_BX--hNTYWYE3YirAVNEYgOC0PB_TA61Af-ZvNKrCVGkE486pMwxVoM2iBLcg8A5LRnzQOHZujAGX0LvaOx4GSsCKQRyHC5rHFPI3FRhOnfB205j2KVy6E_d57UHt7vi0-1j9ssNCC4gkP67tKJwVNsrQs5rTMiqQs0juO61TkhPeVswqceXYHMjZijAUh3RcjtR-xrlPj0dXirr-NcWP_pHl13h9iIdiWsO3OiNooPzN2R9j2jbBtK5pPx3f69OkCn4gqFWVa8glWyYKVNGeM5pOuylkj6Jy2TBSYI3JMy4SVYrFYMJHXaTuRFaNhbyY5XdCU5TNcZDlvGC3KlNJ0MScZxZ5LNVPq1IcVTKRzA1ZJwrKimCheo3Lx3mOs5s0etSDp8nORE8YIW4fLTDqHYmoOXvbyLfaDEJtvJrYKotN62DmSUSWdd9-n8dIrrD46vB4ib65Nerwna-njfTgZrKqeDJO-G-pZY3rCtkHx-poerPmCjSdsG7NwhG2viZwq9l8AAAD__1AxNdg">