Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
4 changes: 2 additions & 2 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1781,7 +1781,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo()
// We furthermore allocate the "monitor acquired" bool between PSP and
// the saved registers because this is part of the EnC header.
// Note that OSR methods reuse the monitor bool created by tier 0.
saveRegsPlusPSPSize += compiler->lvaLclSize(compiler->lvaMonAcquired);
saveRegsPlusPSPSize += compiler->lvaLclStackHomeSize(compiler->lvaMonAcquired);
}

unsigned const saveRegsPlusPSPSizeAligned = roundUp(saveRegsPlusPSPSize, STACK_ALIGN);
Expand Down Expand Up @@ -2966,7 +2966,7 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
if (lclNode->IsMultiReg())
{
// This is the case of storing to a multi-reg HFA local from a fixed-size SIMD type.
assert(varTypeIsSIMD(data) && varDsc->lvIsHfa() && (varDsc->GetHfaType() == TYP_FLOAT));
assert(varTypeIsSIMD(data));
regNumber operandReg = genConsumeReg(data);
unsigned int regCount = varDsc->lvFieldCnt;
for (unsigned i = 0; i < regCount; ++i)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
if (treeNode->putInIncomingArgArea())
{
varNumOut = getFirstArgWithStackSlot();
argOffsetMax = compiler->compArgSize;
argOffsetMax = compiler->lvaParameterStackSize;
#if FEATURE_FASTTAILCALL
// This must be a fast tail call.
assert(treeNode->gtCall->IsFastTailCall());
Expand Down
35 changes: 11 additions & 24 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3820,7 +3820,7 @@ void CodeGen::genCheckUseBlockInit()
{
// Var is on the stack at entry.
initStkLclCnt +=
roundUp(compiler->lvaLclSize(varNum), TARGET_POINTER_SIZE) / sizeof(int);
roundUp(compiler->lvaLclStackHomeSize(varNum), TARGET_POINTER_SIZE) / sizeof(int);
counted = true;
}
}
Expand Down Expand Up @@ -3869,7 +3869,8 @@ void CodeGen::genCheckUseBlockInit()

if (!counted)
{
initStkLclCnt += roundUp(compiler->lvaLclSize(varNum), TARGET_POINTER_SIZE) / sizeof(int);
initStkLclCnt +=
roundUp(compiler->lvaLclStackHomeSize(varNum), TARGET_POINTER_SIZE) / sizeof(int);
counted = true;
}
}
Expand Down Expand Up @@ -4130,7 +4131,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg,
(varDsc->lvExactSize() >= TARGET_POINTER_SIZE))
{
// We only initialize the GC variables in the TYP_STRUCT
const unsigned slots = (unsigned)compiler->lvaLclSize(varNum) / REGSIZE_BYTES;
const unsigned slots = (unsigned)compiler->lvaLclStackHomeSize(varNum) / REGSIZE_BYTES;
ClassLayout* layout = varDsc->GetLayout();

for (unsigned i = 0; i < slots; i++)
Expand All @@ -4147,7 +4148,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg,
regNumber zeroReg = genGetZeroReg(initReg, pInitRegZeroed);

// zero out the whole thing rounded up to a single stack slot size
unsigned lclSize = roundUp(compiler->lvaLclSize(varNum), (unsigned)sizeof(int));
unsigned lclSize = roundUp(compiler->lvaLclStackHomeSize(varNum), (unsigned)sizeof(int));
unsigned i;
for (i = 0; i + REGSIZE_BYTES <= lclSize; i += REGSIZE_BYTES)
{
Expand Down Expand Up @@ -4589,21 +4590,6 @@ void CodeGen::genReportGenericContextArg(regNumber initReg, bool* pInitRegZeroed
}
else
{
if (isFramePointerUsed())
{
#if defined(TARGET_ARM)
// GetStackOffset() is always valid for incoming stack-arguments, even if the argument
// will become enregistered.
// On Arm compiler->compArgSize doesn't include r11 and lr sizes and hence we need to add 2*REGSIZE_BYTES
noway_assert((2 * REGSIZE_BYTES <= varDsc->GetStackOffset()) &&
(size_t(varDsc->GetStackOffset()) < compiler->compArgSize + 2 * REGSIZE_BYTES));
#else
// GetStackOffset() is always valid for incoming stack-arguments, even if the argument
// will become enregistered.
noway_assert((0 < varDsc->GetStackOffset()) && (size_t(varDsc->GetStackOffset()) < compiler->compArgSize));
#endif
}
Comment on lines -4592 to -4605
Copy link
Member Author

Choose a reason for hiding this comment

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

We could replace compArgSize here as well, but the assert did not look useful to me.


// We will just use the initReg since it is an available register
// and we are probably done using it anyway...
reg = initReg;
Expand Down Expand Up @@ -5212,7 +5198,7 @@ void CodeGen::genFnProlog()
}

signed int loOffs = varDsc->GetStackOffset();
signed int hiOffs = varDsc->GetStackOffset() + compiler->lvaLclSize(varNum);
signed int hiOffs = varDsc->GetStackOffset() + compiler->lvaLclStackHomeSize(varNum);

/* We need to know the offset range of tracked stack GC refs */
/* We assume that the GC reference can be anywhere in the TYP_STRUCT */
Expand Down Expand Up @@ -5669,7 +5655,7 @@ void CodeGen::genFnProlog()
{
// The last slot is reserved for ICodeManager::FixContext(ppEndRegion)
unsigned filterEndOffsetSlotOffs =
compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE;
compiler->lvaLclStackHomeSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE;

// Zero out the slot for nesting level 0
unsigned firstSlotOffs = filterEndOffsetSlotOffs - TARGET_POINTER_SIZE;
Expand Down Expand Up @@ -7880,12 +7866,13 @@ void CodeGen::genMultiRegStoreToLocal(GenTreeLclVar* lclNode)
offset += genTypeSize(srcType);

#ifdef DEBUG
unsigned stackHomeSize = compiler->lvaLclStackHomeSize(lclNum);
#ifdef TARGET_64BIT
assert(offset <= varDsc->lvSize());
assert(offset <= stackHomeSize);
#else // !TARGET_64BIT
if (varTypeIsStruct(varDsc))
{
assert(offset <= varDsc->lvSize());
assert(offset <= stackHomeSize);
}
else
{
Expand Down Expand Up @@ -8200,7 +8187,7 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)

assert(varDsc->lvOnFrame);

unsigned int size = compiler->lvaLclSize(varNum);
unsigned int size = compiler->lvaLclStackHomeSize(varNum);
if ((size / TARGET_POINTER_SIZE) > 16)
{
// This will require more than 16 instructions, switch to rep stosd/memset call.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1893,7 +1893,7 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk, unsigned outArg
// We can't write beyond the arg area unless this is a tail call, in which case we use
// the first stack arg as the base of the incoming arg area.
#ifdef DEBUG
unsigned areaSize = compiler->lvaLclSize(outArgVarNum);
unsigned areaSize = compiler->lvaLclStackHomeSize(outArgVarNum);
#if FEATURE_FASTTAILCALL
if (putArgStk->gtCall->IsFastTailCall())
{
Expand Down
7 changes: 3 additions & 4 deletions src/coreclr/jit/codegenloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4841,8 +4841,8 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
assert(varDsc->lvType == TYP_STRUCT);
assert(varDsc->lvOnFrame && !varDsc->lvRegister);

srcSize = varDsc->lvSize(); // This yields the roundUp size, but that is fine
// as that is how much stack is allocated for this LclVar
srcSize = compiler->lvaLclStackHomeSize(varNode->GetLclNum());

layout = varDsc->GetLayout();
}
else // we must have a GT_BLK
Expand Down Expand Up @@ -4870,8 +4870,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
if (varNode != nullptr)
{
// If we have a varNode, even if it was casted using `OBJ`, we can read its original memory size.
const LclVarDsc* varDsc = compiler->lvaGetDesc(varNode);
const unsigned varStackSize = varDsc->lvSize();
const unsigned varStackSize = compiler->lvaLclStackHomeSize(varNode->GetLclNum());
if (varStackSize >= srcSize)
{
srcSize = varStackSize;
Expand Down
14 changes: 6 additions & 8 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,8 @@ BasicBlock* CodeGen::genCallFinally(BasicBlock* block)

// The last slot is reserved for ICodeManager::FixContext(ppEndRegion)
unsigned filterEndOffsetSlotOffs;
filterEndOffsetSlotOffs = (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);
filterEndOffsetSlotOffs =
(unsigned)(compiler->lvaLclStackHomeSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);

unsigned curNestingSlotOffs;
curNestingSlotOffs = (unsigned)(filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE));
Expand Down Expand Up @@ -2210,10 +2211,9 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)

// The last slot is reserved for ICodeManager::FixContext(ppEndRegion)
unsigned filterEndOffsetSlotOffs;
PREFIX_ASSUME(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) > TARGET_POINTER_SIZE); // below doesn't
// underflow.
assert(compiler->lvaLclStackHomeSize(compiler->lvaShadowSPslotsVar) > TARGET_POINTER_SIZE);
filterEndOffsetSlotOffs =
(unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);
(unsigned)(compiler->lvaLclStackHomeSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);

size_t curNestingSlotOffs;
curNestingSlotOffs = filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE);
Expand Down Expand Up @@ -10752,10 +10752,8 @@ void CodeGen::genFnEpilog(BasicBlock* block)

if (fCalleePop)
{
noway_assert(compiler->compArgSize >= intRegState.rsCalleeRegArgCount * REGSIZE_BYTES);
stkArgSize = compiler->compArgSize - intRegState.rsCalleeRegArgCount * REGSIZE_BYTES;

noway_assert(compiler->compArgSize < 0x10000); // "ret" only has 2 byte operand
stkArgSize = compiler->lvaParameterStackSize;
noway_assert(stkArgSize < 0x10000); // "ret" only has 2 byte operand
}

#ifdef UNIX_X86_ABI
Expand Down
23 changes: 10 additions & 13 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ class LclVarDsc
#endif // FEATURE_HFA_FIELDS_PRESENT

#ifdef DEBUG
// TODO-Cleanup: See the note on lvSize() - this flag is only in use by asserts that are checking for struct
// TODO-Cleanup: this flag is only in use by asserts that are checking for struct
// types, and is needed because of cases where TYP_STRUCT is bashed to an integral type.
// Consider cleaning this up so this workaround is not required.
unsigned char lvUnusedStruct : 1; // All references to this promoted struct are through its field locals.
Expand Down Expand Up @@ -1118,9 +1118,6 @@ class LclVarDsc
}

unsigned lvExactSize() const;
unsigned lvSize() const;

size_t lvArgStackSize() const;

unsigned lvSlotNum; // original slot # (if remapped)

Expand Down Expand Up @@ -4312,7 +4309,7 @@ class Compiler
return varNum;
}

