Repository navigation
JIT: Why are ranche checks not optimized #135418
Copy link
Copy link
Closed
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issuePerformance related issue
Milestone
Description
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 16Why 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?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMICLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issuePerformance related issue
Activity
dotnet-policy-service commentedon Oct 8, 2026
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.
MihuBot commentedon Oct 8, 2026
I'm a bot. Here are possible related and/or duplicate issues (I may be wrong):
Corniel commentedon Oct 9, 2026
Someone also pointed out #93521, suggesting this was already addressed?!
JIT: Fold unsigned constant range tests (#135421)