Skip to content

Commit ede3733

Browse files
author
Sergey Andreenko
authored
Enregister structs on win x64. (#55045)
* Enreg structs x64 windows. * try to get zero diffs on other platforms. * fix comment
1 parent 03cb946 commit ede3733

File tree

8 files changed

+45
-37
lines changed

8 files changed

+45
-37
lines changed

src/coreclr/jit/codegencommon.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4355,16 +4355,10 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
43554355
#endif // defined(UNIX_AMD64_ABI)
43564356

43574357
noway_assert(varDsc->lvIsParam && varDsc->lvIsRegArg);
4358-
#ifndef TARGET_64BIT
4359-
#ifndef TARGET_ARM
4360-
// Right now we think that incoming arguments are not pointer sized. When we eventually
4361-
// understand the calling convention, this still won't be true. But maybe we'll have a better
4362-
// idea of how to ignore it.
4363-
4364-
// On Arm, a long can be passed in register
4365-
noway_assert(genTypeSize(genActualType(varDsc->TypeGet())) == TARGET_POINTER_SIZE);
4366-
#endif
4367-
#endif // TARGET_64BIT
4358+
#ifdef TARGET_X86
4359+
// On x86 we don't enregister args that are not pointer sized.
4360+
noway_assert(genTypeSize(varDsc->GetActualRegisterType()) == TARGET_POINTER_SIZE);
4361+
#endif // TARGET_X86
43684362

43694363
noway_assert(varDsc->lvIsInReg() && !regArgTab[argNum].circular);
43704364

src/coreclr/jit/codegenlinear.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,12 +1191,12 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree)
11911191
assert(spillType != TYP_UNDEF);
11921192

11931193
// TODO-Cleanup: The following code could probably be further merged and cleaned up.
1194-
#ifdef TARGET_XARCH
1194+
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
11951195
// Load local variable from its home location.
11961196
// In most cases the tree type will indicate the correct type to use for the load.
11971197
// However, if it is NOT a normalizeOnLoad lclVar (i.e. NOT a small int that always gets
1198-
// widened when loaded into a register), and its size is not the same as genActualType of
1199-
// the type of the lclVar, then we need to change the type of the tree node when loading.
1198+
// widened when loaded into a register), and its size is not the same as the actual register type
1199+
// of the lclVar, then we need to change the type of the tree node when loading.
12001200
// This situation happens due to "optimizations" that avoid a cast and
12011201
// simply retype the node when using long type lclVar as an int.
12021202
// While loading the int in that case would work for this use of the lclVar, if it is
@@ -1210,13 +1210,6 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree)
12101210
assert(!varTypeIsGC(varDsc));
12111211
spillType = lclActualType;
12121212
}
1213-
#elif defined(TARGET_ARM64)
1214-
var_types targetType = unspillTree->gtType;
1215-
if (spillType != genActualType(varDsc->lvType) && !varTypeIsGC(spillType) && !varDsc->lvNormalizeOnLoad())
1216-
{
1217-
assert(!varTypeIsGC(varDsc));
1218-
spillType = genActualType(varDsc->lvType);
1219-
}
12201213
#elif defined(TARGET_ARM)
12211214
// No normalizing for ARM
12221215
#else
@@ -1465,7 +1458,8 @@ regNumber CodeGen::genConsumeReg(GenTree* tree)
14651458
LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()];
14661459
if (varDsc->GetRegNum() != REG_STK)
14671460
{
1468-
inst_Mov(tree->TypeGet(), tree->GetRegNum(), varDsc->GetRegNum(), /* canSkip */ true);
1461+
var_types regType = varDsc->GetRegisterType(lcl);
1462+
inst_Mov(regType, tree->GetRegNum(), varDsc->GetRegNum(), /* canSkip */ true);
14691463
}
14701464
}
14711465

src/coreclr/jit/compiler.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,11 +1016,20 @@ class LclVarDsc
10161016

10171017
var_types GetActualRegisterType() const;
10181018

1019-
bool IsEnregisterable() const
1019+
bool IsEnregisterableType() const
10201020
{
10211021
return GetRegisterType() != TYP_UNDEF;
10221022
}
10231023

1024+
bool IsEnregisterableLcl() const
1025+
{
1026+
if (lvDoNotEnregister)
1027+
{
1028+
return false;
1029+
}
1030+
return IsEnregisterableType();
1031+
}
1032+
10241033
bool CanBeReplacedWithItsField(Compiler* comp) const;
10251034

10261035
#ifdef DEBUG

src/coreclr/jit/jitconfigvalues.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,12 @@ CONFIG_INTEGER(JitSaveFpLrWithCalleeSavedRegisters, W("JitSaveFpLrWithCalleeSave
552552
#endif // defined(TARGET_ARM64)
553553
#endif // DEBUG
554554

555-
// Allow to enregister locals with struct type.
556-
CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 0)
555+
#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
556+
CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 1) // Allow to enregister locals with struct type.
557+
#else
558+
CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 0) // Don't allow to enregister locals with struct type
559+
// yet.
560+
#endif
557561

558562
#undef CONFIG_INTEGER
559563
#undef CONFIG_STRING

src/coreclr/jit/lclvars.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3493,7 +3493,7 @@ void Compiler::lvaSortByRefCount()
34933493
{
34943494
varDsc->lvTracked = 0;
34953495
}
3496-
else if ((varDsc->lvType == TYP_STRUCT) && !varDsc->lvRegStruct)
3496+
else if ((varDsc->lvType == TYP_STRUCT) && !varDsc->lvRegStruct && !compEnregStructLocals())
34973497
{
34983498
lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_IsStruct));
34993499
}