unsigned lvaLclSize(unsigned varNum);
unsigned lvaLclStackHomeSize(unsigned varNum);
unsigned lvaLclExactSize(unsigned varNum);

bool lvaHaveManyLocals(float percent = 1.0f) const;
Expand Down Expand Up @@ -4437,6 +4434,7 @@ class Compiler
bool ShouldPromoteStructVar(unsigned lclNum);
void PromoteStructVar(unsigned lclNum);
void SortStructFields();
bool IsArmHfaParameter(unsigned lclNum);

var_types TryPromoteValueClassAsPrimitive(CORINFO_TYPE_LAYOUT_NODE* treeNodes, size_t maxTreeNodes, size_t index);
void AdvanceSubTree(CORINFO_TYPE_LAYOUT_NODE* treeNodes, size_t maxTreeNodes, size_t* index);
Expand All @@ -4457,27 +4455,26 @@ class Compiler
bool lvaIsGCTracked(const LclVarDsc* varDsc);

#if defined(FEATURE_SIMD)
bool lvaMapSimd12ToSimd16(const LclVarDsc* varDsc)
bool lvaMapSimd12ToSimd16(unsigned varNum)
{
assert(varDsc->lvType == TYP_SIMD12);
LclVarDsc* varDsc = lvaGetDesc(varNum);
assert(varDsc->TypeGet() == TYP_SIMD12);

#if defined(TARGET_64BIT)
assert(compAppleArm64Abi() || varDsc->lvSize() == 16);
#endif // defined(TARGET_64BIT)
unsigned stackHomeSize = lvaLclStackHomeSize(varNum);

// We make local variable SIMD12 types 16 bytes instead of just 12.
// lvSize() will return 16 bytes for SIMD12, even for fields.
// lvaLclStackHomeSize() will return 16 bytes for SIMD12, even for fields.
// However, we can't do that mapping if the var is a dependently promoted struct field.
// Such a field must remain its exact size within its parent struct unless it is a single
// field *and* it is the only field in a struct of 16 bytes.
if (varDsc->lvSize() != 16)
if (stackHomeSize != 16)
{
return false;
}
if (lvaIsFieldOfDependentlyPromotedStruct(varDsc))
{
LclVarDsc* parentVarDsc = lvaGetDesc(varDsc->lvParentLcl);
return (parentVarDsc->lvFieldCnt == 1) && (parentVarDsc->lvSize() == 16);
return (parentVarDsc->lvFieldCnt == 1) && (lvaLclStackHomeSize(varDsc->lvParentLcl) == 16);
}
return true;
}
Expand Down
24 changes: 18 additions & 6 deletions src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4085,6 +4085,17 @@ inline bool Compiler::impIsPrimitive(CorInfoType jitType)

