diff options
author | Sergey Andreenko <seandree@microsoft.com> | 2021-07-01 20:31:58 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-01 20:31:58 +0300 |
commit | eeadfdb2f57e607241b9b09ada1ef08717e618f6 (patch) | |
tree | c6cbe2308d4daad66cdd4aaae8a7edfc35c7869e /src/coreclr/jit | |
parent | 7298a534a00d21ab275576b89f2f29126bbc83b1 (diff) |
Mark vars as do not enreg earlier in minopts. (#54998)
* Improve morphblock logic.
* change lclVars.
* Extract compEnregLocals
* same for args/locals
Diffstat (limited to 'src/coreclr/jit')
-rw-r--r-- | src/coreclr/jit/compiler.cpp | 4 | ||||
-rw-r--r-- | src/coreclr/jit/compiler.h | 5 | ||||
-rw-r--r-- | src/coreclr/jit/compiler.hpp | 5 | ||||
-rw-r--r-- | src/coreclr/jit/decomposelongs.cpp | 2 | ||||
-rw-r--r-- | src/coreclr/jit/lclvars.cpp | 20 | ||||
-rw-r--r-- | src/coreclr/jit/lsra.cpp | 4 | ||||
-rw-r--r-- | src/coreclr/jit/morph.cpp | 1 | ||||
-rw-r--r-- | src/coreclr/jit/morphblock.cpp | 104 |
8 files changed, 83 insertions, 62 deletions
diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 23aed4e317d..6e691f73f77 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2855,8 +2855,8 @@ void Compiler::compInitOptions(JitFlags* jitFlags) setUsesSIMDTypes(false); #endif // FEATURE_SIMD - lvaEnregEHVars = (((opts.compFlags & CLFLG_REGVAR) != 0) && JitConfig.EnableEHWriteThru()); - lvaEnregMultiRegVars = (((opts.compFlags & CLFLG_REGVAR) != 0) && JitConfig.EnableMultiRegLocals()); + lvaEnregEHVars = (compEnregLocals() && JitConfig.EnableEHWriteThru()); + lvaEnregMultiRegVars = (compEnregLocals() && JitConfig.EnableMultiRegLocals()); if (compIsForImportOnly()) { diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index fbafd6e9a84..9086613da28 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -9778,6 +9778,11 @@ public: #endif // FEATURE_MULTIREG_RET } + bool compEnregLocals() + { + return ((opts.compFlags & CLFLG_REGVAR) != 0); + } + bool compEnregStructLocals() { return (JitConfig.JitEnregStructLocals() != 0); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index d05bfc6bbeb..0d6336d089b 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -1585,6 +1585,11 @@ inline unsigned Compiler::lvaGrabTemp(bool shortLifetime DEBUGARG(const char* re lvaTable[tempNum].lvIsTemp = shortLifetime; lvaTable[tempNum].lvOnFrame = true; + if (!compEnregLocals()) + { + lvaSetVarDoNotEnregister(tempNum DEBUGARG(Compiler::DNER_NoRegVars)); + } + // If we've started normal ref counting, bump the ref count of this // local, as we no longer do any incremental counting, and we presume // this new local will be referenced. diff --git a/src/coreclr/jit/decomposelongs.cpp b/src/coreclr/jit/decomposelongs.cpp index 39a4d01acc4..1ee7d142858 100644 --- a/src/coreclr/jit/decomposelongs.cpp +++ b/src/coreclr/jit/decomposelongs.cpp @@ -2076,7 +2076,7 @@ genTreeOps DecomposeLongs::GetLoOper(genTreeOps oper) // void DecomposeLongs::PromoteLongVars() { - if ((m_compiler->opts.compFlags & CLFLG_REGVAR) == 0) + if (!m_compiler->compEnregLocals()) { return; } diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index eec7450e656..852c2586caa 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1431,6 +1431,11 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, } #endif + if (!compEnregLocals()) + { + lvaSetVarDoNotEnregister(varNum DEBUGARG(Compiler::DNER_NoRegVars)); + } + #ifdef DEBUG varDsc->SetStackOffset(BAD_STK_OFFS); #endif @@ -2622,6 +2627,7 @@ void Compiler::lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregister case DNER_NoRegVars: JITDUMP("opts.compFlags & CLFLG_REGVAR is not set\n"); assert((opts.compFlags & CLFLG_REGVAR) == 0); + assert(!compEnregLocals()); break; case DNER_MinOptsGC: JITDUMP("It is a GC Ref and we are compiling MinOpts\n"); @@ -3467,7 +3473,7 @@ void Compiler::lvaSortByRefCount() assert(varDsc->lvType != TYP_STRUCT || varDsc->lvDoNotEnregister); // For structs, should have set this when we set lvAddrExposed. } - else if (varTypeIsStruct(varDsc)) + if (varTypeIsStruct(varDsc)) { // Promoted structs will never be considered for enregistration anyway, // and the DoNotEnregister flag was used to indicate whether promotion was @@ -3481,28 +3487,24 @@ void Compiler::lvaSortByRefCount() lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_IsStruct)); } } - else if (varDsc->lvIsStructField && (lvaGetParentPromotionType(lclNum) != PROMOTION_TYPE_INDEPENDENT)) + if (varDsc->lvIsStructField && (lvaGetParentPromotionType(lclNum) != PROMOTION_TYPE_INDEPENDENT)) { lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_DepField)); } - else if (varDsc->lvPinned) + if (varDsc->lvPinned) { varDsc->lvTracked = 0; #ifdef JIT32_GCENCODER lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_PinningRef)); #endif } - else if (opts.MinOpts() && !JitConfig.JitMinOptsTrackGCrefs() && varTypeIsGC(varDsc->TypeGet())) + if (opts.MinOpts() && !JitConfig.JitMinOptsTrackGCrefs() && varTypeIsGC(varDsc->TypeGet())) { varDsc->lvTracked = 0; lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_MinOptsGC)); } - else if ((opts.compFlags & CLFLG_REGVAR) == 0) - { - lvaSetVarDoNotEnregister(lclNum DEBUGARG(DNER_NoRegVars)); - } #if defined(JIT32_GCENCODER) && defined(FEATURE_EH_FUNCLETS) - else if (lvaIsOriginalThisArg(lclNum) && (info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0) + if (lvaIsOriginalThisArg(lclNum) && (info.compMethodInfo->options & CORINFO_GENERICS_CTXT_FROM_THIS) != 0) { // For x86/Linux, we need to track "this". // However we cannot have it in tracked variables, so we set "this" pointer always untracked diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 86d037e12ac..a2bb138ad0c 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -700,7 +700,7 @@ LinearScan::LinearScan(Compiler* theCompiler) // after the first liveness analysis - either by optimizations or by Lowering, and the tracked // set won't be recomputed until after Lowering (and this constructor is called prior to Lowering), // so we don't want to check that yet. - enregisterLocalVars = ((compiler->opts.compFlags & CLFLG_REGVAR) != 0); + enregisterLocalVars = compiler->compEnregLocals(); #ifdef TARGET_ARM64 availableIntRegs = (RBM_ALLINT & ~(RBM_PR | RBM_FP | RBM_LR) & ~compiler->codeGen->regSet.rsMaskResvd); #else @@ -1448,7 +1448,7 @@ bool LinearScan::isRegCandidate(LclVarDsc* varDsc) { return false; } - assert((compiler->opts.compFlags & CLFLG_REGVAR) != 0); + assert(compiler->compEnregLocals()); if (!varDsc->lvTracked) { diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 64e852397a8..4ec1328f878 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -2064,6 +2064,7 @@ GenTree* Compiler::fgMakeTmpArgNode(fgArgTabEntry* curArgTabEntry) { arg->ChangeOper(GT_LCL_FLD); arg->gtType = type; + lvaSetVarDoNotEnregister(tmpVarNum DEBUGARG(Compiler::DNER_LocalField)); } else { diff --git a/src/coreclr/jit/morphblock.cpp b/src/coreclr/jit/morphblock.cpp index 5e8d47a671b..515ce6fa4ab 100644 --- a/src/coreclr/jit/morphblock.cpp +++ b/src/coreclr/jit/morphblock.cpp @@ -137,7 +137,11 @@ GenTree* MorphInitBlockHelper::Morph() if (m_transformationDecision == BlockTransformation::Undefined) { - GenTree* oneAsgTree = m_comp->fgMorphOneAsgBlockOp(m_asg); + GenTree* oneAsgTree = nullptr; + if (m_dst != m_dstLclNode) + { + oneAsgTree = m_comp->fgMorphOneAsgBlockOp(m_asg); + } if (oneAsgTree != nullptr) { assert((m_asg == oneAsgTree) && "fgMorphOneAsgBlock must return the incoming tree."); @@ -362,22 +366,6 @@ void MorphInitBlockHelper::MorphStructCases() m_result = newTree; } } - - if (m_transformationDecision != BlockTransformation::FieldByField) - { - if (m_dst != m_dstLclNode) - { - // If we access the dst as a whole but not directly, for example, with OBJ(ADDR(LCL_VAR)) - // then set doNotEnreg. - // TODO-1stClassStructs: remove it when we can represent narowing struct cast - // without taking address of the lcl. - m_comp->lvaSetVarDoNotEnregister(m_dstLclNum DEBUGARG(Compiler::DNER_BlockOp)); - } - else if (m_dstVarDsc->lvPromoted) - { - m_comp->lvaSetVarDoNotEnregister(m_dstLclNum DEBUGARG(Compiler::DNER_BlockOp)); - } - } } if (m_transformationDecision == BlockTransformation::Undefined) @@ -403,6 +391,22 @@ void MorphInitBlockHelper::MorphStructCases() m_result->AsOp()->gtOp2 = m_src; } #endif // FEATURE_SIMD + + if (m_dstVarDsc != nullptr) + { + if (m_dst != m_dstLclNode) + { + // If we access the dst as a whole but not directly, for example, with OBJ(ADDR(LCL_VAR)) + // then set doNotEnreg. + // TODO-1stClassStructs: remove it when we can represent narowing struct cast + // without taking address of the lcl. + m_comp->lvaSetVarDoNotEnregister(m_dstLclNum DEBUGARG(Compiler::DNER_BlockOp)); + } + else if (m_dstVarDsc->lvPromoted) + { + m_comp->lvaSetVarDoNotEnregister(m_dstLclNum DEBUGARG(Compiler::DNER_BlockOp)); + } + } } } @@ -981,35 +985,6 @@ void MorphCopyBlockHelper::MorphStructCases() JITDUMP(requiresCopyBlock ? " this requires a CopyBlock.\n" : " using field by field assignments.\n"); - // Mark the dest/src structs as DoNotEnreg when they are not being fully referenced as the same type. - // - if (!m_dstDoFldAsg && (m_dstVarDsc != nullptr) && !m_dstSingleLclVarAsg) - { - if (!m_dstVarDsc->lvRegStruct || (m_dstVarDsc->lvType != m_dst->TypeGet())) - { - if (!m_dst->IsMultiRegLclVar() || (m_blockSize != m_dstVarDsc->lvExactSize) || - (m_dstVarDsc->lvCustomLayout && m_dstVarDsc->lvContainsHoles)) - { - // Mark it as DoNotEnregister. - m_comp->lvaSetVarDoNotEnregister(m_dstLclNum DEBUGARG(Compiler::DNER_BlockOp)); - } - else if (m_dst->IsMultiRegLclVar()) - { - // Handle this as lvIsMultiRegRet; this signals to SSA that it can't consider these fields - // SSA candidates (we don't have a way to represent multiple SSANums on MultiRegLclVar nodes). - m_dstVarDsc->lvIsMultiRegRet = true; - } - } - } - - if (!m_srcDoFldAsg && (m_srcVarDsc != nullptr) && !m_srcSingleLclVarAsg) - { - if (!m_srcVarDsc->lvRegStruct || (m_srcVarDsc->lvType != m_dst->TypeGet())) - { - m_comp->lvaSetVarDoNotEnregister(m_srcLclNum DEBUGARG(Compiler::DNER_BlockOp)); - } - } - if (requiresCopyBlock) { const var_types asgType = m_dst->TypeGet(); @@ -1031,6 +1006,40 @@ void MorphCopyBlockHelper::MorphStructCases() m_result = CopyFieldByField(); m_transformationDecision = BlockTransformation::FieldByField; } + + // Mark the dest/src structs as DoNotEnreg when they are not being fully referenced as the same type. + // + if (!m_dstDoFldAsg && (m_dstVarDsc != nullptr) && !m_dstSingleLclVarAsg) + { + if (m_dst != m_dstLclNode) + { + // Mark it as DoNotEnregister. + m_comp->lvaSetVarDoNotEnregister(m_dstLclNum DEBUGARG(Compiler::DNER_BlockOp)); + } + else if (m_dstVarDsc->lvPromoted) + { + // Mark it as DoNotEnregister. + m_comp->lvaSetVarDoNotEnregister(m_dstLclNum DEBUGARG(Compiler::DNER_BlockOp)); + } + else if (m_dst->IsMultiRegLclVar()) + { + // Handle this as lvIsMultiRegRet; this signals to SSA that it can't consider these fields + // SSA candidates (we don't have a way to represent multiple SSANums on MultiRegLclVar nodes). + m_dstVarDsc->lvIsMultiRegRet = true; + } + } + + if (!m_srcDoFldAsg && (m_srcVarDsc != nullptr) && !m_srcSingleLclVarAsg) + { + if (m_src != m_srcLclNode) + { + m_comp->lvaSetVarDoNotEnregister(m_srcLclNum DEBUGARG(Compiler::DNER_BlockOp)); + } + else if (m_srcVarDsc->lvPromoted) + { + m_comp->lvaSetVarDoNotEnregister(m_srcLclNum DEBUGARG(Compiler::DNER_BlockOp)); + } + } } //------------------------------------------------------------------------ @@ -1156,8 +1165,6 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() // We will *not* consider this to define the local, but rather have each individual field assign // be a definition. addrSpillOp->gtFlags &= ~(GTF_LIVENESS_MASK); - assert(m_comp->lvaGetPromotionType(addrSpillOp->AsLclVarCommon()->GetLclNum()) != - Compiler::PROMOTION_TYPE_INDEPENDENT); addrSpillIsStackDest = true; // addrSpill represents the address of LclVar[varNum] in our // local stack frame } @@ -1423,6 +1430,7 @@ GenTree* MorphCopyBlockHelper::CopyFieldByField() m_srcLclNode->ChangeOper(GT_LCL_FLD); m_srcLclNode->gtType = destType; m_srcLclNode->AsLclFld()->SetFieldSeq(curFieldSeq); + m_comp->lvaSetVarDoNotEnregister(m_srcLclNum DEBUGARG(Compiler::DNER_LocalField)); srcFld = m_srcLclNode; done = true; } |