Turn these into functions.
}
if ((varDsc->TypeGet() == TYP_STRUCT) && !compiler->info.compInitMem &&
- (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
+ (varDsc->lvExactSize() >= TARGET_POINTER_SIZE))
{
// We only initialize the GC variables in the TYP_STRUCT
const unsigned slots = (unsigned)compiler->lvaLclSize(varNum) / REGSIZE_BYTES;
unsigned char lvLRACandidate : 1; // Tracked for linear scan register allocation purposes
#ifdef FEATURE_SIMD
- // Note that both SIMD vector args and locals are marked as lvSIMDType = true, but the
- // type of an arg node is TYP_BYREF and a local node is TYP_SIMD*.
- unsigned char lvSIMDType : 1; // This is a SIMD struct
unsigned char lvUsedInSIMDIntrinsic : 1; // This tells lclvar is used for simd intrinsic
unsigned char lvSimdBaseJitType : 5; // Note: this only packs because CorInfoType has less than 32 entries
assert(varTypeIsStruct(lvType));
unsigned slots = 0;
#ifdef TARGET_ARM
- slots = lvExactSize / sizeof(float);
+ slots = lvExactSize() / sizeof(float);
assert(slots <= 8);
#elif defined(TARGET_ARM64)
switch (GetLvHfaElemKind())
assert(!"lvHfaSlots called for non-HFA");
break;
case CORINFO_HFA_ELEM_FLOAT:
- assert((lvExactSize % 4) == 0);
- slots = lvExactSize >> 2;
+ assert((lvExactSize() % 4) == 0);
+ slots = lvExactSize() >> 2;
break;
case CORINFO_HFA_ELEM_DOUBLE:
case CORINFO_HFA_ELEM_VECTOR64:
- assert((lvExactSize % 8) == 0);
- slots = lvExactSize >> 3;
+ assert((lvExactSize() % 8) == 0);
+ slots = lvExactSize() >> 3;
break;
case CORINFO_HFA_ELEM_VECTOR128:
- assert((lvExactSize % 16) == 0);
- slots = lvExactSize >> 4;
+ assert((lvExactSize() % 16) == 0);
+ slots = lvExactSize() >> 4;
break;
default:
unreached();
#endif // FEATURE_MULTIREG_ARGS
#ifdef FEATURE_SIMD
- // Is this is a SIMD struct?
- bool lvIsSIMDType() const
- {
- return lvSIMDType;
- }
-
// Is this is a SIMD struct which is used for SIMD intrinsic?
bool lvIsUsedInSIMDIntrinsic() const
{
lvStkOffs = offset;
}
- // TODO-Cleanup: Remove this in favor of GetLayout()->Size/genTypeSize(lvType).
- unsigned lvExactSize; // (exact) size of a STRUCT/SIMD/BLK local in bytes.
-
+ unsigned lvExactSize() const;
unsigned lvSize() const;
size_t lvArgStackSize() const;
assert(varTypeIsStruct(lvType));
assert((m_layout == nullptr) || (m_layout->IsBlockLayout() && (m_layout->GetSize() <= layout->GetSize())));
assert(layout->IsBlockLayout());
- m_layout = layout;
- lvExactSize = layout->GetSize();
+ m_layout = layout;
}
SsaDefArray<LclSsaVarDsc> lvPerSsaData;
bool lvaMapSimd12ToSimd16(const LclVarDsc* varDsc)
{
assert(varDsc->lvType == TYP_SIMD12);
- assert(varDsc->lvExactSize == 12);
#if defined(TARGET_64BIT)
assert(compMacOsArm64Abi() || varDsc->lvSize() == 16);
// Returns true if the lclVar is an opaque SIMD type.
bool isOpaqueSIMDLclVar(const LclVarDsc* varDsc) const
{
- if (!varDsc->lvSIMDType)
+ if (!varTypeIsSIMD(varDsc))
{
return false;
}
#endif // FEATURE_HW_INTRINSICS
private:
- // These routines need not be enclosed under FEATURE_SIMD since lvIsSIMDType()
- // is defined for both FEATURE_SIMD and !FEATURE_SIMD appropriately. The use
- // of this routines also avoids the need of #ifdef FEATURE_SIMD specific code.
-
- // Is this var is of type simd struct?
- bool lclVarIsSIMDType(unsigned varNum)
- {
- return lvaGetDesc(varNum)->lvIsSIMDType();
- }
-
// Returns true if the TYP_SIMD locals on stack are aligned at their
// preferred byte boundary specified by getSIMDTypeAlignment().
//
bool isSIMDTypeLocalAligned(unsigned varNum)
{
#if defined(FEATURE_SIMD) && ALIGN_SIMD_TYPES
- if (lclVarIsSIMDType(varNum) && lvaTable[varNum].lvType != TYP_BYREF)
+ LclVarDsc* lcl = lvaGetDesc(varNum);
+ if (varTypeIsSIMD(lcl))
{
// TODO-Cleanup: Can't this use the lvExactSize on the varDsc?
- int alignment = getSIMDTypeAlignment(lvaTable[varNum].lvType);
+ int alignment = getSIMDTypeAlignment(lcl->TypeGet());
if (alignment <= STACK_ALIGN)
{
bool rbpBased;
// If this is a TYP_STRUCT, handle its GC pointers.
// Note that the enregisterable struct types cannot have GC pointers in them.
if ((varDsc->TypeGet() == TYP_STRUCT) && varDsc->GetLayout()->HasGCPtr() && varDsc->lvOnFrame &&
- (varDsc->lvExactSize >= TARGET_POINTER_SIZE))
+ (varDsc->lvExactSize() >= TARGET_POINTER_SIZE))
{
ClassLayout* layout = varDsc->GetLayout();
unsigned slots = layout->GetSlotCount();
{
varDsc->lvType = dstTyp = genActualType(valTyp);
- if (varTypeIsStruct(dstTyp))
+ if (dstTyp == TYP_STRUCT)
{
- if (varTypeIsSIMD(dstTyp))
- {
- varDsc->lvExactSize = genTypeSize(dstTyp);
-#ifdef FEATURE_SIMD
- varDsc->lvSIMDType = 1;
-#endif
- }
- else
- {
- lvaSetStruct(tmp, val->GetLayout(this), false);
- }
+ lvaSetStruct(tmp, val->GetLayout(this), false);
}
}
-#if FEATURE_SIMD
- if (varTypeIsSIMD(dstTyp))
- {
- varDsc->lvSIMDType = 1;
- }
-#endif
-
#ifdef DEBUG
// Make sure the actual types match.
if (genActualType(valTyp) != genActualType(dstTyp))
//
bool GenTree::IsPartialLclFld(Compiler* comp)
{
- return OperIs(GT_LCL_FLD, GT_STORE_LCL_FLD) && (comp->lvaGetDesc(AsLclFld())->lvExactSize != AsLclFld()->GetSize());
+ return OperIs(GT_LCL_FLD, GT_STORE_LCL_FLD) &&
+ (comp->lvaGetDesc(AsLclFld())->lvExactSize() != AsLclFld()->GetSize());
}
//------------------------------------------------------------------------
shadowVarDsc->lvType = type;
#ifdef FEATURE_SIMD
- shadowVarDsc->lvSIMDType = varDsc->lvSIMDType;
shadowVarDsc->lvUsedInSIMDIntrinsic = varDsc->lvUsedInSIMDIntrinsic;
- if (varDsc->lvSIMDType)
+ if (varTypeIsSIMD(varDsc))
{
CorInfoType simdBaseJitType = varDsc->GetSimdBaseJitType();
shadowVarDsc->SetSimdBaseJitType(simdBaseJitType);
if (type == TYP_STRUCT)
{
assert(shadowVarDsc->GetLayout() != nullptr);
- assert(shadowVarDsc->lvExactSize != 0);
+ assert(shadowVarDsc->lvExactSize() != 0);
opAssign = gtNewBlkOpNode(dst, src);
}
else
// Increase size of lvaNewObjArrayArgs to be the largest size needed to hold 'numArgs' integers
// for our call to CORINFO_HELP_NEW_MDARR.
- if (dimensionsSize > lvaTable[lvaNewObjArrayArgs].lvExactSize)
+ if (dimensionsSize > lvaTable[lvaNewObjArrayArgs].lvExactSize())
{
lvaTable[lvaNewObjArrayArgs].GrowBlockLayout(typGetBlkLayout(dimensionsSize));
}
{
inlCurArgInfo->argIsByRefToStructLocal = true;
#ifdef FEATURE_SIMD
- if (varDsc->lvSIMDType)
+ if (varTypeIsSIMD(varDsc))
{
pInlineInfo->hasSIMDTypeArgLocalOrReturn = true;
}
defFlag = GTF_VAR_DEF;
if ((val.Offset() != 0) ||
- (varDsc->lvExactSize != m_compiler->typGetObjLayout(callUser->gtRetClsHnd)->GetSize()))
+ (varDsc->lvExactSize() != m_compiler->typGetObjLayout(callUser->gtRetClsHnd)->GetSize()))
{
defFlag |= GTF_VAR_USEASG;
}
LclVarDsc* fieldVarDsc = compiler->lvaGetDesc(varNum);
fieldVarDsc->lvType = pFieldInfo->fldType;
- fieldVarDsc->lvExactSize = pFieldInfo->fldSize;
fieldVarDsc->lvIsStructField = true;
fieldVarDsc->lvFldOffset = pFieldInfo->fldOffset;
fieldVarDsc->lvFldOrdinal = pFieldInfo->fldOrdinal;
#ifdef FEATURE_SIMD
if (varTypeIsSIMD(pFieldInfo->fldType))
{
- // Set size to zero so that lvaSetStruct will appropriately set the SIMD-relevant fields.
- fieldVarDsc->lvExactSize = 0;
compiler->lvaSetStruct(varNum, pFieldInfo->fldTypeHnd, false);
// We will not recursively promote this, so mark it as 'lvRegStruct' (note that we wouldn't
// be promoting this if we didn't think it could be enregistered.
CORINFO_CLASS_HANDLE clsHnd = varDsc->GetLayout()->GetClassHandle();
structPassingKind howToPassStruct;
- var_types type = getArgTypeForStruct(clsHnd, &howToPassStruct, isVarArg, varDsc->lvExactSize);
+ var_types type = getArgTypeForStruct(clsHnd, &howToPassStruct, isVarArg, varDsc->lvExactSize());
if (howToPassStruct == SPK_ByValueAsHfa)
{
{
varDsc->SetLayout(layout);
- assert(varDsc->lvExactSize == 0);
- varDsc->lvExactSize = layout->GetSize();
- assert(layout->IsBlockLayout() || (varDsc->lvExactSize != 0));
-
if (layout->IsValueClass())
{
varDsc->lvType = layout->GetType();
{
structPassingKind howToReturnStruct;
getArgTypeForStruct(layout->GetClassHandle(), &howToReturnStruct, this->info.compIsVarArgs,
- varDsc->lvExactSize);
+ varDsc->lvExactSize());
if (howToReturnStruct == SPK_ByReference)
{
if (simdBaseJitType != CORINFO_TYPE_UNDEF)
{
assert(varTypeIsSIMD(varDsc));
- varDsc->lvSIMDType = true;
varDsc->SetSimdBaseJitType(simdBaseJitType);
}
}
// hfa variables can never contain GC pointers
assert(!layout->HasGCPtr());
// The size of this struct should be evenly divisible by 4 or 8
- assert((varDsc->lvExactSize % genTypeSize(hfaType)) == 0);
+ assert((varDsc->lvExactSize() % genTypeSize(hfaType)) == 0);
// The number of elements in the HFA should fit into our MAX_ARG_REG_COUNT limit
- assert((varDsc->lvExactSize / genTypeSize(hfaType)) <= MAX_ARG_REG_COUNT);
+ assert((varDsc->lvExactSize() / genTypeSize(hfaType)) <= MAX_ARG_REG_COUNT);
}
}
}
assert(ClassLayout::AreCompatible(varDsc->GetLayout(), layout));
// Inlining could replace a canon struct type with an exact one.
varDsc->SetLayout(layout);
- assert(layout->IsBlockLayout() || (varDsc->lvExactSize != 0));
+ assert(layout->IsBlockLayout() || (layout->GetSize() != 0));
}
if (!layout->IsBlockLayout())
unsigned Compiler::lvaLclExactSize(unsigned varNum)
{
assert(varNum < lvaCount);
-
- var_types varType = lvaTable[varNum].TypeGet();
-
- if (varType == TYP_STRUCT)
- {
- return lvaTable[varNum].lvExactSize;
- }
-
- return genTypeSize(varType);
+ return lvaGetDesc(varNum)->lvExactSize();
}
// getCalledCount -- get the value used to normalized weights for this method
}
#endif // FEATURE_SIMD
+//------------------------------------------------------------------------
+// lvExactSize: Get the exact size of the type of this local.
+//
+// Return Value:
+// Size in bytes. Always non-zero, but not necessarily a multiple of the
+// stack slot size.
+//
+unsigned LclVarDsc::lvExactSize() const
+{
+ return (lvType == TYP_STRUCT) ? GetLayout()->GetSize() : genTypeSize(lvType);
+}
+
+//------------------------------------------------------------------------
+// lvSize: Get the size of a struct local on the stack frame.
+//
+// Return Value:
+// Size in bytes.
+//
unsigned LclVarDsc::lvSize() const // Size needed for storage representation. Only used for structs.
{
// TODO-Review: Sometimes we get called on ARM with HFA struct variables that have been promoted,
assert(varTypeIsStruct(lvType));
const bool isFloatHfa = (lvIsHfa() && (GetHfaType() == TYP_FLOAT));
const unsigned argSizeAlignment = Compiler::eeGetArgSizeAlignment(lvType, isFloatHfa);
- return roundUp(lvExactSize, argSizeAlignment);
+ return roundUp(lvExactSize(), argSizeAlignment);
}
#if defined(FEATURE_SIMD) && !defined(TARGET_64BIT)
if (lvType == TYP_SIMD12)
{
assert(!lvIsParam);
- assert(lvExactSize == 12);
return 16;
}
#endif // defined(FEATURE_SIMD) && !defined(TARGET_64BIT)
- return roundUp(lvExactSize, TARGET_POINTER_SIZE);
+ return roundUp(lvExactSize(), TARGET_POINTER_SIZE);
}
/**********************************************************************************
{
noway_assert(lclNum != BAD_VAR_NUM);
+ LclVarDsc* lcl = lvaGetDesc(lclNum);
#ifdef TARGET_64BIT
// Before final frame layout, assume the worst case, that every >=8 byte local will need
// maximum padding to be aligned. This is because we generate code based on the stack offset
// better performance.
if ((size >= 8) && ((lvaDoneFrameLayout != FINAL_FRAME_LAYOUT) || ((stkOffs % 8) != 0)
#if defined(FEATURE_SIMD) && ALIGN_SIMD_TYPES
- || lclVarIsSIMDType(lclNum)
+ || varTypeIsSIMD(lcl)
#endif
))
{
// alignment padding
unsigned pad = 0;
#if defined(FEATURE_SIMD) && ALIGN_SIMD_TYPES
- if (lclVarIsSIMDType(lclNum) && !lvaIsImplicitByRefLocal(lclNum))
+ if (varTypeIsSIMD(lcl))
{
- int alignment = getSIMDTypeAlignment(lvaTable[lclNum].lvType);
+ int alignment = getSIMDTypeAlignment(lcl->TypeGet());
if (stkOffs % alignment != 0)
{
lvaIncrementFrameSize(size);
stkOffs -= size;
- lvaTable[lclNum].SetStackOffset(stkOffs);
+ lcl->SetStackOffset(stkOffs);
#ifdef DEBUG
if (verbose)
if (varType != TYP_STRUCT)
{
// Change the variable to a block struct
- varDsc->lvExactSize = roundUp(padding + pComp->lvaLclSize(lclNum), TARGET_POINTER_SIZE);
- varDsc->lvType = TYP_STRUCT;
- varDsc->SetLayout(pComp->typGetBlkLayout(varDsc->lvExactSize));
+ ClassLayout* layout =
+ pComp->typGetBlkLayout(roundUp(padding + pComp->lvaLclSize(lclNum), TARGET_POINTER_SIZE));
+ varDsc->lvType = TYP_STRUCT;
+ varDsc->SetLayout(layout);
pComp->lvaSetVarAddrExposed(lclNum DEBUGARG(AddressExposedReason::STRESS_LCL_FLD));
JITDUMP("Converting V%02u to %u sized block with LCL_FLD at offset (padding %u)\n", lclNum,
- varDsc->lvExactSize, padding);
+ layout->GetSize(), padding);
}
tree->gtFlags |= GTF_GLOB_REF;
// to turn the tree type into "CorInfoType".
if ((tree->TypeGet() == simdBaseType) && ((fieldOffset % baseTypeSize) == 0))
{
- *simdSizeOut = varDsc->lvExactSize;
+ *simdSizeOut = varDsc->lvExactSize();
*simdBaseJitTypeOut = simdBaseJitType;
*indexOut = fieldOffset / baseTypeSize;
// If we have marked this as lvUsedInSIMDIntrinsic, then we do not want to promote
// its fields. Instead, we will attempt to enregister the entire struct.
- if (varDsc->lvIsSIMDType() && (varDsc->lvIsUsedInSIMDIntrinsic() || isOpaqueSIMDLclVar(varDsc)))
+ if (varTypeIsSIMD(varDsc) && (varDsc->lvIsUsedInSIMDIntrinsic() || isOpaqueSIMDLclVar(varDsc)))
{
varDsc->lvRegStruct = true;
}
madeChanges |= promotedVar;
- if (!promotedVar && varDsc->lvIsSIMDType() && !varDsc->lvFieldAccessed)
+ if (!promotedVar && varTypeIsSIMD(varDsc) && !varDsc->lvFieldAccessed)
{
// Even if we have not used this in a SIMD intrinsic, if it is not being promoted,
// we will treat it as a reg struct.
m_dstLclNum = m_dstLclNode->GetLclNum();
m_dstVarDsc = m_comp->lvaGetDesc(m_dstLclNum);
- assert((m_dstVarDsc->TypeGet() != TYP_STRUCT) ||
- (m_dstVarDsc->GetLayout()->GetSize() == m_dstVarDsc->lvExactSize));
-
// Kill everything about m_dstLclNum (and its field locals)
if (m_comp->optLocalAssertionProp && (m_comp->optAssertionCount > 0))
{
return;
}
- if (destLclVar->lvExactSize != blockSize)
+ if (destLclVar->lvExactSize() != blockSize)
{
JITDUMP(" dest size mismatch.\n");
return;
noway_assert(varTypeIsStruct(m_dstVarDsc));
noway_assert(!m_comp->opts.MinOpts());
- if (m_blockSize == m_dstVarDsc->lvExactSize)
+ if (m_blockSize == m_dstVarDsc->lvExactSize())
{
JITDUMP(" (m_dstDoFldAsg=true)");
// We may decide later that a copyblk is required when this struct has holes
noway_assert(varTypeIsStruct(m_srcVarDsc));
noway_assert(!m_comp->opts.MinOpts());
- if (m_blockSize == m_srcVarDsc->lvExactSize)
+ if (m_blockSize == m_srcVarDsc->lvExactSize())
{
JITDUMP(" (m_srcDoFldAsg=true)");
// We may decide later that a copyblk is required when this struct has holes
assert(destType != TYP_STRUCT);
unsigned destSize = genTypeSize(destType);
m_srcVarDsc = m_comp->lvaGetDesc(m_srcLclNum);
- unsigned srcSize =
- (m_srcVarDsc->lvType == TYP_STRUCT) ? m_srcVarDsc->lvExactSize : genTypeSize(m_srcVarDsc);
+ unsigned srcSize = m_srcVarDsc->lvExactSize();
if (destSize == srcSize)
{
m_srcLclNode->ChangeOper(GT_LCL_FLD);
GenTree* addr = indir->Addr();
- if (addr->OperIs(GT_LCL_VAR_ADDR) && comp->lvaGetDesc(addr->AsLclVar())->lvSIMDType)
+ if (addr->OperIs(GT_LCL_VAR_ADDR) && varTypeIsSIMD(comp->lvaGetDesc(addr->AsLclVar())))
{
// If we have GT_IND(GT_LCL_VAR_ADDR) and the var is a SIMD type,
// replace the expression by GT_LCL_VAR or GT_LCL_FLD.