Skip to content

Matching on ASCII digits no longer optimized #123305

Open
@krtab

Description

@krtab

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

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-codegenArea: Code generationC-bugCategory: This is a bug.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions