Skip to content

Conversation

AndyAyersMS
Copy link
Member

If a method has GDVs and the JIT is able to to improve types during inlining, run a pass after inlining that tries to resolve GDVs using those improved types.

This typically happens when the object tested in a GDV is returned from some kind of factory method where the exact type becomes apparent only after inlining.

Contributes to #25448.

If a method has GDVs and the JIT is able to to improve types during inlining,
run a pass after inlining that tries to resolve GDVs using those improved types.

This typically happens when the object tested in a GDV is returned from some kind of
factory method where the exact type becomes apparent only after inlining.

Contributes to dotnet#25448.
@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 Jun 24, 2025
Copy link
Contributor

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

@AndyAyersMS
Copy link
Member Author

@EgorBot --filter "System.Collections.IterateForEach*.*Dictionary"

@AndyAyersMS
Copy link
Member Author

AndyAyersMS commented Jun 25, 2025

libraries tests and SPMI both hit an assert

[19:32:54] ISSUE: <ASSERT> #578761 /Users/runner/work/1/s/src/coreclr/jit/flowgraph.cpp (6883) - Assertion failed 'm_dfsTree->Contains(dominator) && m_dfsTree->Contains(dominated)' in 'Xunit.Sdk.XunitTheoryTestCaseRunner+<AfterTestCaseStartingAsync>d__9:MoveNext():this' during 'Allocate Objects' (IL size 1270; hash 0x7e3c2df3; Tier1)

EgorBot confirms this improves the ConcurrentDictionary<int,int> case as expected but no other dictionary collection types.

@AndyAyersMS
Copy link
Member Author

Can't repro the SPMI assert. I have some other changes to make here so will see if it recurs when I push those.

@AndyAyersMS AndyAyersMS marked this pull request as ready for review June 25, 2025 18:47
@Copilot Copilot AI review requested due to automatic review settings June 25, 2025 18:47
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces a new JIT phase that resolves Guarded Devirtualization (GDV) checks using improved type information discovered during inlining. Key changes include additions to the GuardInfo structure, a new static IsGuard method implementation, a new fgResolveGDVs phase in fgopt.cpp, and updates in the compiler phase handling to integrate this new functionality.

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/coreclr/jit/objectalloc.h Added new fields (m_stmt, m_relop) in GuardInfo and updated the IsGuard method signature.
src/coreclr/jit/objectalloc.cpp Updated IsGuard implementation to capture guard-related nodes, but missing assignment of m_block.
src/coreclr/jit/fgopt.cpp Added a new fgResolveGDVs phase that resolves GDV checks based on improved type information.
src/coreclr/jit/fginline.cpp Updated inline walker to set hasUpdatedTypeLocals when type updates occur during inlining.
src/coreclr/jit/compphases.h Registered the new PHASE_RESOLVE_GDVS phase.
src/coreclr/jit/compiler.h Added a flag and declaration for fgResolveGDVs.
src/coreclr/jit/compiler.cpp Invoked fgResolveGDVs in the main compile flow if optimizations are enabled.

@AndyAyersMS
Copy link
Member Author

@dotnet/jit-contrib PTAL

Arguably we should try folding other branches here too, though I don't know of any other cases where we'd expect to succeed, so have kept this narrowly focused for now.

// Passed the checks... fill in the info.
//
info->m_local = addr->AsLclVar()->GetLclNum();
bool isNonNull = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit for style:

- GenTree* ObjectAllocator::IsGuard(BasicBlock* block, GuardInfo* info)
+ /* static */ GenTree* ObjectAllocator::IsGuard(BasicBlock* block, GuardInfo* info)

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks. I will add this to my (growing) list of deferred cleanups.

Copy link
Member

Choose a reason for hiding this comment

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

Is that actually in our coding conventions? I certainly never add those and prefer to keep them only in the header.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's mentioned here, though with a slightly different format. To be honest, I based this suggestion on what I've seen elsewhere in the codebase, rather than what the guidelines say -- in some respects, we've diverged quite a bit from them (or the document hasn't been maintained).

@AndyAyersMS AndyAyersMS merged commit 5177e08 into dotnet:main Jun 25, 2025
107 of 112 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Jul 27, 2025
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants