Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Andreenko <seandree@microsoft.com>2021-07-01 20:31:58 +0300
committerGitHub <noreply@github.com>2021-07-01 20:31:58 +0300
commiteeadfdb2f57e607241b9b09ada1ef08717e618f6 (patch)
treec6cbe2308d4daad66cdd4aaae8a7edfc35c7869e /src/coreclr/jit
parent7298a534a00d21ab275576b89f2f29126bbc83b1 (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.cpp4
-rw-r--r--src/coreclr/jit/compiler.h5
-rw-r--r--src/coreclr/jit/compiler.hpp5
-rw-r--r--src/coreclr/jit/decomposelongs.cpp2
-rw-r--r--src/coreclr/jit/lclvars.cpp20
-rw-r--r--src/coreclr/jit/lsra.cpp4
-rw-r--r--src/coreclr/jit/morph.cpp1
-rw-r--r--src/coreclr/jit/morphblock.cpp104
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;
}