inline Compiler::lvaPromotionType Compiler::lvaGetPromotionType(const LclVarDsc* varDsc)
{
// TODO-Review: Sometimes we get called on ARM with HFA struct variables that have been promoted,
// where the struct itself is no longer used because all access is via its member fields.
// When that happens, the struct is marked as unused and its type has been changed to
// TYP_INT (to keep the GC tracking code from looking at it).
// See Compiler::raAssignVars() for details. For example:
// N002 ( 4, 3) [00EA067C] ------------- return struct $346
// N001 ( 3, 2) [00EA0628] ------------- lclVar struct(U) V03 loc2
// float V03.f1 (offs=0x00) -> V12 tmp7
// f8 (last use) (last use) $345
// Here, the "struct(U)" shows that the "V03 loc2" variable is unused. Not shown is that V03
// is now TYP_INT in the local variable table. It's not really unused, because it's in the tree.
assert(!varDsc->lvPromoted || varTypeIsPromotable(varDsc) || varDsc->lvUnusedStruct);

if (!varDsc->lvPromoted)
Expand Down Expand Up @@ -4322,19 +4333,20 @@ bool Compiler::fgVarNeedsExplicitZeroInit(unsigned varNum, bool bbInALoop, bool
return false;
}

// Below conditions guarantee block initialization, which will initialize
// all struct fields. If the logic for block initialization in CodeGen::genCheckUseBlockInit()
// changes, these conditions need to be updated.
// Below conditions guarantee block initialization, which will initialize
// all struct fields. If the logic for block initialization in CodeGen::genCheckUseBlockInit()
// changes, these conditions need to be updated.
unsigned stackHomeSize = lvaLclStackHomeSize(varNum);
#ifdef TARGET_64BIT
#if defined(TARGET_AMD64)
// We can clear using aligned SIMD so the threshold is lower,
// and clears in order which is better for auto-prefetching
if (roundUp(varDsc->lvSize(), TARGET_POINTER_SIZE) / sizeof(int) > 4)
if (roundUp(stackHomeSize, TARGET_POINTER_SIZE) / sizeof(int) > 4)
#else // !defined(TARGET_AMD64)
if (roundUp(varDsc->lvSize(), TARGET_POINTER_SIZE) / sizeof(int) > 8)
if (roundUp(stackHomeSize, TARGET_POINTER_SIZE) / sizeof(int) > 8)
#endif
#else
if (roundUp(varDsc->lvSize(), TARGET_POINTER_SIZE) / sizeof(int) > 4)
if (roundUp(stackHomeSize, TARGET_POINTER_SIZE) / sizeof(int) > 4)
#endif
{
return false;
Expand Down
7 changes: 3 additions & 4 deletions src/coreclr/jit/gcencode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1588,10 +1588,9 @@ size_t GCInfo::gcInfoBlockHdrSave(
assert(header->revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET);
}

assert((compiler->compArgSize & 0x3) == 0);

size_t argCount =
(compiler->compArgSize - (compiler->codeGen->intRegState.rsCalleeRegArgCount * REGSIZE_BYTES)) / REGSIZE_BYTES;
assert(compiler->lvaParameterStackSize ==
(compiler->compArgSize - compiler->codeGen->intRegState.rsCalleeRegArgCount * REGSIZE_BYTES));
size_t argCount = compiler->lvaParameterStackSize / REGSIZE_BYTES;
assert(argCount <= MAX_USHORT_SIZE_T);
header->argCount = static_cast<unsigned short>(argCount);

Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27052,9 +27052,9 @@ GenTree* Compiler::gtNewSimdWithElementNode(
//
GenTreeFieldList* Compiler::gtConvertTableOpToFieldList(GenTree* op, unsigned fieldCount)
{
LclVarDsc* opVarDsc = lvaGetDesc(op->AsLclVar());
unsigned lclNum = lvaGetLclNum(opVarDsc);
unsigned fieldSize = opVarDsc->lvSize() / fieldCount;
unsigned lclNum = op->AsLclVar()->GetLclNum();
LclVarDsc* opVarDsc = lvaGetDesc(lclNum);
unsigned fieldSize = opVarDsc->lvExactSize() / fieldCount;
var_types fieldType = Compiler::getSIMDTypeForSize(fieldSize);

GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList();
Expand Down Expand Up @@ -27083,9 +27083,9 @@ GenTreeFieldList* Compiler::gtConvertTableOpToFieldList(GenTree* op, unsigned fi
//
GenTreeFieldList* Compiler::gtConvertParamOpToFieldList(GenTree* op, unsigned fieldCount, CORINFO_CLASS_HANDLE clsHnd)
{
LclVarDsc* opVarDsc = lvaGetDesc(op->AsLclVar());
unsigned lclNum = lvaGetLclNum(opVarDsc);
unsigned fieldSize = opVarDsc->lvSize() / fieldCount;
unsigned lclNum = op->AsLclVar()->GetLclNum();
LclVarDsc* opVarDsc = lvaGetDesc(lclNum);
unsigned fieldSize = opVarDsc->lvExactSize() / fieldCount;
GenTreeFieldList* fieldList = new (this, GT_FIELD_LIST) GenTreeFieldList();
int offset = 0;
unsigned sizeBytes = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6757,7 +6757,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
VAR_ST_VALID:

/* if it is a struct store, make certain we don't overflow the buffer */
assert(lclTyp != TYP_STRUCT || lvaLclSize(lclNum) >= info.compCompHnd->getClassSize(clsHnd));
assert(lclTyp != TYP_STRUCT || lvaLclStackHomeSize(lclNum) >= info.compCompHnd->getClassSize(clsHnd));

if (lvaTable[lclNum].lvNormalizeOnLoad())
{
Expand Down
Loading
Loading