-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
JIT: Extend escape analysis to account for arrays with non-gcref elements #104906
base: main
Are you sure you want to change the base?
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.
For arrays (and also perhaps boxes and ref classes) we ought to have some kind of size limit... possibly similar to the one we use for stackallocs.
We need to be careful we don't allocate a lot of stack for an object that might not be heavily used, as we'll pay per-call prolog zeroing costs.
@AndyAyersMS Now all tests are green, and this is ready for merge, please take another look. |
I have some other changes to escape analysis which are going to conflict, so my plan is to merge those first and then pick this (or something like it) up later. Not sure how long that will take, hopefully not too long. In the meantime, could you check if your changes to Also if you want to peel off the change to always use a temp for |
@hez2010 can you resolve conflicts? The work I was doing was held up so maybe we can work on this and get it in first. |
Hopefully #110787 unblocks this. |
@hez2010 given the small number of diffs from MihuBot, it would be good to understand what changes might be needed elsewhere to make this more effective. I'm guessing the main blocker is lack of inlining, but a quantitative analysis might reveal other things. |
Some interesting diffs from SPMI |
One of the regression coming from - sub rsp, 40
+ sub rsp, 56
;; size=4 bbWeight=0 PerfScore 0.00
G_M52314_IG02: ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
+ vxorps xmm0, xmm0, xmm0
+ vmovdqu xmmword ptr [rsp+0x20], xmm0
+ vmovdqu xmmword ptr [rsp+0x24], xmm0
+ mov rcx, 0xD1FFAB1E ; int[]
+ mov qword ptr [rsp+0x20], rcx
+ mov dword ptr [rsp+0x28], 1
mov ecx, 28
call [System.ThrowHelper:ThrowArgumentNullException(int)]
; gcr arg pop 0
int3 The loop was originally unrolled but now it's no longer doing that. Seems that we need to propagate the assertion into loops so that the bound can be replaced by a constant, which is #110501 |
I will dig into some of these tomorrow. Need to look closely at the dumps. |
@AndyAyersMS BTW we can mark |
If we start passing stack allocated ref classes to callees we also have to fix the GC reporting for those callee arguments to be managed (not object) pointers (and transitively, fix reporting for any place those arguments can propagate, including possibly in the native parts of the runtime). So there is (perhaps considerable) extra work. |
@EgorBo and me discussed on discord that we can probe the size argument using value probing, so that for unknown sized arrays we can do "guarded stack allocation" in the future. It would effectively replace Span<int> arr = new int[size]; with Span<int> arr;
// dummy code below
if (size < 16)
{
arr = stackalloc int[16];
arr.Length = size;
}
else
{
arr = new int[size];
} |
Positive case:
Codegen:
Negative case:
Codegen:
Benchmark on Mandelbrot:
Diff: https://www.diffchecker.com/bNP4qHdF/