summaryrefslogtreecommitdiff
path: root/src/jit
diff options
context:
space:
mode:
authormikedn <onemihaid@hotmail.com>2018-08-26 01:29:28 +0300
committerSergey Andreenko <seandree@microsoft.com>2018-08-25 15:29:28 -0700
commit9951a1b06f1279fdf8ad465dff355fc38238211f (patch)
treecc50b25b0f2d3e3317f3765fb7496a9cb7402870 /src/jit
parenta1404cafbe1cd15a5c0cfbd4995ad97694b708bd (diff)
downloadcoreclr-9951a1b06f1279fdf8ad465dff355fc38238211f.tar.gz
coreclr-9951a1b06f1279fdf8ad465dff355fc38238211f.tar.bz2
coreclr-9951a1b06f1279fdf8ad465dff355fc38238211f.zip
Streamline fgExcludeFromSsa (#15351)
This function is relatively expensive due to the many checks it does. Adding an LclVarDsc "in SSA" bit that is set during SSA construction by calling fgExcludeFromSsa only once per variable results in 0.35% drop in instructions retired. Most of the checks done in fgExcludeFromSsa are implied by lvTracked and they could probably be converted to asserts. But lvOverlappingFields is not implied by lvTracked so even if all redundant checks are converted to asserts fgExcludeFromSsa still needs 2 checks rather than just one. Incidentally, this difference between tracked variables and SSA variables results in SSA and value numbers being assigned to some variables that are actually excluded from SSA - SsaBuilder::RenameVariables and fgValueNumber assign numbers to all live in fgFirstBB variables that require initialization without checking fgExcludeFromSsa first. Structs with overlapping fields are not common but properly excluding them is still enough to save 0.15% memory when compiling corelib. - Replace calls to fgExcludeFromSsa with calls to lvaInSsa (the old name is kind of weird, it has nothing to do with the flow graph and "exclude" results in double negation) - Move fgExcludeFromSsa logic to SsaBuild::IncludeInSsa and use it to initialize LclVarDsc::lvInSsa for all variables - Change RenameVariables and fgValueNumber to call lvaInSsa before assigning numbers to live in fgFirstBB variables
Diffstat (limited to 'src/jit')
-rw-r--r--src/jit/assertionprop.cpp4
-rw-r--r--src/jit/compiler.h12
-rw-r--r--src/jit/compiler.hpp44
-rw-r--r--src/jit/copyprop.cpp8
-rw-r--r--src/jit/earlyprop.cpp4
-rw-r--r--src/jit/morph.cpp2
-rw-r--r--src/jit/optimizer.cpp6
-rw-r--r--src/jit/ssabuilder.cpp79
-rw-r--r--src/jit/ssabuilder.h2
-rw-r--r--src/jit/valuenum.cpp40
10 files changed, 115 insertions, 86 deletions
diff --git a/src/jit/assertionprop.cpp b/src/jit/assertionprop.cpp
index ebf118038b..87cf677b5e 100644
--- a/src/jit/assertionprop.cpp
+++ b/src/jit/assertionprop.cpp
@@ -1296,8 +1296,8 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1,
noway_assert(lclNum < lvaCount);
LclVarDsc* lclVar = &lvaTable[lclNum];
- // If the local variable has its address exposed then bail
- if (fgExcludeFromSsa(lclNum))
+ // If the local variable is not in SSA then bail
+ if (!lvaInSsa(lclNum))
{
goto DONE_ASSERTION;
}
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index d3179509d5..a7629fcbe7 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -330,6 +330,8 @@ public:
unsigned char lvFieldAccessed : 1; // The var is a struct local, and a field of the variable is accessed. Affects
// struct promotion.
+ unsigned char lvInSsa : 1; // The variable is in SSA form (set by SsaBuilder)
+
#ifdef DEBUG
// These further document the reasons for setting "lvDoNotEnregister". (Note that "lvAddrExposed" is one of the
// reasons;
@@ -3025,6 +3027,13 @@ public:
unsigned lvaGSSecurityCookie; // LclVar number
bool lvaTempsHaveLargerOffsetThanVars();
+ // Returns "true" iff local variable "lclNum" is in SSA form.
+ bool lvaInSsa(unsigned lclNum)
+ {
+ assert(lclNum < lvaCount);
+ return lvaTable[lclNum].lvInSsa;
+ }
+
unsigned lvaSecurityObject; // variable representing the security object on the stack
unsigned lvaStubArgumentVar; // variable representing the secret stub argument coming in EAX
@@ -4133,9 +4142,6 @@ public:
unsigned fgSsaPassesCompleted; // Number of times fgSsaBuild has been run.
- // Returns "true" iff lcl "lclNum" should be excluded from SSA.
- inline bool fgExcludeFromSsa(unsigned lclNum);
-
// Returns "true" if a struct temp of the given type requires needs zero init in this block
inline bool fgStructTempNeedsExplicitZeroInit(LclVarDsc* varDsc, BasicBlock* block);
diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp
index 45d0828582..cdaa04a53d 100644
--- a/src/jit/compiler.hpp
+++ b/src/jit/compiler.hpp
@@ -4276,48 +4276,6 @@ bool Compiler::fgStructTempNeedsExplicitZeroInit(LclVarDsc* varDsc, BasicBlock*
}
/*****************************************************************************/
-bool Compiler::fgExcludeFromSsa(unsigned lclNum)
-{
- if (opts.MinOpts())
- {
- return true; // If we're doing MinOpts, no SSA vars.
- }
-
- LclVarDsc* varDsc = &lvaTable[lclNum];
-
- if (varDsc->lvAddrExposed)
- {
- return true; // We exclude address-exposed variables.
- }
- if (!varDsc->lvTracked)
- {
- return true; // SSA is only done for tracked variables
- }
- // lvPromoted structs are never tracked...
- assert(!varDsc->lvPromoted);
-
- if (varDsc->lvOverlappingFields)
- {
- return true; // Don't use SSA on structs that have overlapping fields
- }
-
- if (varDsc->lvIsStructField && (lvaGetParentPromotionType(lclNum) != PROMOTION_TYPE_INDEPENDENT))
- {
- // SSA must exclude struct fields that are not independent
- // - because we don't model the struct assignment properly when multiple fields can be assigned by one struct
- // assignment.
- // - SSA doesn't allow a single node to contain multiple SSA definitions.
- // - and PROMOTION_TYPE_DEPENDEDNT fields are never candidates for a register.
- //
- // Example mscorlib method: CompatibilitySwitches:IsCompatibilitySwitchSet
- //
- return true;
- }
- // otherwise this variable is *not* excluded for SSA
- return false;
-}
-
-/*****************************************************************************/
ValueNum Compiler::GetUseAsgDefVNOrTreeVN(GenTree* op)
{
if (op->gtFlags & GTF_VAR_USEASG)
@@ -4336,7 +4294,7 @@ ValueNum Compiler::GetUseAsgDefVNOrTreeVN(GenTree* op)
unsigned Compiler::GetSsaNumForLocalVarDef(GenTree* lcl)
{
// Address-taken variables don't have SSA numbers.
- if (fgExcludeFromSsa(lcl->AsLclVarCommon()->gtLclNum))
+ if (!lvaInSsa(lcl->AsLclVarCommon()->gtLclNum))
{
return SsaConfig::RESERVED_SSA_NUM;
}
diff --git a/src/jit/copyprop.cpp b/src/jit/copyprop.cpp
index a83682df97..a1beccacb5 100644
--- a/src/jit/copyprop.cpp
+++ b/src/jit/copyprop.cpp
@@ -38,7 +38,7 @@ void Compiler::optBlockCopyPropPopStacks(BasicBlock* block, LclNumToGenTreePtrSt
continue;
}
unsigned lclNum = tree->gtLclVarCommon.gtLclNum;
- if (fgExcludeFromSsa(lclNum))
+ if (!lvaInSsa(lclNum))
{
continue;
}
@@ -153,8 +153,8 @@ void Compiler::optCopyProp(BasicBlock* block, GenTree* stmt, GenTree* tree, LclN
}
unsigned lclNum = tree->AsLclVarCommon()->GetLclNum();
- // Skip address exposed variables.
- if (fgExcludeFromSsa(lclNum))
+ // Skip non-SSA variables.
+ if (!lvaInSsa(lclNum))
{
return;
}
@@ -287,7 +287,7 @@ void Compiler::optCopyProp(BasicBlock* block, GenTree* stmt, GenTree* tree, LclN
*/
bool Compiler::optIsSsaLocal(GenTree* tree)
{
- return tree->IsLocal() && !fgExcludeFromSsa(tree->AsLclVarCommon()->GetLclNum());
+ return tree->IsLocal() && lvaInSsa(tree->AsLclVarCommon()->GetLclNum());
}
//------------------------------------------------------------------------------
diff --git a/src/jit/earlyprop.cpp b/src/jit/earlyprop.cpp
index 787dc84de5..edbcefdf69 100644
--- a/src/jit/earlyprop.cpp
+++ b/src/jit/earlyprop.cpp
@@ -273,7 +273,7 @@ GenTree* Compiler::optEarlyPropRewriteTree(GenTree* tree)
return nullptr;
}
- if (!objectRefPtr->OperIsScalarLocal() || fgExcludeFromSsa(objectRefPtr->AsLclVarCommon()->GetLclNum()))
+ if (!objectRefPtr->OperIsScalarLocal() || !lvaInSsa(objectRefPtr->AsLclVarCommon()->GetLclNum()))
{
return nullptr;
@@ -442,7 +442,7 @@ GenTree* Compiler::optPropGetValueRec(unsigned lclNum, unsigned ssaNum, optPropK
assert(treelhs == treeDefParent->gtGetOp1());
GenTree* treeRhs = treeDefParent->gtGetOp2();
- if (treeRhs->OperIsScalarLocal() && !fgExcludeFromSsa(treeRhs->AsLclVarCommon()->GetLclNum()))
+ if (treeRhs->OperIsScalarLocal() && lvaInSsa(treeRhs->AsLclVarCommon()->GetLclNum()))
{
// Recursively track the Rhs
unsigned rhsLclNum = treeRhs->AsLclVarCommon()->GetLclNum();
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 806a3cfba7..dd570d3256 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -17712,7 +17712,7 @@ void Compiler::fgRetypeImplicitByRefArgs()
// Since this previously was a TYP_STRUCT and we have changed it to a TYP_BYREF
// make sure that the following flag is not set as these will force SSA to
- // exclude tracking/enregistering these LclVars. (see fgExcludeFromSsa)
+ // exclude tracking/enregistering these LclVars. (see SsaBuilder::IncludeInSsa)
//
varDsc->lvOverlappingFields = 0; // This flag could have been set, clear it.
diff --git a/src/jit/optimizer.cpp b/src/jit/optimizer.cpp
index 83f3a021e2..73c79c9c2a 100644
--- a/src/jit/optimizer.cpp
+++ b/src/jit/optimizer.cpp
@@ -7178,7 +7178,7 @@ bool Compiler::optTreeIsValidAtLoopHead(GenTree* tree, unsigned lnum)
unsigned lclNum = lclVar->gtLclNum;
// The lvlVar must be have an Ssa tracked lifetime
- if (fgExcludeFromSsa(lclNum))
+ if (!lvaInSsa(lclNum))
{
return false;
}
@@ -7627,7 +7627,7 @@ void Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
{
// If it's a local byref for which we recorded a value number, use that...
GenTreeLclVar* argLcl = arg->AsLclVar();
- if (!fgExcludeFromSsa(argLcl->GetLclNum()))
+ if (lvaInSsa(argLcl->GetLclNum()))
{
ValueNum argVN =
lvaTable[argLcl->GetLclNum()].GetPerSsaData(argLcl->GetSsaNum())->m_vnPair.GetLiberal();
@@ -7717,7 +7717,7 @@ void Compiler::optComputeLoopSideEffectsOfBlock(BasicBlock* blk)
if (rhsVN != ValueNumStore::NoVN)
{
rhsVN = vnStore->VNNormVal(rhsVN);
- if (!fgExcludeFromSsa(lhsLcl->GetLclNum()))
+ if (lvaInSsa(lhsLcl->GetLclNum()))
{
lvaTable[lhsLcl->GetLclNum()]
.GetPerSsaData(lhsLcl->GetSsaNum())
diff --git a/src/jit/ssabuilder.cpp b/src/jit/ssabuilder.cpp
index b4bb8afa67..d7347c2d87 100644
--- a/src/jit/ssabuilder.cpp
+++ b/src/jit/ssabuilder.cpp
@@ -687,10 +687,6 @@ void SsaBuilder::InsertPhiFunctions(BasicBlock** postOrder, int count)
{
JITDUMP("*************** In SsaBuilder::InsertPhiFunctions()\n");
- // Compute liveness on the graph.
- m_pCompiler->fgLocalVarLiveness();
- EndPhase(PHASE_BUILD_SSA_LIVENESS);
-
// Compute dominance frontier.
BlkToBlkVectorMap mapDF(m_allocator);
ComputeDominanceFrontiers(postOrder, count, &mapDF);
@@ -722,7 +718,7 @@ void SsaBuilder::InsertPhiFunctions(BasicBlock** postOrder, int count)
unsigned lclNum = m_pCompiler->lvaTrackedToVarNum[varIndex];
DBG_SSA_JITDUMP(" Considering local var V%02u:\n", lclNum);
- if (m_pCompiler->fgExcludeFromSsa(lclNum))
+ if (!m_pCompiler->lvaInSsa(lclNum))
{
DBG_SSA_JITDUMP(" Skipping because it is excluded.\n");
continue;
@@ -914,7 +910,7 @@ void SsaBuilder::TreeRenameVariables(GenTree* tree, BasicBlock* block, SsaRename
unsigned lclNum = tree->gtLclVarCommon.gtLclNum;
// Is this a variable we exclude from SSA?
- if (m_pCompiler->fgExcludeFromSsa(lclNum))
+ if (!m_pCompiler->lvaInSsa(lclNum))
{
tree->gtLclVarCommon.SetSsaNum(SsaConfig::RESERVED_SSA_NUM);
return;
@@ -1526,20 +1522,25 @@ void SsaBuilder::RenameVariables(BlkToBlkVectorMap* domTree, SsaRenameState* pRe
// The first thing we do is treat parameters and must-init variables as if they have a
// virtual definition before entry -- they start out at SSA name 1.
- for (unsigned i = 0; i < m_pCompiler->lvaCount; i++)
+ for (unsigned lclNum = 0; lclNum < m_pCompiler->lvaCount; lclNum++)
{
- LclVarDsc* varDsc = &m_pCompiler->lvaTable[i];
+ if (!m_pCompiler->lvaInSsa(lclNum))
+ {
+ continue;
+ }
+
+ LclVarDsc* varDsc = &m_pCompiler->lvaTable[lclNum];
+ assert(varDsc->lvTracked);
if (varDsc->lvIsParam || m_pCompiler->info.compInitMem || varDsc->lvMustInit ||
- (varDsc->lvTracked &&
- VarSetOps::IsMember(m_pCompiler, m_pCompiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex)))
+ VarSetOps::IsMember(m_pCompiler, m_pCompiler->fgFirstBB->bbLiveIn, varDsc->lvVarIndex))
{
unsigned ssaNum = varDsc->lvPerSsaData.AllocSsaNum(m_allocator);
// In ValueNum we'd assume un-inited variables get FIRST_SSA_NUM.
assert(ssaNum == SsaConfig::FIRST_SSA_NUM);
- pRenameState->Push(nullptr, i, ssaNum);
+ pRenameState->Push(nullptr, lclNum, ssaNum);
}
}
@@ -1729,6 +1730,16 @@ void SsaBuilder::Build()
ComputeDominators(postOrder, count, domTree);
EndPhase(PHASE_BUILD_SSA_DOMS);
+ // Compute liveness on the graph.
+ m_pCompiler->fgLocalVarLiveness();
+ EndPhase(PHASE_BUILD_SSA_LIVENESS);
+
+ // Mark all variables that will be tracked by SSA
+ for (unsigned lclNum = 0; lclNum < m_pCompiler->lvaCount; lclNum++)
+ {
+ m_pCompiler->lvaTable[lclNum].lvInSsa = IncludeInSsa(lclNum);
+ }
+
// Insert phi functions.
InsertPhiFunctions(postOrder, count);
@@ -1791,6 +1802,52 @@ void SsaBuilder::SetupBBRoot()
}
}
+//------------------------------------------------------------------------
+// IncludeInSsa: Check if the specified variable can be included in SSA.
+//
+// Arguments:
+// lclNum - the variable number
+//
+// Return Value:
+// true if the variable is included in SSA
+//
+bool SsaBuilder::IncludeInSsa(unsigned lclNum)
+{
+ LclVarDsc* varDsc = &m_pCompiler->lvaTable[lclNum];
+
+ if (varDsc->lvAddrExposed)
+ {
+ return false; // We exclude address-exposed variables.
+ }
+ if (!varDsc->lvTracked)
+ {
+ return false; // SSA is only done for tracked variables
+ }
+ // lvPromoted structs are never tracked...
+ assert(!varDsc->lvPromoted);
+
+ if (varDsc->lvOverlappingFields)
+ {
+ return false; // Don't use SSA on structs that have overlapping fields
+ }
+
+ if (varDsc->lvIsStructField &&
+ (m_pCompiler->lvaGetParentPromotionType(lclNum) != Compiler::PROMOTION_TYPE_INDEPENDENT))
+ {
+ // SSA must exclude struct fields that are not independent
+ // - because we don't model the struct assignment properly when multiple fields can be assigned by one struct
+ // assignment.
+ // - SSA doesn't allow a single node to contain multiple SSA definitions.
+ // - and PROMOTION_TYPE_DEPENDEDNT fields are never candidates for a register.
+ //
+ // Example mscorlib method: CompatibilitySwitches:IsCompatibilitySwitchSet
+ //
+ return false;
+ }
+ // otherwise this variable is included in SSA
+ return true;
+}
+
#ifdef DEBUG
// This method asserts that SSA name constraints specified are satisfied.
void Compiler::JitTestCheckSSA()
diff --git a/src/jit/ssabuilder.h b/src/jit/ssabuilder.h
index 27934c8aac..eab25549df 100644
--- a/src/jit/ssabuilder.h
+++ b/src/jit/ssabuilder.h
@@ -24,6 +24,8 @@ private:
m_pCompiler->EndPhase(phase);
}
+ bool IncludeInSsa(unsigned lclNum);
+
public:
// Constructor
SsaBuilder(Compiler* pCompiler);
diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp
index 8d07436402..9ab6098b33 100644
--- a/src/jit/valuenum.cpp
+++ b/src/jit/valuenum.cpp
@@ -4756,9 +4756,16 @@ void Compiler::fgValueNumber()
// Start by giving incoming arguments value numbers.
// Also give must-init vars a zero of their type.
- for (unsigned i = 0; i < lvaCount; i++)
+ for (unsigned lclNum = 0; lclNum < lvaCount; lclNum++)
{
- LclVarDsc* varDsc = &lvaTable[i];
+ if (!lvaInSsa(lclNum))
+ {
+ continue;
+ }
+
+ LclVarDsc* varDsc = &lvaTable[lclNum];
+ assert(varDsc->lvTracked);
+
if (varDsc->lvIsParam)
{
// We assume that code equivalent to this variable initialization loop
@@ -4767,13 +4774,13 @@ void Compiler::fgValueNumber()
// SSA numbers always start from FIRST_SSA_NUM, and we give the value number to SSA name FIRST_SSA_NUM.
// We use the VNF_InitVal(i) from here so we know that this value is loop-invariant
// in all loops.
- ValueNum initVal = vnStore->VNForFunc(varDsc->TypeGet(), VNF_InitVal, vnStore->VNForIntCon(i));
+ ValueNum initVal = vnStore->VNForFunc(varDsc->TypeGet(), VNF_InitVal, vnStore->VNForIntCon(lclNum));
LclSsaVarDsc* ssaDef = varDsc->GetPerSsaData(SsaConfig::FIRST_SSA_NUM);
ssaDef->m_vnPair.SetBoth(initVal);
ssaDef->m_defLoc.m_blk = fgFirstBB;
}
else if (info.compInitMem || varDsc->lvMustInit ||
- (varDsc->lvTracked && VarSetOps::IsMember(this, fgFirstBB->bbLiveIn, varDsc->lvVarIndex)))
+ VarSetOps::IsMember(this, fgFirstBB->bbLiveIn, varDsc->lvVarIndex))
{
// The last clause covers the use-before-def variables (the ones that are live-in to the the first block),
// these are variables that are read before being initialized (at least on some control flow paths)
@@ -4804,7 +4811,7 @@ void Compiler::fgValueNumber()
else
{
// Here we have uninitialized TYP_BYREF
- initVal = vnStore->VNForFunc(typ, VNF_InitVal, vnStore->VNForIntCon(i));
+ initVal = vnStore->VNForFunc(typ, VNF_InitVal, vnStore->VNForIntCon(lclNum));
}
break;
@@ -4816,12 +4823,12 @@ void Compiler::fgValueNumber()
}
else
{
- initVal = vnStore->VNForFunc(typ, VNF_InitVal, vnStore->VNForIntCon(i));
+ initVal = vnStore->VNForFunc(typ, VNF_InitVal, vnStore->VNForIntCon(lclNum));
}
break;
}
#ifdef _TARGET_X86_
- bool isVarargParam = (i == lvaVarargsBaseOfStkArgs || i == lvaVarargsHandleArg);
+ bool isVarargParam = (lclNum == lvaVarargsBaseOfStkArgs || lclNum == lvaVarargsHandleArg);
if (isVarargParam)
initVal = vnStore->VNForExpr(fgFirstBB); // a new, unique VN.
#endif
@@ -5530,7 +5537,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree, bool evalAsgLhsInd)
// Ignore vars that we excluded from SSA (for example, because they're address-exposed). They don't have
// SSA names in which to store VN's on defs. We'll yield unique VN's when we read from them.
- if (!fgExcludeFromSsa(lclNum))
+ if (lvaInSsa(lclNum))
{
// Should not have been recorded as updating ByrefExposed.
assert(!GetMemorySsaMap(ByrefExposed)->Lookup(tree, &memorySsaNum));
@@ -5598,7 +5605,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree, bool evalAsgLhsInd)
unsigned lhsLclNum = lclVarTree->GetLclNum();
FieldSeqNode* lhsFldSeq = nullptr;
// If it's excluded from SSA, don't need to do anything.
- if (!fgExcludeFromSsa(lhsLclNum))
+ if (lvaInSsa(lhsLclNum))
{
// Should not have been recorded as updating ByrefExposed.
assert(!GetMemorySsaMap(ByrefExposed)->Lookup(tree, &memorySsaNum));
@@ -5652,7 +5659,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree, bool evalAsgLhsInd)
{
unsigned rhsLclNum = rhsLclVarTree->GetLclNum();
rhsVarDsc = &lvaTable[rhsLclNum];
- if (fgExcludeFromSsa(rhsLclNum) || rhsFldSeq == FieldSeqStore::NotAField())
+ if (!lvaInSsa(rhsLclNum) || rhsFldSeq == FieldSeqStore::NotAField())
{
rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, rhsLclVarTree->TypeGet()));
isNewUniq = true;
@@ -5681,7 +5688,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree, bool evalAsgLhsInd)
{
unsigned rhsLclNum = rhsLclVarTree->GetLclNum();
rhsVarDsc = &lvaTable[rhsLclNum];
- if (fgExcludeFromSsa(rhsLclNum) || rhsFldSeq == FieldSeqStore::NotAField())
+ if (!lvaInSsa(rhsLclNum) || rhsFldSeq == FieldSeqStore::NotAField())
{
isNewUniq = true;
}
@@ -5983,7 +5990,7 @@ void Compiler::fgValueNumberTree(GenTree* tree, bool evalAsgLhsInd)
case GT_LCL_FLD:
{
GenTreeLclFld* lclFld = tree->AsLclFld();
- assert(fgExcludeFromSsa(lclFld->GetLclNum()) || lclFld->gtFieldSeq != nullptr);
+ assert(!lvaInSsa(lclFld->GetLclNum()) || lclFld->gtFieldSeq != nullptr);
// If this is a (full) def, then the variable will be labeled with the new SSA number,
// which will not have a value. We skip; it will be handled by one of the assignment-like
// forms (assignment, or initBlk or copyBlk).
@@ -5994,7 +6001,7 @@ void Compiler::fgValueNumberTree(GenTree* tree, bool evalAsgLhsInd)
LclVarDsc* varDsc = &lvaTable[lclNum];
var_types indType = tree->TypeGet();
- if (lclFld->gtFieldSeq == FieldSeqStore::NotAField() || fgExcludeFromSsa(lclFld->GetLclNum()))
+ if (lclFld->gtFieldSeq == FieldSeqStore::NotAField() || !lvaInSsa(lclFld->GetLclNum()))
{
// This doesn't represent a proper field access or it's a struct
// with overlapping fields that is hard to reason about; return a new unique VN.
@@ -6363,7 +6370,7 @@ void Compiler::fgValueNumberTree(GenTree* tree, bool evalAsgLhsInd)
wasLocal = true;
- if (!fgExcludeFromSsa(lclNum))
+ if (lvaInSsa(lclNum))
{
FieldSeqNode* fieldSeq = vnStore->FieldSeqVNToFieldSeq(funcApp.m_args[1]);
@@ -6716,7 +6723,7 @@ void Compiler::fgValueNumberTree(GenTree* tree, bool evalAsgLhsInd)
{
FieldSeqNode* fieldSeq = nullptr;
ValueNum newVN = ValueNumStore::NoVN;
- if (fgExcludeFromSsa(arg->gtLclVarCommon.GetLclNum()))
+ if (!lvaInSsa(arg->gtLclVarCommon.GetLclNum()))
{
newVN = vnStore->VNForExpr(compCurBB, TYP_BYREF);
}
@@ -6928,8 +6935,7 @@ void Compiler::fgValueNumberTree(GenTree* tree, bool evalAsgLhsInd)
VNFuncApp funcApp;
// Is it a local or a heap address?
- if (addr->IsLocalAddrExpr(this, &lclVarTree, &localFldSeq) &&
- !fgExcludeFromSsa(lclVarTree->GetLclNum()))
+ if (addr->IsLocalAddrExpr(this, &lclVarTree, &localFldSeq) && lvaInSsa(lclVarTree->GetLclNum()))
{
unsigned lclNum = lclVarTree->GetLclNum();
unsigned ssaNum = lclVarTree->GetSsaNum();