Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set lvSingleDef for non TYP_REF locals #85398

Merged
merged 3 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 17 additions & 17 deletions src/coreclr/jit/fgbasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2536,7 +2536,6 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed
{
LclVarDsc* lclDsc = lvaGetDesc(lclNum);
assert(lclDsc->lvSingleDef == 0);
// could restrict this to TYP_REF
lclDsc->lvSingleDef = !lclDsc->lvHasMultipleILStoreOp && !lclDsc->lvHasLdAddrOp;

if (lclDsc->lvSingleDef)
Expand Down Expand Up @@ -3494,19 +3493,20 @@ void Compiler::fgFindBasicBlocks()
// This temp should already have the type of the return value.
JITDUMP("\nInliner: re-using pre-existing spill temp V%02u\n", lvaInlineeReturnSpillTemp);

if (info.compRetType == TYP_REF)
// We may have co-opted an existing temp for the return spill.
// We likely assumed it was single-def at the time, but now
// we can see it has multiple definitions.
if ((fgReturnCount > 1) && (lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef == 1))
{
// We may have co-opted an existing temp for the return spill.
// We likely assumed it was single-def at the time, but now
// we can see it has multiple definitions.
if ((fgReturnCount > 1) && (lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef == 1))
// Make sure it is no longer marked single def. This is only safe
// to do if we haven't ever updated the type.
if (info.compRetType == TYP_REF)
{
// Make sure it is no longer marked single def. This is only safe
// to do if we haven't ever updated the type.
assert(!lvaTable[lvaInlineeReturnSpillTemp].lvClassInfoUpdated);
JITDUMP("Marked return spill temp V%02u as NOT single def temp\n", lvaInlineeReturnSpillTemp);
lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef = 0;
}

JITDUMP("Marked return spill temp V%02u as NOT single def temp\n", lvaInlineeReturnSpillTemp);
lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef = 0;
}
}
else
Expand All @@ -3515,18 +3515,18 @@ void Compiler::fgFindBasicBlocks()
lvaInlineeReturnSpillTemp = lvaGrabTemp(false DEBUGARG("Inline return value spill temp"));
lvaTable[lvaInlineeReturnSpillTemp].lvType = info.compRetType;

// The return spill temp is single def only if the method has a single return block.
if (fgReturnCount == 1)
{
lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef = 1;
JITDUMP("Marked return spill temp V%02u as a single def temp\n", lvaInlineeReturnSpillTemp);
}

