summaryrefslogtreecommitdiff
path: root/src/jit/lclvars.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/lclvars.cpp')
-rw-r--r--src/jit/lclvars.cpp136
1 files changed, 93 insertions, 43 deletions
diff --git a/src/jit/lclvars.cpp b/src/jit/lclvars.cpp
index ea9c573a02..b4e4cc6e55 100644
--- a/src/jit/lclvars.cpp
+++ b/src/jit/lclvars.cpp
@@ -465,7 +465,7 @@ void Compiler::lvaInitRetBuffArg(InitVarDscInfo* varDscInfo)
varDsc->lvArgReg = genMapIntRegArgNumToRegNum(retBuffArgNum);
}
-#if FEATURE_MULTIREG__ARGS
+#if FEATURE_MULTIREG_ARGS
varDsc->lvOtherArgReg = REG_NA;
#endif
varDsc->setPrefReg(varDsc->lvArgReg, this);
@@ -488,6 +488,16 @@ void Compiler::lvaInitRetBuffArg(InitVarDscInfo* varDscInfo)
varDsc->lvType = TYP_I_IMPL;
}
}
+#ifdef FEATURE_SIMD
+ else if (featureSIMD && varTypeIsSIMD(info.compRetType))
+ {
+ varDsc->lvSIMDType = true;
+ varDsc->lvBaseType =
+ getBaseTypeAndSizeOfSIMDType(info.compMethodInfo->args.retTypeClass, &varDsc->lvExactSize);
+ assert(varDsc->lvBaseType != TYP_UNKNOWN);
+ }
+#endif // FEATURE_SIMD
+
assert(isValidIntArgReg(varDsc->lvArgReg));
#ifdef DEBUG
@@ -1059,7 +1069,7 @@ void Compiler::lvaInitVarArgsHandle(InitVarDscInfo* varDscInfo)
varDsc->lvIsRegArg = 1;
varDsc->lvArgReg = genMapRegArgNumToRegNum(varArgHndArgNum, TYP_I_IMPL);
-#if FEATURE_MULTIREG__ARGS
+#if FEATURE_MULTIREG_ARGS
varDsc->lvOtherArgReg = REG_NA;
#endif
varDsc->setPrefReg(varDsc->lvArgReg, this);
@@ -1414,9 +1424,16 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd,
if (typeHnd != StructPromotionInfo->typeHnd)
{
- // sizeof(double) represents the size of the largest primitive type that we can struct promote
- // In the future this may be changing to XMM_REGSIZE_BYTES
- const int MaxOffset = MAX_NumOfFieldsInPromotableStruct * sizeof(double); // must be a compile time constant
+ // sizeof(double) represents the size of the largest primitive type that we can struct promote.
+ // In the future this may be changing to XMM_REGSIZE_BYTES.
+ // Note: MaxOffset is used below to declare a local array, and therefore must be a compile-time constant.
+ CLANG_FORMAT_COMMENT_ANCHOR;
+#ifdef FEATURE_SIMD
+ // This will allow promotion of 2 Vector<T> fields on AVX2, or 4 Vector<T> fields on SSE2.
+ const int MaxOffset = MAX_NumOfFieldsInPromotableStruct * XMM_REGSIZE_BYTES;
+#else // !FEATURE_SIMD
+ const int MaxOffset = MAX_NumOfFieldsInPromotableStruct * sizeof(double);
+#endif // !FEATURE_SIMD
assert((BYTE)MaxOffset == MaxOffset); // because lvaStructFieldInfo.fldOffset is byte-sized
assert((BYTE)MAX_NumOfFieldsInPromotableStruct ==
@@ -1507,13 +1524,31 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd,
CorInfoType corType = info.compCompHnd->getFieldType(pFieldInfo->fldHnd, &pFieldInfo->fldTypeHnd);
var_types varType = JITtype2varType(corType);
pFieldInfo->fldType = varType;
- pFieldInfo->fldSize = genTypeSize(varType);
+ unsigned size = genTypeSize(varType);
+ pFieldInfo->fldSize = size;
if (varTypeIsGC(varType))
{
containsGCpointers = true;
}
+#ifdef FEATURE_SIMD
+ // Check to see if this is a SIMD type.
+ // We will only check this if we have already found a SIMD type, which will be true if
+ // we have encountered any SIMD intrinsics.
+ if (usesSIMDTypes() && (pFieldInfo->fldSize == 0) && isSIMDClass(pFieldInfo->fldTypeHnd))
+ {
+ unsigned simdSize;
+ var_types simdBaseType = getBaseTypeAndSizeOfSIMDType(pFieldInfo->fldTypeHnd, &simdSize);
+ if (simdBaseType != TYP_UNKNOWN)
+ {
+ varType = getSIMDTypeForSize(simdSize);
+ pFieldInfo->fldType = varType;
+ pFieldInfo->fldSize = simdSize;
+ }
+ }
+#endif // FEATURE_SIMD
+
if (pFieldInfo->fldSize == 0)
{
// Non-primitive struct field. Don't promote.
@@ -1556,8 +1591,10 @@ void Compiler::lvaCanPromoteStructType(CORINFO_CLASS_HANDLE typeHnd,
#endif // _TARGET_ARM_
}
- // If we saw any GC pointer fields above then the CORINFO_FLG_CONTAINS_GC_PTR has to be set!
- noway_assert((containsGCpointers == false) || ((typeFlags & CORINFO_FLG_CONTAINS_GC_PTR) != 0));
+ // If we saw any GC pointer or by-ref fields above then CORINFO_FLG_CONTAINS_GC_PTR or
+ // CORINFO_FLG_CONTAINS_STACK_PTR has to be set!
+ noway_assert((containsGCpointers == false) ||
+ ((typeFlags & (CORINFO_FLG_CONTAINS_GC_PTR | CORINFO_FLG_CONTAINS_STACK_PTR)) != 0));
// If we have "Custom Layout" then we might have an explicit Size attribute
// Managed C++ uses this for its structs, such C++ types will not contain GC pointers.
@@ -1683,7 +1720,7 @@ void Compiler::lvaPromoteStructVar(unsigned lclNum, lvaStructPromotionInfo* Stru
{
lvaStructFieldInfo* pFieldInfo = &StructPromotionInfo->fields[index];
- if (varTypeIsFloating(pFieldInfo->fldType))
+ if (varTypeIsFloating(pFieldInfo->fldType) || varTypeIsSIMD(pFieldInfo->fldType))
{
lvaTable[lclNum].lvContainsFloatingFields = 1;
// Whenever we promote a struct that contains a floating point field
@@ -1727,12 +1764,32 @@ void Compiler::lvaPromoteStructVar(unsigned lclNum, lvaStructPromotionInfo* Stru
fieldVarDsc->lvIsRegArg = true;
fieldVarDsc->lvArgReg = varDsc->lvArgReg;
fieldVarDsc->setPrefReg(varDsc->lvArgReg, this); // Set the preferred register
+#if FEATURE_MULTIREG_ARGS && defined(FEATURE_SIMD)
+ if (varTypeIsSIMD(fieldVarDsc))
+ {
+ // This field is a SIMD type, and will be considered to be passed in multiple registers
+ // if the parent struct was. Note that this code relies on the fact that if there is
+ // a SIMD field of an enregisterable struct, it is the only field.
+ // We will assert that, in case future changes are made to the ABI.
+ assert(varDsc->lvFieldCnt == 1);
+ fieldVarDsc->lvOtherArgReg = varDsc->lvOtherArgReg;
+ }
+#endif // FEATURE_MULTIREG_ARGS && defined(FEATURE_SIMD)
lvaMarkRefsWeight = BB_UNITY_WEIGHT; // incRefCnts can use this compiler global variable
fieldVarDsc->incRefCnts(BB_UNITY_WEIGHT, this); // increment the ref count for prolog initialization
}
#endif
+#ifdef FEATURE_SIMD
+ if (varTypeIsSIMD(pFieldInfo->fldType))
+ {
+ // Set size to zero so that lvaSetStruct will appropriately set the SIMD-relevant fields.
+ fieldVarDsc->lvExactSize = 0;
+ lvaSetStruct(varNum, pFieldInfo->fldTypeHnd, false, true);
+ }
+#endif // FEATURE_SIMD
+
#ifdef DEBUG
// This temporary should not be converted to a double in stress mode,
// because we introduce assigns to it after the stress conversion
@@ -1947,14 +2004,14 @@ bool Compiler::lvaIsMultiregStruct(LclVarDsc* varDsc)
if (howToPassStruct == SPK_ByValueAsHfa)
{
- assert(type = TYP_STRUCT);
+ assert(type == TYP_STRUCT);
return true;
}
#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) || defined(_TARGET_ARM64_)
if (howToPassStruct == SPK_ByValue)
{
- assert(type = TYP_STRUCT);
+ assert(type == TYP_STRUCT);
return true;
}
#endif
@@ -2029,7 +2086,6 @@ void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool
}
else
{
- assert(varDsc->lvExactSize != 0);
#if FEATURE_SIMD
assert(!varTypeIsSIMD(varDsc) || (varDsc->lvBaseType != TYP_UNKNOWN));
#endif // FEATURE_SIMD
@@ -3082,37 +3138,6 @@ void Compiler::lvaMarkLclRefs(GenTreePtr tree)
#endif
}
-#if FANCY_ARRAY_OPT
-
- /* Special case: assignment node */
-
- if (tree->gtOper == GT_ASG)
- {
- if (tree->gtType == TYP_INT)
- {
- unsigned lclNum1;
- LclVarDsc* varDsc1;
-
- GenTreePtr op1 = tree->gtOp.gtOp1;
-
- if (op1->gtOper != GT_LCL_VAR)
- return;
-
- lclNum1 = op1->gtLclVarCommon.gtLclNum;
- noway_assert(lclNum1 < lvaCount);
- varDsc1 = lvaTable + lclNum1;
-
- if (varDsc1->lvAssignOne)
- varDsc1->lvAssignTwo = true;
- else
- varDsc1->lvAssignOne = true;
- }
-
- return;
- }
-
-#endif
-
#ifdef _TARGET_XARCH_
/* Special case: integer shift node by a variable amount */
@@ -5750,6 +5775,7 @@ void Compiler::lvaAlignFrame()
#elif defined(_TARGET_X86_)
+#if DOUBLE_ALIGN
if (genDoubleAlign())
{
// Double Frame Alignement for x86 is handled in Compiler::lvaAssignVirtualFrameOffsetsToLocals()
@@ -5760,6 +5786,30 @@ void Compiler::lvaAlignFrame()
lvaIncrementFrameSize(sizeof(void*));
}
}
+#endif
+
+ if (STACK_ALIGN > REGSIZE_BYTES)
+ {
+ if (lvaDoneFrameLayout != FINAL_FRAME_LAYOUT)
+ {
+ // If we are not doing final layout, we don't know the exact value of compLclFrameSize
+ // and thus do not know how much we will need to add in order to be aligned.
+ // We add the maximum pad that we could ever have (which is 12)
+ lvaIncrementFrameSize(STACK_ALIGN - REGSIZE_BYTES);
+ }
+
+ // Align the stack with STACK_ALIGN value.
+ int adjustFrameSize = compLclFrameSize;
+#if defined(UNIX_X86_ABI)
+ // we need to consider spilled register(s) plus return address and/or EBP
+ int adjustCount = compCalleeRegsPushed + 1 + (codeGen->isFramePointerUsed() ? 1 : 0);
+ adjustFrameSize += (adjustCount * REGSIZE_BYTES) % STACK_ALIGN;
+#endif
+ if ((adjustFrameSize % STACK_ALIGN) != 0)
+ {
+ lvaIncrementFrameSize(STACK_ALIGN - (adjustFrameSize % STACK_ALIGN));
+ }
+ }
#else
NYI("TARGET specific lvaAlignFrame");