镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

JIT: Expand PGO casts with up to three type checks - #136248

Open
EgorBo wants to merge 4 commits into
dotnet:mainfrom
EgorBo:jit-helper-pgo-casts
Open

EgorBo wants to merge 4 commits into
dotnet:mainfrom
EgorBo:jit-helper-pgo-casts

Conversation

@EgorBo

@EgorBo EgorBo commented Oct 21, 2026

Copy link
Copy Markdown
Member

Use up to three compatible profiled runtime types when expanding isinst/castclass, rather than only the first candidate. Guards sharing a result block must agree on returning the object or null, and multi-check expansions load the method table once. The general cast helper remains the fallback for unprofiled types.

Add DOTNET_JitCastMaxTypeChecks (default 3) to control cast candidates independently of virtual-call GDV. NativeAOT's getExactClasses enumeration uses the same budget without relaxing its existing exactness checks; size-optimized NativeAOT casts consequently default to three candidates instead of one.

Clamp normalized conditional edge likelihoods to avoid floating-point rounding assertions when candidate probabilities sum to 100%.

EgorBo and others added 2 commits October 21, 2026 20:47
Use compatible candidates returned by pickGDV instead of discarding every candidate after the first. Validate candidates with compareTypesForCast and require guards sharing a success block to agree on whether they return the object or null.

Load the object's method table once for multi-guard expansions. Retain the specialized class-cast fallback only when the target type itself has been ruled out, and keep the existing GDV candidate limits and profitability thresholds unchanged.

<!-- -->

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cc84edb4-2bc3-4cfb-81af-8c1922ce58d8
Add DOTNET_JitCastMaxTypeChecks, defaulting to 3, for profiled and enumerated cast candidates. Keep virtual-call guarded devirtualization on its existing independent budget.

Clamp conditional edge likelihoods to one so floating-point roundoff cannot cause an assertion when several cast candidates cover 100% of the profile.

<!-- -->

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cc84edb4-2bc3-4cfb-81af-8c1922ce58d8
@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 Oct 21, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@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.

@EgorBo

This comment was marked as outdated.

@EgorBo

EgorBo commented Oct 21, 2026

Copy link
Copy Markdown
Member Author

@EgorBot -arm -amd

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(CastBench).Assembly).Run(args);

public class CastBench {
    private readonly object[] _objects = [new B(), new C()];

    [Benchmark(OperationsPerInvoke = 2)]
    public int IsA() {
        int count = 0;
        foreach (object obj in _objects) {
            if (obj is A) {
                count++;
            }
        }
        return count;
    }

    private class A { }
    private sealed class B : A { }
    private sealed class C : A { }
}

Note

This benchmark comment was composed with GitHub Copilot.

@EgorBo

EgorBo commented Oct 22, 2026

Copy link
Copy Markdown
Member Author

PTAL @dotnet/jit-contrib @adamperlin

A few improvements to cast expansion, enable multiple guessed by default.
Example of a benchmark - improved by 1.5x

@EgorBo
EgorBo requested a review from adamperlin October 22, 2026 15:33
@jkotas

jkotas commented Oct 22, 2026

Copy link
Copy Markdown
Member

size-optimized NativeAOT casts consequently default to three candidates instead of one.

What is the size optimization that this is talking about? Checking three candidates inline does not sound like a size optimization to me - it is more code than a call to a cast helper.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 474803a8-11ce-496c-a351-ff85e990bedc
@EgorBo

EgorBo commented Oct 22, 2026

Copy link
Copy Markdown
Member Author

size-optimized NativeAOT casts consequently default to three candidates instead of one.

What is the size optimization that this is talking about? Checking three candidates inline does not sound like a size optimization to me - it is more code than a call to a cast helper.

@jkotas oops, that was not intentional, although, e.g. 2 exact checks (no fallback) is not much bigger than just helper-call: https://godbolt.org/z/bcfqc6v5W (in case of NAOT we mostly talk about the non-fallbac get-exact-classes case only).

Fixed.

This branch has not been deployed

No deployments
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants