-
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
Allow StoreLclVar src to be IND/FLD. #59315
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3525,14 +3525,49 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) | |
convertToStoreObj = false; | ||
} | ||
} | ||
else if (!src->OperIs(GT_LCL_VAR)) | ||
else if (src->OperIs(GT_LCL_VAR)) | ||
{ | ||
convertToStoreObj = false; | ||
} | ||
else if (src->OperIs(GT_IND, GT_OBJ, GT_BLK, GT_LCL_FLD)) | ||
{ | ||
#if !defined(TARGET_ARM64) | ||
|
||
if (src->TypeIs(TYP_STRUCT)) | ||
{ | ||
src->ChangeType(lclRegType); | ||
if (src->OperIs(GT_IND, GT_OBJ, GT_BLK)) | ||
{ | ||
if (src->OperIs(GT_OBJ, GT_BLK)) | ||
{ | ||
src->SetOper(GT_IND); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unless there is an assert somewhere that makes sure that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is |
||
} | ||
// This logic is skipped for struct indir in | ||
// `Lowering::LowerIndir` because we don't know the size. | ||
// Do it now. | ||
GenTreeIndir* indir = src->AsIndir(); | ||
LowerIndir(indir); | ||
#if defined(TARGET_XARCH) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have |
||
if (varTypeIsSmall(lclRegType)) | ||
{ | ||
indir->SetDontExtend(); | ||
} | ||
#endif // TARGET_XARCH | ||
} | ||
} | ||
convertToStoreObj = false; | ||
#else // TARGET_ARM64 | ||
// This optimization on arm64 allows more SIMD16 vars to be enregistered but it could cause | ||
// regressions when there are many calls and before/after each one we have to store/save the upper | ||
// half of these registers. So enable this for arm64 only when LSRA is taught not to allocate registers when | ||
// it would have to spilled too many times. | ||
convertToStoreObj = true; | ||
#endif // TARGET_ARM64 | ||
} | ||
else | ||
{ | ||
assert(src->OperIs(GT_LCL_VAR)); | ||
convertToStoreObj = false; | ||
assert(src->OperIsInitVal()); | ||
convertToStoreObj = true; | ||
} | ||
|
||
if (convertToStoreObj) | ||
|
@@ -7214,6 +7249,7 @@ void Lowering::TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, Bas | |
bool useNullCheck = false; | ||
#else // TARGET_XARCH | ||
bool useNullCheck = !ind->Addr()->isContained(); | ||
ind->ClearDontExtend(); | ||
#endif // !TARGET_XARCH | ||
|
||
if (useNullCheck && !ind->OperIs(GT_NULLCHECK)) | ||
|
@@ -7311,14 +7347,6 @@ bool Lowering::TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode) | |
return false; | ||
} | ||
|
||
if (varTypeIsSmall(regType) && !src->IsConstInitVal() && !src->IsLocal()) | ||
{ | ||
// source operand INDIR will use a widening instruction | ||
// and generate worse code, like `movzx` instead of `mov` | ||
// on x64. | ||
return false; | ||
} | ||
|
||
JITDUMP("Replacing STORE_OBJ with STOREIND for [%06u]\n", blkNode->gtTreeID); | ||
blkNode->ChangeOper(GT_STOREIND); | ||
blkNode->ChangeType(regType); | ||
|
@@ -7341,6 +7369,14 @@ bool Lowering::TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode) | |
{ | ||
assert(src->TypeIs(regType) || src->IsCnsIntOrI() || src->IsCall()); | ||
} | ||
|
||
#if defined(TARGET_XARCH) | ||
if (varTypeIsSmall(regType) && src->OperIs(GT_IND)) | ||
{ | ||
src->AsIndir()->SetDontExtend(); | ||
} | ||
#endif // TARGET_XARCH | ||
|
||
LowerStoreIndirCommon(blkNode->AsStoreInd()); | ||
return true; | ||
} | ||
|
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 logic allows us to generate
STORE_LCL_VAR struct<1> V01(IND struct(addr)
asinstead of
The solution with additional flag does not look very nice but it was better than alternatives that I have tried:
STORE_LCL_VAR
: it required too many changes in LSRA/codegen/emitter and it was hard to make it work for all cases and it created many new checks for this scenario;IND
asint
so we domov rax, [addr]
instead ofmov al, [addr]
. This could be a solution without any additional diffs but I am not sure if this transformation is correct.We currently use it for nullchecks already since https://github.com/dotnet/runtime/pull/37991/files so
NULLCHECK byte addr
is currently transformed intoNULLCHECK int addr
but if theaddr
is the last byte on a last readable page won't it cause issues? Maybe we should reconsider this transformation (inruntime/src/coreclr/jit/lower.cpp
Line 6736 in 78593b9
could somebody please confirm if it can't cause issues?