-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Stop spilling ldvirtftn #120866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Stop spilling ldvirtftn #120866
Conversation
There was a problem hiding this 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 refactors devirtualization handling by renaming a field and removing function pointer spilling for ldvirtftn
operations. The change aims to improve performance by avoiding unnecessary temporary storage while preparing for further Generic Virtual Method (GVM) devirtualization improvements.
Key changes:
- Renamed
wasArrayInterfaceDevirt
toneedsMethodContext
to better reflect its broader purpose - Removed spilling of
ldvirtftn
function pointers to temporary locals - Added better handling for cloned "this" pointers in virtual function calls
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
File | Description |
---|---|
src/coreclr/vm/jitinterface.cpp | Updated field assignments from wasArrayInterfaceDevirt to needsMethodContext |
src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp | Updated SuperPMI recording/replay to use the renamed field |
src/coreclr/tools/superpmi/superpmi-shared/agnostic.h | Renamed struct field from wasArrayInterfaceDevirt to needsMethodContext |
src/coreclr/jit/importercalls.cpp | Removed function pointer spilling, improved "this" pointer handling, updated field references |
src/coreclr/jit/compiler.hpp | Fixed comment for helper function |
src/coreclr/inc/corinfo.h | Updated struct definition and comments to use the new field name |
CORINFO_RESOLVED_TOKEN resolvedTokenDevirtualizedUnboxedMethod; | ||
bool isInstantiatingStub; | ||
bool wasArrayInterfaceDevirt; | ||
bool needsMethodContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a rename without any meaningful change.
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
ba46914
to
ee4bd19
Compare
unsigned lclNum = lvaGrabTemp(true DEBUGARG("VirtualCall through function pointer")); | ||
impStoreToTemp(lclNum, fptr, CHECK_SPILL_ALL); | ||
fptr = gtNewLclvNode(lclNum, TYP_I_IMPL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the only actual change.
ee4bd19
to
1c781c1
Compare
bc516bb
to
a2a1d86
Compare
trigger mihubot since spmi jobs are broken @MihuBot |
It looks like what you're trying to achieve is the devirtualization of indirect calls (GVM specifically), but you seems to be focused on a very specific case where the actual type is created right before the call (judging by your example in #112596 and the fact that you try to avoid spills). I think we should focus on implementing #44610 for PGO first, e.g. using System.Runtime.CompilerServices;
for (int i = 0; i < 200; i++)
{
Test(new MyValueProcessor());
Thread.Sleep(16);
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void Test(IProcessor p)
{
p.Process(42); // should devirtualize, but doesn't today.
}
public interface IProcessor
{
void Process<T>(T item);
}
public class MyValueProcessor : IProcessor
{
public void Process<T>(T item)
{
Console.WriteLine(item?.ToString());
}
} today we give up on instrumenting indirect calls. And then, if you also want to have it divirtualized without the PGO (e.g. NAOT) you can just create fake (speculative) GDVs (which then will be folded once we hit a phase that can see through locals). Instead of just un-spilling the target that might be changed by the args? cc @AndyAyersMS @dotnet/jit-contrib |
ContainCheckIndir(node->AsIndir()); | ||
break; | ||
case GT_PUTARG_REG: | ||
case GT_PUTARG_STK: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the motivation behind this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's trying to suppress an assertion before addressing the lowering issue that is specific to windows-x86:
15:32:19.222 Running test: JIT/Directed/tailcall/more_tailcalls/more_tailcalls.cmd
Assert failure(PID 204 [0x000000cc], Thread: 2564 [0x0a04]): Assertion failed 'node->GetRegNum() != REG_NA' in 'GenInstance`2[System.__Canon,int]:VirtForward[System.__Canon,System.__Canon](System.__Canon,int,System.__Canon,System.__Canon):System.String:this' during 'Lowering nodeinfo' (IL size 23; hash 0xb3dc36bf; FullOpts)
File: D:\a\_work\1\s\src\coreclr\jit\lower.cpp:9445
Image: C:\h\w\ABFD09AF\p\corerun.exe
15:36:59.890 Running test: JIT/Regression/JitBlue/Runtime_87393/Runtime_87393/Runtime_87393.cmd
Assert failure(PID 9576 [0x00002568], Thread: 9588 [0x2574]): Assertion failed 'node->GetRegNum() != REG_NA' in 'Runtime_87393.Bar:M2[int](int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int):int' during 'Lowering nodeinfo' (IL size 41; hash 0x12b37abb; FullOpts)
File: D:\a\_work\1\s\src\coreclr\jit\lower.cpp:9445
Image: C:\h\w\ABFD09AF\p\corerun.exe
We first need to stop spilling ldvirtftn before we can take the next step on GVM devirt.
Let's stop spilling them and see what we need to take to handle potential regressions.
Contributes to #112596