<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">