Skip to content

Commit ba46901

Browse files
author
Sergey
committed
Improve mustInit for structs.
1 parent ccc25a9 commit ba46901

File tree

4 files changed

+54
-9
lines changed

4 files changed

+54
-9
lines changed

src/coreclr/jit/codegencommon.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4794,14 +4794,41 @@ void CodeGen::genCheckUseBlockInit()
47944794
}
47954795
}
47964796

4797-
/* With compInitMem, all untracked vars will have to be init'ed */
4798-
/* VSW 102460 - Do not force initialization of compiler generated temps,
4799-
unless they are untracked GC type or structs that contain GC pointers */
4800-
CLANG_FORMAT_COMMENT_ANCHOR;
4797+
bool mustInitThisVar = false;
4798+
4799+
const bool isTemp = varDsc->lvIsTemp;
4800+
const bool hasGCPtr = varDsc->HasGCPtr();
4801+
const bool isTracked = varDsc->lvTracked;
4802+
const bool isStruct = varTypeIsStruct(varDsc);
4803+
const bool compInitMem = compiler->info.compInitMem;
48014804

4802-
if ((!varDsc->lvTracked || (varDsc->lvType == TYP_STRUCT)) && varDsc->lvOnFrame)
4805+
if (hasGCPtr && !isTracked)
4806+
{
4807+
JITDUMP("must init V%02u because it has a GC ref\n", varNum);
4808+
mustInitThisVar = true;
4809+
}
4810+
else if (hasGCPtr && isStruct)
4811+
{
4812+
// TODO-1stClassStructs: support precise liveness reporting for such structs.
4813+
JITDUMP("must init a tracked V%02u because it a struct with a GC ref\n", varNum);
4814+
mustInitThisVar = true;
4815+
}
4816+
else
48034817
{
4818+
// We are done with tracked or GC vars, now look at untracked vars without GC refs.
4819+
if (!isTracked)
4820+
{
4821+
assert(!hasGCPtr);
4822+
if (compInitMem && !isTemp)
4823+
{
4824+
JITDUMP("must init V%02u because compInitMem is set and it is not a temp\n", varNum);
4825+
mustInitThisVar = true;
4826+
}
4827+
}
4828+
}
48044829

4830+
if (mustInitThisVar)
4831+
{
48054832
varDsc->lvMustInit = true;
48064833

48074834
if (!counted)

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ class LclVarDsc
971971
var_types lvaArgType();
972972

973973
// Returns true if this variable contains GC pointers (including being a GC pointer itself).
974-
bool HasGCPtr()
974+
bool HasGCPtr() const
975975
{
976976
return varTypeIsGC(lvType) || ((lvType == TYP_STRUCT) && m_layout->HasGCPtr());
977977
}

src/coreclr/jit/lower.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5915,17 +5915,34 @@ void Lowering::CheckNode(Compiler* compiler, GenTree* node)
59155915
{
59165916
unsigned lclNum = node->AsLclVarCommon()->GetLclNum();
59175917
LclVarDsc* lclVar = &compiler->lvaTable[lclNum];
5918-
#ifdef DEBUG
59195918
if (node->TypeIs(TYP_SIMD12))
59205919
{
59215920
assert(compiler->lvaIsFieldOfDependentlyPromotedStruct(lclVar) || (lclVar->lvSize() == 12));
59225921
}
5923-
#endif // DEBUG
59245922
}
59255923
break;
59265924
#endif // TARGET_64BIT
59275925
#endif // SIMD
59285926

5927+
case GT_LCL_VAR_ADDR:
5928+
case GT_LCL_FLD_ADDR:
5929+
{
5930+
const GenTreeLclVarCommon* lclVarAddr = node->AsLclVarCommon();
5931+
const LclVarDsc* varDsc = compiler->lvaGetDesc(lclVarAddr);
5932+
if (((lclVarAddr->gtFlags & GTF_VAR_DEF) != 0) && varDsc->HasGCPtr())
5933+
{
5934+
// Emitter does not correctly handle live updates for LCL_VAR_ADDR
5935+
// when they are not contained, for example, `STOREIND byref(GT_LCL_VAR_ADDR not-contained)`
5936+
// would generate:
5937+
// add r1, sp, 48 // r1 contains address of a lclVar V01.
5938+
// str r0, [r1] // a gc ref becomes live in V01, but emitter would not report it.
5939+
// Make sure that we use uncontained address nodes only for variables
5940+
// that will be marked as mustInit and will be alive throught the whole block even when tracked.
5941+
assert(lclVarAddr->isContained() || !varDsc->lvTracked || varTypeIsStruct(varDsc));
5942+
// TODO: support this assert for uses, see https://github.com/dotnet/runtime/issues/51900.
5943+
}
5944+
}
5945+
59295946
default:
59305947
break;
59315948
}

src/coreclr/jit/optimizer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9760,7 +9760,8 @@ void Compiler::optRemoveRedundantZeroInits()
97609760
if (BitVecOps::IsMember(&bitVecTraits, zeroInitLocals, lclNum) ||
97619761
(lclDsc->lvIsStructField &&
97629762
BitVecOps::IsMember(&bitVecTraits, zeroInitLocals, lclDsc->lvParentLcl)) ||
9763-
(!lclDsc->lvTracked && !fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn)))
9763+
((!lclDsc->lvTracked || !isEntire) &&
9764+
!fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn)))
97649765
{
97659766
// We are guaranteed to have a zero initialization in the prolog or a
97669767
// dominating explicit zero initialization and the local hasn't been redefined

0 commit comments

Comments
 (0)