-
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
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 Just experimented a bit with late dead stores removal by unexposing locals in the liveness and repeating to convergence: commit Before adding late dead stores removal: diffs Relative diffs:
Diffs look interesting but TP impacts are too high. Now I'm reverting the experiment commit. |
3450580
to
1915450
Compare
@jakobbotsch can you look this one over again? |
src/coreclr/jit/objectalloc.cpp
Outdated
#ifdef FEATURE_READYTORUN | ||
if (comp->opts.IsReadyToRun() && data->IsHelperCall(comp, CORINFO_HELP_READYTORUN_NEWARR_1)) | ||
{ | ||
len = data->AsCall()->gtArgs.GetArgByIndex(0)->GetNode(); |
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.
Dead code?
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.
I removed R2R support more completely
src/coreclr/jit/helperexpansion.cpp
Outdated
GenTree* const mtStore = gtNewStoreLclFldNode(lclNum, TYP_I_IMPL, 0, mt); | ||
Statement* const mtStmt = gtNewStmt(mtStore); | ||
|
||
fgInsertStmtBefore(block, newStmt, mtStmt); | ||
gtSetStmtInfo(mtStmt); | ||
fgSetStmtSeq(mtStmt); |
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.
GenTree* const mtStore = gtNewStoreLclFldNode(lclNum, TYP_I_IMPL, 0, mt); | |
Statement* const mtStmt = gtNewStmt(mtStore); | |
fgInsertStmtBefore(block, newStmt, mtStmt); | |
gtSetStmtInfo(mtStmt); | |
fgSetStmtSeq(mtStmt); | |
GenTree* const mtStore = gtNewStoreLclFldNode(lclNum, TYP_I_IMPL, 0, mt); | |
Statement* const mtStmt = fgNewStmtFromTree(mtStore); | |
fgInsertStmtBefore(block, newStmt, mtStmt); |
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.
Ditto below, more things can switch to use fgNewStmtFromTree
@@ -181,6 +254,11 @@ inline bool ObjectAllocator::CanAllocateLclVarOnStack(unsigned int lclNu | |||
return false; | |||
} |
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 seems like we should have a limit on the aggregate stack allocated size. That's somewhat preexisting, but probably more important now.
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.
Agree but will do that in a future PR
// If this is a local array, there are no asyncronous modifications, so we can set the | ||
// conservative VN to the liberal VN. | ||
// | ||
VNFuncApp arrFn; | ||
if (vnStore->IsVNNewLocalArr(arrVN, &arrFn)) | ||
{ | ||
loadTree->gtVNPair.SetConservative(loadValueVN); | ||
} | ||
else | ||
{ | ||
loadTree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, loadType)); | ||
} |
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.
Does this actually show up as benefits?
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.
In some limited cases, yes... eg we can const propagate through a[2] = 1; y = a[2];
@jakobbotsch think I've addressed most of the key points. Overall size limit will come in a future PR. |
@AndyAyersMS Did you push those changes? |
Ah, I pushed to my fork, but ... this PR is not from my fork. |
@jakobbotsch changes are there now |
@@ -4227,6 +4227,7 @@ enum GenTreeCallFlags : unsigned int | |||
GTF_CALL_M_CAST_CAN_BE_EXPANDED = 0x04000000, // this cast (helper call) can be expanded if it's profitable. To be removed. | |||
GTF_CALL_M_CAST_OBJ_NONNULL = 0x08000000, // if we expand this specific cast we don't need to check the input object for null | |||
// NOTE: if needed, this flag can be removed, and we can introduce new _NONNUL cast helpers | |||
GTF_CALL_M_STACK_ARRAY = 0x10000000, // this call is a new array helper for a stack allocated array. |
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.
I suppose we weren't able to get rid of this since it's also used in VN.
// modHeap = false; | ||
} | ||
else if (vnf == VNF_JitReadyToRunNewArr) | ||
{ | ||
vnf = VNF_JitReadyToRunNewLclArr; | ||
// modHeap = false; |
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.
Nit: commented code (feel free to remove as part of a follow up)
@@ -14338,7 +14367,22 @@ bool Compiler::fgValueNumberHelperCall(GenTreeCall* call) | |||
} | |||
} | |||
|
|||
if (isAlloc && ((call->gtCallMoreFlags & GTF_CALL_M_STACK_ARRAY) != 0)) |
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.
I suppose this could be changed to FindWellKnownArg(StackArrayLocal) != nullptr
to get rid of the flag
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.
LGTM
Thanks. I have more changes in this area so I can handle the last few bits in a subsequent PR. |
@hez2010 thanks for all the work you did here. |
Positive case:
Codegen:
Negative case:
Codegen:
Benchmark on Mandelbrot:
Diff: https://www.diffchecker.com/bNP4qHdF/