diff options
Diffstat (limited to 'src/jit/lclvars.cpp')
-rw-r--r-- | src/jit/lclvars.cpp | 136 |
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"); |