<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/103501>103501</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [x86-64 BMI2] Missed canonicalization on ~blsmsk
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Validark
      </td>
    </tr>
</table>

<pre>
    This code:

```zig
export fn foo(a: u64) u64 {
    return ~blsmsk(a);
}

fn blsmsk(a: u64) u64 {
 return (a ^ (a - 1));
}
```

Gives this emit:

```asm
foo:
        mov     rax, rdi
        neg rax
        xor     rax, rdi
        ret
```

With inline assembly, we can force the compiler to do the thing we want:

```asm
export fn bar(a: u64) u64 {
    return ~blsmsk_asm(a);
}

inline fn blsmsk_asm(src: u64) u64 {
 return asm ("blsmsk %[src], %[ret]"
        : [ret] "=r" (-> u64),
 : [src] "r" (src),
    );
}
```

```asm
bar:
 blsmsk  rax, rdi
        not     rax
        ret
```

In my real code, I was doing a bitwise AND on `~blsmsk(a)`. Meaning the `not` can be folded into an `ANDN` instruction.

```zig
export fn foo(a: u64, b: u64) u64 {
    return ~blsmsk(a) & b;
}
```

```asm
foo:
        mov     rax, rdi
 neg     rax
        xor     rax, rdi
        and     rax, rsi
 ret
```

Again, with inline assembly, we can get:

```asm
bar:
        blsmsk  rax, rdi
        andn rax, rax, rsi
        ret
```

[Godbolt link](https://zig.godbolt.org/z/GMcf56rj7)
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycVU1z4jgQ_TXypQtKbn8ABx8gDKkcktPW7nFLtoTRRJZSkghJDvvbt9p2SJiZwDCuVITVr5_647UsQtCtVapixYoV60Ts48756m9htBT-MamdfK3-2ukAjZOKZUvG14y__y_58Pem22FHvTw5H2FrYescw7lg2RL2Zc5wQQuw2WoAAgB4Fffewn-1CV147NG4YNmIYLP157O2Fj7hvmIdKQkDrPg2_JhASsS_5H7P4PNRt_pZBYiUtOp0_CppEboxNOeOGBifzj33qxcvDG_AS31qt6rtbSebL86fdfIqngn7Hx13oK3RVoEIQXW1eSWag4JGUEN8oyDuFDSue9JGeYgOpOu34k7blpAHYS8n_NHlWvjruvwvkZzv9JjCseGjS_DNpbaL0FHHGeLgCQwLVqzIs1hTKYZ3KiO942l1if1oBTJna88QiXLCsm_j0QxvRr_RYaAnh3c07XwGEvlvq-_nclORj_oaM_taWC4eNXSFeO4sdK_glTDDoOMN3MFBBJCOlCGg1vGgg4LlwxqcBVbyH-a25FO4V8ISnCTFSm5dZCXv1Vcr2DojlQRtowPRMywf1g8E0DZEv2-idnb6p_fLDdRX3zXAsCS3P-zLVXNPA__LvlwaemHliT3oD9GfCXfZCm378T9_LbTq8ryfCHB8LulQWGmPxh9D_y1JsmJ162TtTASj7WM_svNdjE-BgsENw82bbqftgJk639IOw83tfbMtSv99xnCRyCqTi2whElWlM8xKjgvEZFcJmc9rmecLkSOKdJtumzlPxZwLkTV1jYmukGPO52nOMSsQp7Mam0I1is-zsqxnKcu56oQ2U2OeOzo-0SHsVZXyrOBpYkStTOi_q4hWHaC30rVSrBNfkdOk3reB5dzoEMMHTdTR9B_kl3k5KXNY3d-RE9zrEJSkrjmrG2H0m6CRoXEcdZ3svalOS9TquNvX08Z1DDd0xLhMnrz7rprIcNMHFhhuxsifK_w_AAD__2F8LvI">