Repository: rust
Issue: Unnecessary assembly generated on match statement of u64::trailing_zeros() result
Labels: A-LLVM,I-slow,A-codegen,E-needs-test,T-compiler,C-bug

```rust
pub enum Square2 {
    A1, B1, C1, D1, E1, F1, G1, H1, 
    A2, B2, C2, D2, E2, F2, G2, H2, 
    A3, B3, C3, D3, E3, F3, G3, H3, 
    A4, B4, C4, D4, E4, F4, G4, H4, 
    A5, B5, C5, D5, E5, F5, G5, H5, 
    A6, B6, C6, D6, E6, F6, G6, H6, 
    A7, B7, C7, D7, E7, F7, G7, H7, 
    A8, B8, C8, D8, E8, F8, G8, H8, 
    ZZ
}

pub fn ggg(v: u64) -> Square2 {
    match v.trailing_zeros() {
        0o00 => Square2::A1,
        0o01 => Square2::B1,
        0o02 => Square2::C1,
        0o03 => Square2::D1,
        0o04 => Square2::E1,
        0o05 => Square2::F1,
        0o06 => Square2::G1,
        0o07 => Square2::H1,

        0o10 => Square2::A2,
        0o11 => Square2::B2,
        0o12 => Square2::C2,
        0o13 => Square2::D2,
        0o14 => Square2::E2,
        0o15 => Square2::F2,
        0o16 => Square2::G2,
        0o17 => Square2::H2,

        0o20 => Square2::A3,
        0o21 => Square2::B3,
        0o22 => Square2::C3,
        0o23 => Square2::D3,
        0o24 => Square2::E3,
        0o25 => Square2::F3,
        0o26 => Square2::G3,
        0o27 => Square2::H3,

        0o30 => Square2::A4,
        0o31 => Square2::B4,
        0o32 => Square2::C4,
        0o33 => Square2::D4,
        0o34 => Square2::E4,
        0o35 => Square2::F4,
        0o36 => Square2::G4,
        0o37 => Square2::H4,

        0o40 => Square2::A5,
        0o41 => Square2::B5,
        0o42 => Square2::C5,
        0o43 => Square2::D5,
        0o44 => Square2::E5,
        0o45 => Square2::F5,
        0o46 => Square2::G5,
        0o47 => Square2::H5,

        0o50 => Square2::A6,
        0o51 => Square2::B6,
        0o52 => Square2::C6,
        0o53 => Square2::D6,
        0o54 => Square2::E6,
        0o55 => Square2::F6,
        0o56 => Square2::G6,
        0o57 => Square2::H6,

        0o60 => Square2::A7,
        0o61 => Square2::B7,
        0o62 => Square2::C7,
        0o63 => Square2::D7,
        0o64 => Square2::E7,
        0o65 => Square2::F7,
        0o66 => Square2::G7,
        0o67 => Square2::H7,

        0o70 => Square2::A8,
        0o71 => Square2::B8,
        0o72 => Square2::C8,
        0o73 => Square2::D8,
        0o74 => Square2::E8,
        0o75 => Square2::F8,
        0o76 => Square2::G8,
        0o77 => Square2::H8,

        0o100 => Square2::ZZ,

        _ => unreachable!(),
    }
}
```

https://godbolt.org/z/c9Y83vsPc

The assembly generated does not need to check if the `trailing_zeros()` result is greater than 64 and does not need the panic branch because the enumeration has 65 elements. All possible results of `trailing_zeros()` can be converted into the enumeration. 

The above code generates the assembly below:

```asm
example::ggg:
        test    rdi, rdi
        je      .LBB0_1
        bsf     rax, rdi
        cmp     eax, 65
        jae     .LBB0_4
.LBB0_5:
        ret
.LBB0_1:
        mov     eax, 64
        cmp     eax, 65
        jb      .LBB0_5
.LBB0_4:
        push    rax
        lea     rdi, [rip + .L__unnamed_1]
        lea     rdx, [rip + .L__unnamed_2]
        mov     esi, 40
        call    qword ptr [rip + core::panicking::panic@GOTPCREL]
        ud2

.L__unnamed_1:
        .ascii  "internal error: entered unreachable code"

.L__unnamed_3:
        .ascii  "/app/example.rs"

.L__unnamed_2:
        .quad   .L__unnamed_3
        .asciz  "\017\000\000\000\000\000\000\000Y\000\000\000\016\000\000"
```

The panic branch, setting a register to 64 then checking if it is below 65, unreachable branch, etc. are all unnecessary.

The problem does not happen when trying `u8`, `u16`, `u32` and changing the code as appropriate. With these smaller data types, the assembly generated is entirely reasonable:

```asm
example::ggg:
        test    edi, edi
        je      .LBB0_1
        bsf     eax, edi
        ret
.LBB0_1:
        mov     eax, 32
        ret
```

I expected to see this happen with `u64`: The code generated would not have unnecessary comparisons and out-of-bounds panic code, similar to the code generated when using `u8`, `u16`, `u32`.

Tried Rust 1.63, 1.66, beta and nightly withe same results.

`rustc --version --verbose`:
```
$ rustc --version --verbose
rustc 1.66.0 (69f9c33d7 2022-12-12)
binary: rustc
commit-hash: 69f9c33d71c871fc16ac445211281c6e7a340943
commit-date: 2022-12-12
host: x86_64-unknown-linux-gnu
release: 1.66.0
LLVM version: 15.0.2
```