Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch pattern matching codegen poorer than if/else #52730

Closed
danmoseley opened this issue May 13, 2021 · 1 comment
Closed

switch pattern matching codegen poorer than if/else #52730

danmoseley opened this issue May 13, 2021 · 1 comment
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner

Comments

@danmoseley
Copy link
Member

danmoseley commented May 13, 2021

Comparing the codegen for these two methods (similar to code added in #51492)

    int F1(int i) {
       int digits = i switch
        {
            < 10 => 1,
            < 100 => 2,
            < 1000 => 3,
            _ => 0,
        };       
        return digits;
    }
    
    int F2(int i) {
        int digits;
        if (i < 10) digits = 1;
        else if (i < 100) digits = 2;
        else if (i < 1000) digits = 3;
        else digits = 0;   
        return digits;
    }

sharplab.io

The codegen for F1 is poorer:

X.F(Int32)
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: cmp edx, 0x64
    L0006: jge short L000f
    L0008: cmp edx, 0xa
    L000b: jl short L0019
    L000d: jmp short L0020
    L000f: cmp edx, 0x3e8
    L0015: jl short L0027
    L0017: jmp short L002e
    L0019: mov eax, 1
    L001e: jmp short L0030
    L0020: mov eax, 2
    L0025: jmp short L0030
    L0027: mov eax, 3
    L002c: jmp short L0030
    L002e: xor eax, eax
    L0030: pop ebp
    L0031: ret

X.F2(Int32)
    L0000: push ebp
    L0001: mov ebp, esp
    L0003: cmp edx, 0xa
    L0006: jge short L000f
    L0008: mov eax, 1
    L000d: jmp short L002c
    L000f: cmp edx, 0x64
    L0012: jge short L001b
    L0014: mov eax, 2
    L0019: jmp short L002c
    L001b: cmp edx, 0x3e8
    L0021: jge short L002a
    L0023: mov eax, 3
    L0028: jmp short L002c
    L002a: xor eax, eax
    L002c: pop ebp
    L002d: ret

In the actual code there are more cases.

@dotnet-issue-labeler dotnet-issue-labeler bot added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner labels May 13, 2021
@jkotas
Copy link
Member

jkotas commented May 13, 2021

The codegen for F1 has better worst case number of conditonal branches. It is better in some case and worse in some cases, depending on your input distribution.

Roslyn turns switch statements like this into binary search. The JIT just produces code that it was told to produce. This Roslyn optimization assumes that each case of the switch statement has similar probabilities. If you want to make sure that the branches are executed in specific order because some of the cases are more likely than other cases, you need to write it by hand.

@ghost ghost locked as resolved and limited conversation to collaborators Jun 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

2 participants