{
for (unsigned i = lvFieldLclStart; i < lvFieldLclStart + lvFieldCnt; ++i)
{
- comp->lvaTable[i].decRefCnts(comp->lvaMarkRefsWeight, comp, state, false); // Don't propagate
+ comp->lvaTable[i].decRefCnts(weight, comp, state, false); // Don't propagate
}
}
}
assert(!parentvarDsc->lvRegStruct);
if (promotionType == Compiler::PROMOTION_TYPE_DEPENDENT)
{
- parentvarDsc->decRefCnts(comp->lvaMarkRefsWeight, comp, state, false); // Don't propagate
+ parentvarDsc->decRefCnts(weight, comp, state, false); // Don't propagate
}
}
setLvRefCnt((unsigned short)newRefCnt, state);
}
- // This fires when an uninitialize value for 'weight' is used (see lvaMarkRefsWeight)
+ // This fires when an uninitialize value for 'weight' is used
assert(weight != 0xdddddddd);
//
// Increment lvRefCntWtd
{
for (unsigned i = lvFieldLclStart; i < lvFieldLclStart + lvFieldCnt; ++i)
{
- comp->lvaTable[i].incRefCnts(comp->lvaMarkRefsWeight, comp, state, false); // Don't propagate
+ comp->lvaTable[i].incRefCnts(weight, comp, state, false); // Don't propagate
}
}
}
assert(!parentvarDsc->lvRegStruct);
if (promotionType == Compiler::PROMOTION_TYPE_DEPENDENT)
{
- parentvarDsc->incRefCnts(comp->lvaMarkRefsWeight, comp, state, false); // Don't propagate
+ parentvarDsc->incRefCnts(weight, comp, state, false); // Don't propagate
}
}
#endif
}
-/*****************************************************************************
- *
- * Set the lvPrefReg field to reg
- */
-
-inline void LclVarDsc::setPrefReg(regNumber regNum, Compiler* comp)
-{
- regMaskTP regMask;
- if (isFloatRegType(TypeGet()))
- {
- // Check for FP struct-promoted field being passed in integer register
- //
- if (!genIsValidFloatReg(regNum))
- {
- return;
- }
- regMask = genRegMaskFloat(regNum, TypeGet());
- }
- else
- {
- regMask = genRegMask(regNum);
- }
-
-#ifdef _TARGET_ARM_
- // Don't set a preferred register for a TYP_STRUCT that takes more than one register slot
- if ((TypeGet() == TYP_STRUCT) && (lvSize() > REGSIZE_BYTES))
- return;
-#endif
-
- /* Only interested if we have a new register bit set */
- if (lvPrefReg & regMask)
- {
- return;
- }
-
-#ifdef DEBUG
- if (comp->verbose)
- {
- if (lvPrefReg)
- {
- printf("Change preferred register for V%02u from ", this - comp->lvaTable);
- dspRegMask(lvPrefReg);
- }
- else
- {
- printf("Set preferred register for V%02u", this - comp->lvaTable);
- }
- printf(" to ");
- dspRegMask(regMask);
- printf("\n");
- }
-#endif
-
- /* Overwrite the lvPrefReg field */
-
- lvPrefReg = (regMaskSmall)regMask;
-}
-
-/*****************************************************************************
- *
- * Add regMask to the lvPrefReg field
- */
-
-inline void LclVarDsc::addPrefReg(regMaskTP regMask, Compiler* comp)
-{
- assert(regMask != RBM_NONE);
-
-#ifdef _TARGET_ARM_
- // Don't set a preferred register for a TYP_STRUCT that takes more than one register slot
- if ((lvType == TYP_STRUCT) && (lvSize() > REGSIZE_BYTES))
- return;
-#endif
-
- /* Only interested if we have a new register bit set */
- if (lvPrefReg & regMask)
- {
- return;
- }
-
-#ifdef DEBUG
- if (comp->verbose)
- {
- if (lvPrefReg)
- {
- printf("Additional preferred register for V%02u from ", this - comp->lvaTable);
- dspRegMask(lvPrefReg);
- }
- else
- {
- printf("Set preferred register for V%02u", this - comp->lvaTable);
- }
- printf(" to ");
- dspRegMask(lvPrefReg | regMask);
- printf("\n");
- }
-#endif
-
- /* Update the lvPrefReg field */
-
- lvPrefReg |= regMask;
-}
-
/*****************************************************************************
*
* The following returns the mask of all tracked locals
#if FEATURE_MULTIREG_ARGS
varDsc->lvOtherArgReg = REG_NA;
#endif
- varDsc->setPrefReg(varDsc->lvArgReg, this);
varDsc->lvOnFrame = true; // The final home for this incoming register might be our local stack frame
#ifdef DEBUG
#if FEATURE_MULTIREG_ARGS
varDsc->lvOtherArgReg = REG_NA;
#endif
- varDsc->setPrefReg(varDsc->lvArgReg, this);
varDsc->lvOnFrame = true; // The final home for this incoming register might be our local stack frame
info.compRetBuffDefStack = 0;
if (secondEightByteType != TYP_UNDEF)
{
varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(secondAllocatedRegArgNum, secondEightByteType);
- varDsc->addPrefReg(genRegMask(varDsc->lvOtherArgReg), this);
}
#else // ARM32 or ARM64
varDsc->lvArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum, TYP_I_IMPL);
if (cSlots == 2)
{
varDsc->lvOtherArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_I_IMPL);
- varDsc->addPrefReg(genRegMask(varDsc->lvOtherArgReg), this);
}
#endif // _TARGET_ARM64_
#endif // defined(UNIX_AMD64_ABI)
varDsc->lvArgReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum, argType);
}
- varDsc->setPrefReg(varDsc->lvArgReg, this);
-
#ifdef _TARGET_ARM_
if (varDsc->TypeGet() == TYP_LONG)
{
varDsc->lvOtherReg = genMapRegArgNumToRegNum(firstAllocatedRegArgNum + 1, TYP_INT);
- varDsc->addPrefReg(genRegMask(varDsc->lvOtherReg), this);
}
#endif // _TARGET_ARM_
#if FEATURE_MULTIREG_ARGS
varDsc->lvOtherArgReg = REG_NA;
#endif
- varDsc->setPrefReg(varDsc->lvArgReg, this);
varDsc->lvOnFrame = true; // The final home for this incoming register might be our local stack frame
varDscInfo->intRegArgNum++;
#if FEATURE_MULTIREG_ARGS
varDsc->lvOtherArgReg = REG_NA;
#endif
- varDsc->setPrefReg(varDsc->lvArgReg, this);
varDsc->lvOnFrame = true; // The final home for this incoming register might be our local stack frame
#ifdef _TARGET_ARM_
// This has to be spilled right in front of the real arguments and we have
{
fieldVarDsc->lvIsRegArg = true;
fieldVarDsc->lvArgReg = varDsc->lvArgReg;
- fieldVarDsc->setPrefReg(varDsc->lvArgReg, this); // Set the preferred register
#if FEATURE_MULTIREG_ARGS && defined(FEATURE_SIMD)
if (varTypeIsSIMD(fieldVarDsc) && !lvaIsImplicitByRefLocal(lclNum))
{
}
#endif // FEATURE_MULTIREG_ARGS && defined(FEATURE_SIMD)
- lvaMarkRefsWeight = BB_UNITY_WEIGHT; // incRefCnts can use this compiler global variable
fieldVarDsc->incRefCnts(BB_UNITY_WEIGHT, this,
RCS_EARLY); // increment the ref count for prolog initialization
}
* Return positive if dsc2 has a higher ref count
* Return negative if dsc1 has a higher ref count
* Return zero if the ref counts are the same
- * lvPrefReg is only used to break ties
*/
/* static */
/* We have equal ref counts and weighted ref counts */
/* Break the tie by: */
- /* Increasing the weight by 2 if we have exactly one bit set in lvPrefReg */
- /* Increasing the weight by 1 if we have more than one bit set in lvPrefReg */
+ /* Increasing the weight by 2 if we are a register arg */
/* Increasing the weight by 0.5 if we are a GC type */
/* Increasing the weight by 0.5 if we were enregistered in the previous pass */
if (weight1)
{
- if (dsc1->lvPrefReg)
+ if (dsc1->lvIsRegArg)
{
- if ((dsc1->lvPrefReg & ~RBM_BYTE_REG_FLAG) && genMaxOneBit((unsigned)dsc1->lvPrefReg))
- {
- weight1 += 2 * BB_UNITY_WEIGHT;
- }
- else
- {
- weight1 += 1 * BB_UNITY_WEIGHT;
- }
+ weight2 += 2 * BB_UNITY_WEIGHT;
}
+
if (varTypeIsGC(dsc1->TypeGet()))
{
weight1 += BB_UNITY_WEIGHT / 2;
if (weight2)
{
- if (dsc2->lvPrefReg)
+ if (dsc2->lvIsRegArg)
{
- if ((dsc2->lvPrefReg & ~RBM_BYTE_REG_FLAG) && genMaxOneBit((unsigned)dsc2->lvPrefReg))
- {
- weight2 += 2 * BB_UNITY_WEIGHT;
- }
- else
- {
- weight2 += 1 * BB_UNITY_WEIGHT;
- }
+ weight2 += 2 * BB_UNITY_WEIGHT;
}
+
if (varTypeIsGC(dsc2->TypeGet()))
{
weight2 += BB_UNITY_WEIGHT / 2;
}
#endif
- /* Increase the weight by 2 if we have exactly one bit set in lvPrefReg */
- /* Increase the weight by 1 if we have more than one bit set in lvPrefReg */
-
- if (weight1 && dsc1->lvPrefReg)
+ if (weight1 && dsc1->lvIsRegArg)
{
- if ((dsc1->lvPrefReg & ~RBM_BYTE_REG_FLAG) && genMaxOneBit((unsigned)dsc1->lvPrefReg))
- {
- weight1 += 2 * BB_UNITY_WEIGHT;
- }
- else
- {
- weight1 += 1 * BB_UNITY_WEIGHT;
- }
+ weight1 += 2 * BB_UNITY_WEIGHT;
}
- if (weight2 && dsc2->lvPrefReg)
+ if (weight2 && dsc2->lvIsRegArg)
{
- if ((dsc2->lvPrefReg & ~RBM_BYTE_REG_FLAG) && genMaxOneBit((unsigned)dsc2->lvPrefReg))
- {
- weight2 += 2 * BB_UNITY_WEIGHT;
- }
- else
- {
- weight2 += 1 * BB_UNITY_WEIGHT;
- }
+ weight2 += 2 * BB_UNITY_WEIGHT;
}
if (weight2 > weight1)
gtDispLclVar((unsigned)(lvaRefSorted[lclNum] - lvaTable));
printf(" [%6s]: refCnt = %4u, refCntWtd = %6s", varTypeName(lvaRefSorted[lclNum]->TypeGet()), refCnt,
refCntWtd2str(refCntWtd));
-
- regMaskSmall pref = lvaRefSorted[lclNum]->lvPrefReg;
- if (pref)
- {
- printf(" pref ");
- dspRegMask(pref);
- }
printf("\n");
}
return type;
}
-/*****************************************************************************
- *
- * This is called by lvaMarkLclRefsCallback() to do variable ref marking
- */
+//------------------------------------------------------------------------
+// lvaMarkLclRefs: increment local var references counts and more
+//
+// Arguments:
+// tree - some node in a tree
+// block - block that the tree node belongs to
+// stmt - stmt that the tree node belongs to
+//
+// Notes:
+// Invoked via the MarkLocalVarsVisitor
-void Compiler::lvaMarkLclRefs(GenTree* tree)
+void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, GenTreeStmt* stmt)
{
+ const BasicBlock::weight_t weight = block->getBBWeight(this);
+
/* Is this a call to unmanaged code ? */
if (tree->gtOper == GT_CALL && tree->gtFlags & GTF_CALL_UNMANAGED)
{
LclVarDsc* varDsc = lvaTable + lclNum;
/* Increment the ref counts twice */
- varDsc->incRefCnts(lvaMarkRefsWeight, this);
- varDsc->incRefCnts(lvaMarkRefsWeight, this);
+ varDsc->incRefCnts(weight, this);
+ varDsc->incRefCnts(weight, this);
}
}
GenTree* op1 = tree->gtOp.gtOp1;
GenTree* op2 = tree->gtOp.gtOp2;
- /* Set target register for RHS local if assignment is of a "small" type */
-
- if (varTypeIsByte(tree->gtType))
- {
- unsigned lclNum;
- LclVarDsc* varDsc = nullptr;
-
- if (op2->gtOper == GT_LCL_VAR)
- {
- lclNum = op2->gtLclVarCommon.gtLclNum;
- noway_assert(lclNum < lvaCount);
- varDsc = &lvaTable[lclNum];
- }
-#if CPU_HAS_BYTE_REGS
- if (varDsc)
- varDsc->addPrefReg(RBM_BYTE_REG_FLAG, this);
-#endif
- }
-
#if OPT_BOOL_OPS
/* Is this an assignment to a local variable? */
#endif
}
-#ifdef _TARGET_XARCH_
- /* Special case: integer shift node by a variable amount */
-
- if (tree->OperIsShiftOrRotate())
- {
- if (tree->gtType == TYP_INT)
- {
- GenTree* op2 = tree->gtOp.gtOp2;
-
- if (op2->gtOper == GT_LCL_VAR)
- {
- unsigned lclNum = op2->gtLclVarCommon.gtLclNum;
- assert(lclNum < lvaCount);
- lvaTable[lclNum].setPrefReg(REG_ECX, this);
- }
- }
-
- return;
- }
-#endif
-
if ((tree->gtOper != GT_LCL_VAR) && (tree->gtOper != GT_LCL_FLD))
{
return;
/* Increment the reference counts */
- varDsc->incRefCnts(lvaMarkRefsWeight, this);
+ varDsc->incRefCnts(weight, this);
if (lvaVarAddrExposed(lclNum))
{
}
#if ASSERTION_PROP
- if (fgDomsComputed && IsDominatedByExceptionalEntry(lvaMarkRefsCurBlock))
+ if (fgDomsComputed && IsDominatedByExceptionalEntry(block))
{
SetVolatileHint(varDsc);
}
else
{
varDsc->lvSingleDef = true;
- varDsc->lvDefStmt = lvaMarkRefsCurStmt;
+ varDsc->lvDefStmt = stmt;
}
}
else // otherwise this is a ref of our variable
// Lazy initialization
BlockSetOps::AssignNoCopy(this, varDsc->lvRefBlks, BlockSetOps::MakeEmpty(this));
}
- BlockSetOps::AddElemD(this, varDsc->lvRefBlks, lvaMarkRefsCurBlock->bbNum);
+ BlockSetOps::AddElemD(this, varDsc->lvRefBlks, block->bbNum);
}
}
#endif // ASSERTION_PROP
{
class MarkLocalVarsVisitor final : public GenTreeVisitor<MarkLocalVarsVisitor>
{
+ private:
+ BasicBlock* m_block;
+ GenTreeStmt* m_stmt;
+
public:
enum
{
DoPreOrder = true,
};
- MarkLocalVarsVisitor(Compiler* compiler) : GenTreeVisitor<MarkLocalVarsVisitor>(compiler)
+ MarkLocalVarsVisitor(Compiler* compiler, BasicBlock* block, GenTreeStmt* stmt)
+ : GenTreeVisitor<MarkLocalVarsVisitor>(compiler), m_block(block), m_stmt(stmt)
{
}
Compiler::fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
{
- m_compiler->lvaMarkLclRefs(*use);
+ m_compiler->lvaMarkLclRefs(*use, m_block, m_stmt);
return WALK_CONTINUE;
}
};
-#if ASSERTION_PROP
- lvaMarkRefsCurBlock = block;
-#endif
- lvaMarkRefsWeight = block->getBBWeight(this);
-
-#ifdef DEBUG
- if (verbose)
- {
- printf("\n*** marking local variables in block BB%02u (weight=%s)\n", block->bbNum,
- refCntWtd2str(lvaMarkRefsWeight));
- }
-#endif
+ JITDUMP("\n*** marking local variables in block BB%02u (weight=%s)\n", block->bbNum,
+ refCntWtd2str(block->getBBWeight(this)));
- MarkLocalVarsVisitor visitor(this);
- for (GenTree* tree = block->FirstNonPhiDef(); tree; tree = tree->gtNext)
+ for (GenTreeStmt* stmt = block->FirstNonPhiDef(); stmt != nullptr; stmt = stmt->getNextStmt())
{
- assert(tree->gtOper == GT_STMT);
-
-#if ASSERTION_PROP
- lvaMarkRefsCurStmt = tree;
-#endif
-
-#ifdef DEBUG
- if (verbose)
- {
- gtDispTree(tree);
- }
-#endif
-
- visitor.WalkTree(&tree->gtStmt.gtStmtExpr, nullptr);
+ MarkLocalVarsVisitor visitor(this, block, stmt);
+ DISPTREE(stmt);
+ visitor.WalkTree(&stmt->gtStmtExpr, nullptr);
}
}