Skip to content

JIT: Switch to rangecheck when profitable#128524

Open
BoyBaykiller wants to merge 3 commits into
dotnet:mainfrom
BoyBaykiller:switch-collapse-to-range-check-more
Open

JIT: Switch to rangecheck when profitable#128524
BoyBaykiller wants to merge 3 commits into
dotnet:mainfrom
BoyBaykiller:switch-collapse-to-range-check-more

Conversation

@BoyBaykiller
Copy link
Copy Markdown
Contributor

@BoyBaykiller BoyBaykiller commented May 23, 2026

https://godbolt.org/z/ovnb41bfv

The current switch normalization logic (inserting GT_SUB) is purely correctness driven to fit the jump table. Consider:

static bool Test1(int a)
{
    return a == 300 || a == 301 || a == 302;
}
static bool Test2(int a)
{
    return a == 3 || a == 4 || a == 5;
}

Test1 would be normalized by switch-recognition because it has numbers larger than SWITCH_MAX_DISTANCE while Test2 wouldn't. This difference would lead to one being collapsed into range-check while the other wouldn't:

G_M12381_IG02:  ;; offset=0x0000
       sub      ecx, 300
       cmp      ecx, 3
       setb     al
       movzx    rax, al
G_M1246_IG02:  ;; offset=0x0000
       cmp      ecx, 5
       ja       SHORT G_M1246_IG06
						;; size=5 bbWeight=1 PerfScore 1.25
G_M1246_IG03:  ;; offset=0x0005
       mov      eax, 7
       bt       eax, ecx
       jb       SHORT G_M1246_IG06
						;; size=10 bbWeight=0.97 PerfScore 1.70
G_M1246_IG04:  ;; offset=0x000F
       mov      eax, 1
						;; size=5 bbWeight=0.25 PerfScore 0.06
G_M1246_IG05:  ;; offset=0x0014
       ret      
						;; size=1 bbWeight=0.25 PerfScore 0.25
G_M1246_IG06:  ;; offset=0x0015
       xor      eax, eax
						;; size=2 bbWeight=0.25 PerfScore 0.06
G_M1246_IG07:  ;; offset=0x0017
       ret      

Here I am just adding an additional check to normalize the switch whenever the numbers form a continous range which fixes that.

…t will be collapsed to range check by later phase (Optimize pre-layout)
@github-actions github-actions Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 23, 2026
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label May 23, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

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

{
switchValue =
gtNewOperNode(GT_SUB, switchValue->TypeGet(), switchValue, gtNewIconNode(minValue, switchValue->TypeGet()));
if (minValue != 0)
Copy link
Copy Markdown
Contributor Author

@BoyBaykiller BoyBaykiller May 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, this identity check is needed as nothing after "recognize switch" phase optimizes out the SUB(x, 0)

Copy link
Copy Markdown
Contributor Author

@BoyBaykiller BoyBaykiller Jun 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our canonical form would be Add(switchValue, -minValue), should I use that instead?
Then the if-chain shown in the PR description would match codegen for manual switch

@BoyBaykiller BoyBaykiller changed the title JIT: Normalize switch so it gets collapse into range check JIT: Switch to rangecheck when profitable Jun 5, 2026
@BoyBaykiller
Copy link
Copy Markdown
Contributor Author

@AndyAyersMS PTAL. Simple change. diffs

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

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant