diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index bc1bd821b6488d..e607e8b1d8257f 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3816,9 +3816,6 @@ class Compiler StructPromotionHelper* structPromotionHelper; -#if !defined(TARGET_64BIT) - void lvaPromoteLongVars(); -#endif // !defined(TARGET_64BIT) unsigned lvaGetFieldLocal(const LclVarDsc* varDsc, unsigned int fldOffset); lvaPromotionType lvaGetPromotionType(const LclVarDsc* varDsc); lvaPromotionType lvaGetPromotionType(unsigned varNum); diff --git a/src/coreclr/jit/decomposelongs.cpp b/src/coreclr/jit/decomposelongs.cpp index e6a624a901a2ec..423319fc5eb5c3 100644 --- a/src/coreclr/jit/decomposelongs.cpp +++ b/src/coreclr/jit/decomposelongs.cpp @@ -42,7 +42,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/ // void DecomposeLongs::PrepareForDecomposition() { - m_compiler->lvaPromoteLongVars(); + PromoteLongVars(); } //------------------------------------------------------------------------ @@ -1954,4 +1954,104 @@ genTreeOps DecomposeLongs::GetLoOper(genTreeOps oper) } } -#endif // !TARGET_64BIT +//------------------------------------------------------------------------ +// PromoteLongVars: "Struct promote" all register candidate longs as if they are structs of two ints. +// +// Arguments: +// None. +// +// Return Value: +// None. +// +void DecomposeLongs::PromoteLongVars() +{ + if ((m_compiler->opts.compFlags & CLFLG_REGVAR) == 0) + { + return; + } + + // The lvaTable might grow as we grab temps. Make a local copy here. + unsigned startLvaCount = m_compiler->lvaCount; + for (unsigned lclNum = 0; lclNum < startLvaCount; lclNum++) + { + LclVarDsc* varDsc = m_compiler->lvaGetDesc(lclNum); + if (!varTypeIsLong(varDsc)) + { + continue; + } + if (varDsc->lvDoNotEnregister) + { + continue; + } + if (varDsc->lvRefCnt() == 0) + { + continue; + } + if (varDsc->lvIsStructField) + { + continue; + } + if (m_compiler->fgNoStructPromotion) + { + continue; + } + if (m_compiler->fgNoStructParamPromotion && varDsc->lvIsParam) + { + continue; + } + + assert(!varDsc->lvIsMultiRegArgOrRet()); + varDsc->lvFieldCnt = 2; + varDsc->lvFieldLclStart = m_compiler->lvaCount; + varDsc->lvPromoted = true; + varDsc->lvContainsHoles = false; + + JITDUMP("\nPromoting long local V%02u:", lclNum); + + bool isParam = varDsc->lvIsParam; + + for (unsigned index = 0; index < 2; ++index) + { + // Grab the temp for the field local. + CLANG_FORMAT_COMMENT_ANCHOR; + +#ifdef DEBUG + char buf[200]; + sprintf_s(buf, sizeof(buf), "%s V%02u.%s (fldOffset=0x%x)", "field", lclNum, index == 0 ? "lo" : "hi", + index * 4); + + // We need to copy 'buf' as lvaGrabTemp() below caches a copy to its argument. + size_t len = strlen(buf) + 1; + char* bufp = m_compiler->getAllocator(CMK_DebugOnly).allocate(len); + strcpy_s(bufp, len, buf); +#endif + + unsigned varNum = + m_compiler->lvaGrabTemp(false DEBUGARG(bufp)); // Lifetime of field locals might span multiple BBs, so + // they are long lifetime temps. + + LclVarDsc* fieldVarDsc = m_compiler->lvaGetDesc(varNum); + fieldVarDsc->lvType = TYP_INT; + fieldVarDsc->lvExactSize = genTypeSize(TYP_INT); + fieldVarDsc->lvIsStructField = true; + fieldVarDsc->lvFldOffset = (unsigned char)(index * genTypeSize(TYP_INT)); + fieldVarDsc->lvFldOrdinal = (unsigned char)index; + fieldVarDsc->lvParentLcl = lclNum; + // Currently we do not support enregistering incoming promoted aggregates with more than one field. + if (isParam) + { + fieldVarDsc->lvIsParam = true; + m_compiler->lvaSetVarDoNotEnregister(varNum DEBUGARG(Compiler::DNER_LongParamField)); + } + } + } + +#ifdef DEBUG + if (m_compiler->verbose) + { + printf("\nlvaTable after PromoteLongVars\n"); + m_compiler->lvaTableDump(); + } +#endif // DEBUG +} +#endif // !defined(TARGET_64BIT) diff --git a/src/coreclr/jit/decomposelongs.h b/src/coreclr/jit/decomposelongs.h index 42ea8ada70d3c2..4a7320553bdf76 100644 --- a/src/coreclr/jit/decomposelongs.h +++ b/src/coreclr/jit/decomposelongs.h @@ -33,6 +33,8 @@ class DecomposeLongs return *m_range; } + void PromoteLongVars(); + // Driver functions void DecomposeRangeHelper(); GenTree* DecomposeNode(GenTree* tree); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index c503e22a287d0e..ca15afbff50925 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -145,11 +145,13 @@ void Compiler::fgInit() #ifdef DEBUG if (!compIsForInlining()) { - if ((JitConfig.JitNoStructPromotion() & 1) == 1) + const int noStructPromotionValue = JitConfig.JitNoStructPromotion(); + assert(0 <= noStructPromotionValue && noStructPromotionValue <= 2); + if (noStructPromotionValue == 1) { fgNoStructPromotion = true; } - if ((JitConfig.JitNoStructPromotion() & 2) == 2) + if (noStructPromotionValue == 2) { fgNoStructParamPromotion = true; } diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index ba3ab23b8bdd83..bca1c2ee8569c3 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -116,7 +116,8 @@ CONFIG_INTEGER(JitNoHoist, W("JitNoHoist"), 0) CONFIG_INTEGER(JitNoInline, W("JitNoInline"), 0) // Disables inlining of all methods CONFIG_INTEGER(JitNoMemoryBarriers, W("JitNoMemoryBarriers"), 0) // If 1, don't generate memory barriers CONFIG_INTEGER(JitNoRegLoc, W("JitNoRegLoc"), 0) -CONFIG_INTEGER(JitNoStructPromotion, W("JitNoStructPromotion"), 0) // Disables struct promotion in Jit32 +CONFIG_INTEGER(JitNoStructPromotion, W("JitNoStructPromotion"), 0) // Disables struct promotion 1 - for all, 2 - for + // params. CONFIG_INTEGER(JitNoUnroll, W("JitNoUnroll"), 0) CONFIG_INTEGER(JitOrder, W("JitOrder"), 0) CONFIG_INTEGER(JitQueryCurrentStaticFieldClass, W("JitQueryCurrentStaticFieldClass"), 1) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index e2039f930b7dbe..85a04da43718a3 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -2459,94 +2459,6 @@ void Compiler::StructPromotionHelper::PromoteStructVar(unsigned lclNum) } } -#if !defined(TARGET_64BIT) -//------------------------------------------------------------------------ -// lvaPromoteLongVars: "Struct promote" all register candidate longs as if they are structs of two ints. -// -// Arguments: -// None. -// -// Return Value: -// None. -// -void Compiler::lvaPromoteLongVars() -{ - if ((opts.compFlags & CLFLG_REGVAR) == 0) - { - return; - } - - // The lvaTable might grow as we grab temps. Make a local copy here. - unsigned startLvaCount = lvaCount; - for (unsigned lclNum = 0; lclNum < startLvaCount; lclNum++) - { - LclVarDsc* varDsc = &lvaTable[lclNum]; - if (!varTypeIsLong(varDsc) || varDsc->lvDoNotEnregister || (varDsc->lvRefCnt() == 0) || - varDsc->lvIsStructField || (fgNoStructPromotion && varDsc->lvIsParam)) - { - continue; - } - - assert(!varDsc->lvIsMultiRegArgOrRet()); - varDsc->lvFieldCnt = 2; - varDsc->lvFieldLclStart = lvaCount; - varDsc->lvPromoted = true; - varDsc->lvContainsHoles = false; - -#ifdef DEBUG - if (verbose) - { - printf("\nPromoting long local V%02u:", lclNum); - } -#endif - - bool isParam = varDsc->lvIsParam; - - for (unsigned index = 0; index < 2; ++index) - { - // Grab the temp for the field local. - CLANG_FORMAT_COMMENT_ANCHOR; - -#ifdef DEBUG - char buf[200]; - sprintf_s(buf, sizeof(buf), "%s V%02u.%s (fldOffset=0x%x)", "field", lclNum, index == 0 ? "lo" : "hi", - index * 4); - - // We need to copy 'buf' as lvaGrabTemp() below caches a copy to its argument. - size_t len = strlen(buf) + 1; - char* bufp = getAllocator(CMK_DebugOnly).allocate(len); - strcpy_s(bufp, len, buf); -#endif - - unsigned varNum = lvaGrabTemp(false DEBUGARG(bufp)); // Lifetime of field locals might span multiple BBs, so - // they are long lifetime temps. - - LclVarDsc* fieldVarDsc = &lvaTable[varNum]; - fieldVarDsc->lvType = TYP_INT; - fieldVarDsc->lvExactSize = genTypeSize(TYP_INT); - fieldVarDsc->lvIsStructField = true; - fieldVarDsc->lvFldOffset = (unsigned char)(index * genTypeSize(TYP_INT)); - fieldVarDsc->lvFldOrdinal = (unsigned char)index; - fieldVarDsc->lvParentLcl = lclNum; - // Currently we do not support enregistering incoming promoted aggregates with more than one field. - if (isParam) - { - fieldVarDsc->lvIsParam = true; - lvaSetVarDoNotEnregister(varNum DEBUGARG(DNER_LongParamField)); - } - } - } - -#ifdef DEBUG - if (verbose) - { - printf("\nlvaTable after lvaPromoteLongVars\n"); - lvaTableDump(); - } -#endif // DEBUG -} -#endif // !defined(TARGET_64BIT) - //-------------------------------------------------------------------------------------------- // lvaGetFieldLocal - returns the local var index for a promoted field in a promoted struct var. //