Skip to content

JIT: Why are ranche checks not optimized #135418

Closed

Description

@Corniel

While working an an IBAN parser, I stumbled on char.IsBetween():

public static bool IsBetween(char c, char minInclusive, char maxInclusive)
  => (uint)(c - minInclusive) <= (uint)(maxInclusive - minInclusive);

As was writing code that also had to support .NET standard 2.0, I could not use the function itself, and wrote my own version (where the compiler even pre-calculated maxInclusive - minInclusive). So far so good. Then I thought, why not use inline range matching, as it easier to read, and the I assumed the JIT would optimize it this way anyway. But when I did, my benchmark became slower.

So I dove into the disassembly using the following:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;

[DisassemblyDiagnoser(printInstructionAddresses: true, syntax: DisassemblySyntax.Masm)]
public class Digit
{
	public uint n { get; set; } = '1';

	[Benchmark]
	public bool Pattern() => n is >= '0' and <= '9';

	[Benchmark]
	public bool Subtract() => n - '0' <= '9' - '0';
}

Which resulted in:

.NET 10.0.12 (10.0.12, 10.0.1226.42308), X64 RyuJIT x86-64-v3 (Job: DefaultJob)

; Digit.Pattern()
       7FF9F8DDA520 mov       eax,[rcx+8]
       7FF9F8DDA523 xor       ecx,ecx
       7FF9F8DDA525 cmp       eax,39
       7FF9F8DDA528 setbe     dl
       7FF9F8DDA52B movzx     edx,dl
       7FF9F8DDA52E cmp       eax,30
       7FF9F8DDA531 mov       eax,edx
       7FF9F8DDA533 cmovb     eax,ecx
       7FF9F8DDA536 ret
; Total bytes of code 23

.NET 10.0.12 (10.0.12, 10.0.1226.42308), X64 RyuJIT x86-64-v3 (Job: DefaultJob)

; Digit.Subtract()
       7FF9F8DEA4D0 mov       eax,[rcx+8]
       7FF9F8DEA4D3 add       eax,0FFFFFFD0
       7FF9F8DEA4D6 cmp       eax,9
       7FF9F8DEA4D9 setbe     al
       7FF9F8DEA4DC movzx     eax,al
       7FF9F8DEA4DF ret
; Total bytes of code 16

Why is this optimization not applied? Is in the general case not better? Is there something off with my code/setup why it is not done? Or this is this a welcomed improvement that could be added?

Activity

  1. added
    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
    on Oct 8, 2026
  2. dotnet-policy-service commented on Oct 8, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
    See info in area-owners.md if you want to be subscribed.

  3. MihuBot commented on Oct 8, 2026

    @MihuBot

    I'm a bot. Here are possible related and/or duplicate issues (I may be wrong):

  4. added this to the Future milestone on Oct 8, 2026
  5. removed
    untriagedNew issue has not been triaged by the area owner
    on Oct 8, 2026
  6. self-assigned this
    on Oct 8, 2026
  7. modified the milestones: Future, 12.0.0 on Oct 8, 2026
  8. Corniel commented on Oct 9, 2026

    @Corniel
    Author

    Someone also pointed out #93521, suggesting this was already addressed?!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions