Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4355,16 +4355,10 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
#endif // defined(UNIX_AMD64_ABI)

noway_assert(varDsc->lvIsParam && varDsc->lvIsRegArg);
#ifndef TARGET_64BIT
#ifndef TARGET_ARM
// Right now we think that incoming arguments are not pointer sized. When we eventually
// understand the calling convention, this still won't be true. But maybe we'll have a better
// idea of how to ignore it.

// On Arm, a long can be passed in register
noway_assert(genTypeSize(genActualType(varDsc->TypeGet())) == TARGET_POINTER_SIZE);
#endif
#endif // TARGET_64BIT
#ifdef TARGET_X86
// On x86 we don't enregister args that are not pointer sized.
noway_assert(genTypeSize(varDsc->GetActualRegisterType()) == TARGET_POINTER_SIZE);
#endif // TARGET_X86

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

Expand Down
16 changes: 5 additions & 11 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1191,12 +1191,12 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree)
assert(spillType != TYP_UNDEF);

// TODO-Cleanup: The following code could probably be further merged and cleaned up.
#ifdef TARGET_XARCH
#if defined(TARGET_XARCH) || defined(TARGET_ARM64)
// Load local variable from its home location.
// In most cases the tree type will indicate the correct type to use for the load.
// However, if it is NOT a normalizeOnLoad lclVar (i.e. NOT a small int that always gets
// widened when loaded into a register), and its size is not the same as genActualType of
// the type of the lclVar, then we need to change the type of the tree node when loading.
// widened when loaded into a register), and its size is not the same as the actual register type
// of the lclVar, then we need to change the type of the tree node when loading.
// This situation happens due to "optimizations" that avoid a cast and
// simply retype the node when using long type lclVar as an int.
// While loading the int in that case would work for this use of the lclVar, if it is
Expand All @@ -1210,13 +1210,6 @@ void CodeGen::genUnspillRegIfNeeded(GenTree* tree)
assert(!varTypeIsGC(varDsc));
spillType = lclActualType;
}
#elif defined(TARGET_ARM64)
var_types targetType = unspillTree->gtType;
if (spillType != genActualType(varDsc->lvType) && !varTypeIsGC(spillType) && !varDsc->lvNormalizeOnLoad())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could you also update the comment about to genActualType GetActualRegisterType()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, what would you like to add there? now it looks like:

//------------------------------------------------------------------------
// GetActualRegisterType: Determine an actual register type for this local var.
//
// Return Value:
// TYP_UNDEF if the layout is not enregistrable, the register type otherwise.
//
var_types LclVarDsc::GetActualRegisterType() const

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry - didn't notice your comment.

I was suggesting to update the comment right above where you changed the code:

// Load local variable from its home location.
// In most cases the tree type will indicate the correct type to use for the load.
// However, if it is NOT a normalizeOnLoad lclVar (i.e. NOT a small int that always gets
// widened when loaded into a register), and its size is not the same as genActualType of
// the type of the lclVar, then we need to change the type of the tree node when loading.
// This situation happens due to "optimizations" that avoid a cast and

and its size is not the same as genActualType of the type of the lclVar,
and its size is not the same as actual register type,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, fixed

{
assert(!varTypeIsGC(varDsc));
spillType = genActualType(varDsc->lvType);
}
#elif defined(TARGET_ARM)
// No normalizing for ARM
#else
Expand Down Expand Up @@ -1465,7 +1458,8 @@ regNumber CodeGen::genConsumeReg(GenTree* tree)
LclVarDsc* varDsc = &compiler->lvaTable[lcl->GetLclNum()];
if (varDsc->GetRegNum() != REG_STK)
{
inst_Mov(tree->TypeGet(), tree->GetRegNum(), varDsc->GetRegNum(), /* canSkip */ true);
var_types regType = varDsc->GetRegisterType(lcl);
inst_Mov(regType, tree->GetRegNum(), varDsc->GetRegNum(), /* canSkip */ true);
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1016,11 +1016,20 @@ class LclVarDsc

var_types GetActualRegisterType() const;

bool IsEnregisterable() const
bool IsEnregisterableType() const
{
return GetRegisterType() != TYP_UNDEF;
}

bool IsEnregisterableLcl() const
{
if (lvDoNotEnregister)
{
return false;
}
return IsEnregisterableType();
}

bool CanBeReplacedWithItsField(Compiler* comp) const;

#ifdef DEBUG
Expand Down
8 changes: 6 additions & 2 deletions src/coreclr/jit/jitconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,12 @@ CONFIG_INTEGER(JitSaveFpLrWithCalleeSavedRegisters, W("JitSaveFpLrWithCalleeSave
#endif // defined(TARGET_ARM64)
#endif // DEBUG

// Allow to enregister locals with struct type.
CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 0)
#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 1) // Allow to enregister locals with struct type.
#else
CONFIG_INTEGER(JitEnregStructLocals, W("JitEnregStructLocals"), 0) // Don't allow to enregister locals with struct type
// yet.
#endif

#undef CONFIG_INTEGER
#undef CONFIG_STRING
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3482,7 +3482,7 @@ void Compiler::lvaSortByRefCount()
{
varDsc->lvTracked = 0;
}
else if ((varDsc->lvType == TYP_STRUCT) && !varDsc->lvRegStruct)
else if ((varDsc->lvType == TYP_STRUCT) && !varDsc->lvRegStruct && !compEnregStructLocals())
{
lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_IsStruct));
}
Expand Down
23 changes: 12 additions & 11 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3160,7 +3160,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
#endif // !WINDOWS_AMD64_ABI
convertToStoreObj = false;
}
else if (!varDsc->IsEnregisterable())
else if (!varDsc->IsEnregisterableType())
{
convertToStoreObj = true;
}
Expand Down Expand Up @@ -3418,11 +3418,10 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
lclNum = fieldLclNum;
varDsc = comp->lvaGetDesc(lclNum);
}
else if (!varDsc->lvRegStruct && !varTypeIsEnregisterable(varDsc))

else if (varDsc->lvPromoted)
{
// TODO-1stClassStructs: We can no longer promote or enregister this struct,
// since it is referenced as a whole.
// TODO-1stClassStructs: We can no longer independently promote
// or enregister this struct, since it is referenced as a whole.
comp->lvaSetVarDoNotEnregister(lclNum DEBUGARG(Compiler::DNER_BlockOp));
}

Expand All @@ -3434,9 +3433,10 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret)
}
else
{
var_types lclVarType = varDsc->GetRegisterType(lclVar);
const var_types lclVarType = varDsc->GetRegisterType(lclVar);
assert(lclVarType != TYP_UNDEF);
lclVar->ChangeType(lclVarType);
const var_types actualType = genActualType(lclVarType);
lclVar->ChangeType(actualType);

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

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

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

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

firstBlockRange.InsertBefore(insertionPoint, LIR::SeqTree(comp, storeSP));
DISPTREERANGE(firstBlockRange, storeSP);
Expand Down Expand Up @@ -6524,7 +6525,7 @@ void Lowering::ContainCheckRet(GenTreeUnOp* ret)
assert(varDsc->lvIsMultiRegRet || (varDsc->lvIsHfa() && varTypeIsValidHfaType(varDsc->lvType)));

// Mark var as contained if not enregisterable.
if (!varTypeIsEnregisterable(op1))
if (!varDsc->IsEnregisterableLcl())
{
if (!op1->IsMultiRegLclVar())
{
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/lowerxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ void Lowering::LowerBlockStore(GenTreeBlk* blkNode)
// address, not knowing that GT_IND is part of a block op that has containment restrictions.
src->AsIndir()->Addr()->ClearContained();
}
else if (src->OperIs(GT_LCL_VAR))
{
// TODO-1stClassStructs: for now we can't work with STORE_BLOCK source in register.
const unsigned srcLclNum = src->AsLclVar()->GetLclNum();
comp->lvaSetVarDoNotEnregister(srcLclNum DEBUGARG(Compiler::DNER_BlockOp));
}

if (blkNode->OperIs(GT_STORE_OBJ))
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lsra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1490,7 +1490,7 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc)
// or enregistered, on x86 -- it is believed that we can enregister pinned (more properly, "pinning")
// references when using the general GC encoding.
unsigned lclNum = (unsigned)(varDsc - compiler->lvaTable);
if (varDsc->lvAddrExposed || !varDsc->IsEnregisterable() ||
if (varDsc->lvAddrExposed || !varDsc->IsEnregisterableType() ||
(!compiler->compEnregStructLocals() && (varDsc->lvType == TYP_STRUCT)))
{
#ifdef DEBUG
Expand Down