rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.9k stars 12.52k forks source link

Matching on ASCII digits no longer optimized #123305

Open krtab opened 5 months ago

krtab commented 5 months ago

Code

This

pub fn f(character: u8) -> Option<u8> {
    match character {
        b'0' => Some(0),
        b'1' => Some(1),
        b'2' => Some(2),
        b'3' => Some(3),
        b'4' => Some(4),
        b'5' => Some(5),
        b'6' => Some(6),
        b'7' => Some(7),
        b'8' => Some(8),
        b'9' => Some(9),
        _ => None,
    }
}

used in 1.76.0 to be optimized to

f:
        lea     edx, [rdi - 48]
        cmp     dl, 10
        setb    al
        ret

but in 1.77 and nightly, this remains

f:
        movzx   eax, dil
        add     eax, -48
        cmp     eax, 9
        ja      .LBB0_3
        lea     rcx, [rip + .LJTI0_0]
        movsxd  rax, dword ptr [rcx + 4*rax]
        add     rax, rcx
        jmp     rax
.LBB0_2:
        mov     al, 1
        xor     edx, edx
        ret
.LBB0_3:
        xor     eax, eax
        ret
.LBB0_5:
        mov     dl, 1
        mov     al, 1
        ret
.LBB0_6:
        mov     al, 1
        mov     dl, 2
        ret
.LBB0_7:
        mov     al, 1
        mov     dl, 3
        ret
.LBB0_8:
        mov     al, 1
        mov     dl, 4
        ret
.LBB0_9:
        mov     al, 1
        mov     dl, 5
        ret
.LBB0_10:
        mov     al, 1
        mov     dl, 6
        ret
.LBB0_11:
        mov     al, 1
        mov     dl, 7
        ret
.LBB0_12:
        mov     al, 1
        mov     dl, 9
        ret
.LBB0_13:
        mov     al, 1
        mov     dl, 8
        ret
.LJTI0_0:
        .long   .LBB0_2-.LJTI0_0
        .long   .LBB0_5-.LJTI0_0
        .long   .LBB0_6-.LJTI0_0
        .long   .LBB0_7-.LJTI0_0
        .long   .LBB0_8-.LJTI0_0
        .long   .LBB0_9-.LJTI0_0
        .long   .LBB0_10-.LJTI0_0
        .long   .LBB0_11-.LJTI0_0
        .long   .LBB0_13-.LJTI0_0
        .long   .LBB0_12-.LJTI0_0

Interestingly,

pub fn f(character: u8) -> Option<u32> {
    match character {
        b'0' => Some(0),
        b'1' => Some(1),
        b'2' => Some(2),
        b'3' => Some(3),
        b'4' => Some(4),
        b'5' => Some(5),
        b'6' => Some(6),
        b'7' => Some(7),
        b'8' => Some(8),
        b'9' => Some(9),
        _ => None,
    }
}

and

pub fn f(character: u8) -> Option<u8>
{
    match character {
        b'0' => Some(0),
        b'1' => Some(1),
        b'2' => Some(2),
        b'3' => Some(3),
        b'4' => Some(4),
        b'5' => Some(5),
        b'6' => Some(6),
        b'7' => Some(7),
        //b'8' => Some(8),
        //b'9' => Some(9),
        _ => None,
    }
}

Get well optimized.

Bisected to #118991

@rustbot modify labels: +regression-from-stable-to-stable

I'd like to have a go at this so @rustbot claim

krtab commented 5 months ago

@rustbot label -regression-untriaged

apiraino commented 5 months ago

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-medium