{
LclVarDsc* lclDsc = lvaGetDesc(lclNum);
assert(lclDsc->lvSingleDef == 0);
- // could restrict this to TYP_REF
lclDsc->lvSingleDef = !lclDsc->lvHasMultipleILStoreOp && !lclDsc->lvHasLdAddrOp;
if (lclDsc->lvSingleDef)
// 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
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)
{
/* 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.
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());
}
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());
}
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.