src/coreclr/jit/lower.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3160,7 +3160,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
31603160
#endif // !WINDOWS_AMD64_ABI
31613161
convertToStoreObj = false;
31623162
}
3163-
else if (!varDsc->IsEnregisterable())
3163+
else if (!varDsc->IsEnregisterableType())
31643164
{
31653165
convertToStoreObj = true;
31663166
}
@@ -3418,11 +3418,10 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
34183418
lclNum = fieldLclNum;
34193419
varDsc = comp->lvaGetDesc(lclNum);
34203420
}
3421-
else if (!varDsc->lvRegStruct && !varTypeIsEnregisterable(varDsc))
3422-
3421+
else if (varDsc->lvPromoted)
34233422
{
3424-
// TODO-1stClassStructs: We can no longer promote or enregister this struct,
3425-
// since it is referenced as a whole.
3423+
// TODO-1stClassStructs: We can no longer independently promote
3424+
// or enregister this struct, since it is referenced as a whole.
34263425
comp->lvaSetVarDoNotEnregister(lclNum DEBUGARG(Compiler::DNER_BlockOp));
34273426
}
34283427

@@ -3434,9 +3433,10 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
34343433
}
34353434
else
34363435
{
3437-
var_types lclVarType = varDsc->GetRegisterType(lclVar);
3436+
const var_types lclVarType = varDsc->GetRegisterType(lclVar);
34383437
assert(lclVarType != TYP_UNDEF);
3439-
lclVar->ChangeType(lclVarType);
3438+
const var_types actualType = genActualType(lclVarType);
3439+
lclVar->ChangeType(actualType);
34403440

34413441
if (varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(lclVarType))
34423442
{
@@ -4039,12 +4039,12 @@ void Lowering::InsertPInvokeMethodProlog()
40394039
GenTree* call = comp->gtNewHelperCallNode(CORINFO_HELP_INIT_PINVOKE_FRAME, TYP_I_IMPL, argList);
40404040

40414041
// some sanity checks on the frame list root vardsc
4042-
LclVarDsc* varDsc = &comp->lvaTable[comp->info.compLvFrameListRoot];
4042+
const unsigned lclNum = comp->info.compLvFrameListRoot;
4043+
const LclVarDsc* varDsc = comp->lvaGetDesc(lclNum);
40434044
noway_assert(!varDsc->lvIsParam);
40444045
noway_assert(varDsc->lvType == TYP_I_IMPL);
40454046

4046-
GenTree* store =
4047-
new (comp, GT_STORE_LCL_VAR) GenTreeLclVar(GT_STORE_LCL_VAR, TYP_I_IMPL, comp->info.compLvFrameListRoot);
4047+
GenTree* store = new (comp, GT_STORE_LCL_VAR) GenTreeLclVar(GT_STORE_LCL_VAR, TYP_I_IMPL, lclNum);
40484048
store->AsOp()->gtOp1 = call;
40494049
store->gtFlags |= GTF_VAR_DEF;
40504050

@@ -4065,6 +4065,7 @@ void Lowering::InsertPInvokeMethodProlog()
40654065
GenTreeLclFld(GT_STORE_LCL_FLD, TYP_I_IMPL, comp->lvaInlinedPInvokeFrameVar, callFrameInfo.offsetOfCallSiteSP);
40664066
storeSP->gtOp1 = PhysReg(REG_SPBASE);
40674067
storeSP->gtFlags |= GTF_VAR_DEF;
4068+
comp->lvaSetVarDoNotEnregister(comp->lvaInlinedPInvokeFrameVar DEBUGARG(Compiler::DNER_LocalField));
40684069

40694070
firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeSP));
40704071
DISPTREERANGE(firstBlockRange, storeSP);
@@ -6534,7 +6535,7 @@ void Lowering::ContainCheckRet(GenTreeUnOp* ret)
65346535
assert(varDsc->lvIsMultiRegRet || (varDsc->lvIsHfa() && varTypeIsValidHfaType(varDsc->lvType)));
65356536

65366537
// Mark var as contained if not enregisterable.
6537-
if (!varTypeIsEnregisterable(op1))
6538+
if (!varDsc->IsEnregisterableLcl())
65386539
{
65396540
if (!op1->IsMultiRegLclVar())
65406541
{

src/coreclr/jit/lowerxarch.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
269269
// address, not knowing that GT_IND is part of a block op that has containment restrictions.
270270
src->AsIndir()->Addr()->ClearContained();
271271
}
272+
else if (src->OperIs(GT_LCL_VAR))
273+
{
274+
// TODO-1stClassStructs: for now we can't work with STORE_BLOCK source in register.
275+
const unsigned srcLclNum = src->AsLclVar()->GetLclNum();
276+
comp->lvaSetVarDoNotEnregister(srcLclNum DEBUGARG(Compiler::DNER_BlockOp));
277+
}
272278

273279
if (blkNode->OperIs(GT_STORE_OBJ))
274280
{

src/coreclr/jit/lsra.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1490,7 +1490,7 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc)
14901490
// or enregistered, on x86 -- it is believed that we can enregister pinned (more properly, "pinning")
14911491
// references when using the general GC encoding.
14921492
unsigned lclNum = (unsigned)(varDsc - compiler->lvaTable);
1493-
if (varDsc->lvAddrExposed || !varDsc->IsEnregisterable() ||
1493+
if (varDsc->lvAddrExposed || !varDsc->IsEnregisterableType() ||
14941494
(!compiler->compEnregStructLocals() && (varDsc->lvType == TYP_STRUCT)))
14951495
{
14961496
#ifdef DEBUG

0 commit comments

Comments
 (0)