// If the method returns a ref class, set the class of the spill temp
// to the method's return value. We may update this later if it turns
// out we can prove the method returns a more specific type.
if (info.compRetType == TYP_REF)
{
// The return spill temp is single def only if the method has a single return block.
if (fgReturnCount == 1)
{
lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef = 1;
JITDUMP("Marked return spill temp V%02u as a single def temp\n", lvaInlineeReturnSpillTemp);
}

CORINFO_CLASS_HANDLE retClassHnd = impInlineInfo->inlineCandidateInfo->methInfo.args.retTypeClass;
if (retClassHnd != nullptr)
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/fgopt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ PhaseStatus Compiler::fgPostImportationCleanup()
{
LclVarDsc* returnSpillVarDsc = lvaGetDesc(lvaInlineeReturnSpillTemp);

if (returnSpillVarDsc->lvSingleDef)
if ((returnSpillVarDsc->lvType == TYP_REF) && returnSpillVarDsc->lvSingleDef)
{
lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact);
}
Expand Down
55 changes: 30 additions & 25 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1942,14 +1942,18 @@ bool Compiler::impSpillStackEntry(unsigned level,
/* Assign the spilled entry to the temp */
impAssignTempGen(tnum, tree, verCurrentState.esStack[level].seTypeInfo.GetClassHandle(), level);

// If temp is newly introduced and a ref type, grab what type info we can.
if (isNewTemp && (lvaTable[tnum].lvType == TYP_REF))
if (isNewTemp)
{
assert(lvaTable[tnum].lvSingleDef == 0);
lvaTable[tnum].lvSingleDef = 1;
JITDUMP("Marked V%02u as a single def temp\n", tnum);
CORINFO_CLASS_HANDLE stkHnd = verCurrentState.esStack[level].seTypeInfo.GetClassHandle();
lvaSetClass(tnum, tree, stkHnd);

// If temp is newly introduced and a ref type, grab what type info we can.
if (lvaTable[tnum].lvType == TYP_REF)
{
CORINFO_CLASS_HANDLE stkHnd = verCurrentState.esStack[level].seTypeInfo.GetClassHandle();
lvaSetClass(tnum, tree, stkHnd);
}

// If we're assigning a GT_RET_EXPR, note the temp over on the call,
// so the inliner can use it in case it needs a return spill temp.
Expand Down Expand Up @@ -8453,12 +8457,12 @@ void Compiler::impImportBlockCode(BasicBlock* block)
impAssignTempGen(tmpNum, op1, tiRetVal.GetClassHandle(), CHECK_SPILL_ALL);
var_types type = genActualType(lvaTable[tmpNum].TypeGet());

assert(lvaTable[tmpNum].lvSingleDef == 0);
lvaTable[tmpNum].lvSingleDef = 1;
JITDUMP("Marked V%02u as a single def local\n", tmpNum);
// Propagate type info to the temp from the stack and the original tree
if (type == TYP_REF)
{
assert(lvaTable[tmpNum].lvSingleDef == 0);
lvaTable[tmpNum].lvSingleDef = 1;
JITDUMP("Marked V%02u as a single def local\n", tmpNum);
lvaSetClass(tmpNum, tree, tiRetVal.GetClassHandle());
}

Expand Down Expand Up @@ -13662,19 +13666,19 @@ unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reas
lvaTable[tmpNum].lvHasILStoreOp = inlineeLocal.lclHasStlocOp;
lvaTable[tmpNum].lvHasMultipleILStoreOp = inlineeLocal.lclHasMultipleStlocOp;

assert(lvaTable[tmpNum].lvSingleDef == 0);

lvaTable[tmpNum].lvSingleDef = !inlineeLocal.lclHasMultipleStlocOp && !inlineeLocal.lclHasLdlocaOp;
if (lvaTable[tmpNum].lvSingleDef)
{
JITDUMP("Marked V%02u as a single def temp\n", tmpNum);
}

// Copy over class handle for ref types. Note this may be a
// shared type -- someday perhaps we can get the exact
// signature and pass in a more precise type.
if (lclTyp == TYP_REF)
{
assert(lvaTable[tmpNum].lvSingleDef == 0);

lvaTable[tmpNum].lvSingleDef = !inlineeLocal.lclHasMultipleStlocOp && !inlineeLocal.lclHasLdlocaOp;
if (lvaTable[tmpNum].lvSingleDef)
{
JITDUMP("Marked V%02u as a single def temp\n", tmpNum);
}

lvaSetClass(tmpNum, inlineeLocal.lclVerTypeInfo.GetClassHandleForObjRef());
}

Expand Down Expand Up @@ -13859,20 +13863,21 @@ GenTree* Compiler::impInlineFetchArg(unsigned lclNum, InlArgInfo* inlArgInfo, In

lvaTable[tmpNum].lvType = lclTyp;

// For ref types, determine the type of the temp.
if (lclTyp == TYP_REF)
// If arg can't be modified, mark it as single def.
// For ref types, determine the class of the arg temp.
if (!argCanBeModified)
{
if (!argCanBeModified)
assert(lvaTable[tmpNum].lvSingleDef == 0);
lvaTable[tmpNum].lvSingleDef = 1;
JITDUMP("Marked V%02u as a single def temp\n", tmpNum);
if (lclTyp == TYP_REF)
{
// If the arg can't be modified in the method
// body, use the type of the value, if
// known. Otherwise, use the declared type.
assert(lvaTable[tmpNum].lvSingleDef == 0);
lvaTable[tmpNum].lvSingleDef = 1;
JITDUMP("Marked V%02u as a single def temp\n", tmpNum);
lvaSetClass(tmpNum, argNode, lclInfo.lclVerTypeInfo.GetClassHandleForObjRef());
}
else
}
else
{
if (lclTyp == TYP_REF)
{
// Arg might be modified, use the declared type of
// the argument.
Expand Down
7 changes: 3 additions & 4 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5476,12 +5476,11 @@ class SpillRetExprHelper
comp->impAssignTempGen(tmp, retExpr, (unsigned)Compiler::CHECK_SPILL_NONE);
*pRetExpr = comp->gtNewLclvNode(tmp, retExpr->TypeGet());

assert(comp->lvaTable[tmp].lvSingleDef == 0);
comp->lvaTable[tmp].lvSingleDef = 1;
JITDUMP("Marked V%02u as a single def temp\n", tmp);
if (retExpr->TypeGet() == TYP_REF)
{
assert(comp->lvaTable[tmp].lvSingleDef == 0);
comp->lvaTable[tmp].lvSingleDef = 1;
JITDUMP("Marked V%02u as a single def temp\n", tmp);

bool isExact = false;
bool isNonNull = false;
CORINFO_CLASS_HANDLE retClsHnd = comp->gtGetClassHandle(retExpr, &isExact, &isNonNull);
Expand Down