From f7a90a380f06287c17a57f391b68df7152de8b0e Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Mon, 22 Jun 2020 03:20:59 -0700 Subject: [PATCH] Add SSA support. --- src/coreclr/src/jit/morph.cpp | 3 --- src/coreclr/src/jit/rangecheck.cpp | 22 +++++++++++++++++++--- src/coreclr/src/jit/ssabuilder.cpp | 14 +++++++++++--- src/coreclr/src/jit/valuenum.cpp | 6 ++++++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/coreclr/src/jit/morph.cpp b/src/coreclr/src/jit/morph.cpp index 00c548c288423..b67531a101fa5 100644 --- a/src/coreclr/src/jit/morph.cpp +++ b/src/coreclr/src/jit/morph.cpp @@ -10342,9 +10342,6 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree) if (varTypeIsStruct(varDsc) && varDsc->CanBeReplacedWithItsField(this)) { JITDUMP(" not morphing a single reg call return\n"); - // Set `lvIsMultiRegRet` to exclude it from SSA, it is a temporary solution, - // inspired by multi-reg call work. We should support SSA for such structs in the future. - varDsc->lvIsMultiRegRet = true; return tree; } } diff --git a/src/coreclr/src/jit/rangecheck.cpp b/src/coreclr/src/jit/rangecheck.cpp index 9fb0eaf0357d2..663c3a1537d34 100644 --- a/src/coreclr/src/jit/rangecheck.cpp +++ b/src/coreclr/src/jit/rangecheck.cpp @@ -444,7 +444,12 @@ LclSsaVarDsc* RangeCheck::GetSsaDefAsg(GenTreeLclVarCommon* lclUse) return nullptr; } - LclSsaVarDsc* ssaDef = m_pCompiler->lvaGetDesc(lclUse)->GetPerSsaData(ssaNum); + LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lclUse); + if (varDsc->CanBeReplacedWithItsField(m_pCompiler)) + { + varDsc = m_pCompiler->lvaGetDesc(varDsc->lvFieldLclStart); + } + LclSsaVarDsc* ssaDef = varDsc->GetPerSsaData(ssaNum); // RangeCheck does not care about uninitialized variables. if (ssaDef->GetAssignment() == nullptr) @@ -472,6 +477,11 @@ LclSsaVarDsc* RangeCheck::GetSsaDefAsg(GenTreeLclVarCommon* lclUse) #ifdef DEBUG UINT64 RangeCheck::HashCode(unsigned lclNum, unsigned ssaNum) { + LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lclNum); + if (varDsc->CanBeReplacedWithItsField(m_pCompiler)) + { + lclNum = varDsc->lvFieldLclStart; + } assert(ssaNum != SsaConfig::RESERVED_SSA_NUM); return UINT64(lclNum) << 32 | ssaNum; } @@ -499,7 +509,8 @@ RangeCheck::Location* RangeCheck::GetDef(unsigned lclNum, unsigned ssaNum) RangeCheck::Location* RangeCheck::GetDef(GenTreeLclVarCommon* lcl) { - return GetDef(lcl->GetLclNum(), lcl->GetSsaNum()); + unsigned lclNum = lcl->GetLclNum(); + return GetDef(lclNum, lcl->GetSsaNum()); } // Add the def location to the hash table. @@ -546,7 +557,12 @@ void RangeCheck::MergeEdgeAssertions(GenTreeLclVarCommon* lcl, ASSERT_VALARG_TP Limit limit(Limit::keUndef); genTreeOps cmpOper = GT_NONE; - LclSsaVarDsc* ssaData = m_pCompiler->lvaTable[lcl->GetLclNum()].GetPerSsaData(lcl->GetSsaNum()); + LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lcl); + if (varDsc->CanBeReplacedWithItsField(m_pCompiler)) + { + varDsc = m_pCompiler->lvaGetDesc(varDsc->lvFieldLclStart); + } + LclSsaVarDsc* ssaData = varDsc->GetPerSsaData(lcl->GetSsaNum()); ValueNum normalLclVN = m_pCompiler->vnStore->VNConservativeNormalValue(ssaData->m_vnPair); // Current assertion is of the form (i < len - cns) != 0 diff --git a/src/coreclr/src/jit/ssabuilder.cpp b/src/coreclr/src/jit/ssabuilder.cpp index 3bd0b44c4f2b4..5a1df78f21e59 100644 --- a/src/coreclr/src/jit/ssabuilder.cpp +++ b/src/coreclr/src/jit/ssabuilder.cpp @@ -749,7 +749,15 @@ void SsaBuilder::RenameDef(GenTreeOp* asgNode, BasicBlock* block) if (isLocal) { - unsigned lclNum = lclNode->GetLclNum(); + unsigned lclNum = lclNode->GetLclNum(); + LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lclNum); + + if (!m_pCompiler->lvaInSsa(lclNum) && varDsc->CanBeReplacedWithItsField(m_pCompiler)) + { + lclNum = varDsc->lvFieldLclStart; + varDsc = m_pCompiler->lvaGetDesc(lclNum); + assert(isFullDef); + } if (m_pCompiler->lvaInSsa(lclNum)) { @@ -758,7 +766,7 @@ void SsaBuilder::RenameDef(GenTreeOp* asgNode, BasicBlock* block) // This should have been marked as defintion. assert((lclNode->gtFlags & GTF_VAR_DEF) != 0); - unsigned ssaNum = m_pCompiler->lvaGetDesc(lclNum)->lvPerSsaData.AllocSsaNum(m_allocator, block, asgNode); + unsigned ssaNum = varDsc->lvPerSsaData.AllocSsaNum(m_allocator, block, asgNode); if (!isFullDef) { @@ -787,7 +795,7 @@ void SsaBuilder::RenameDef(GenTreeOp* asgNode, BasicBlock* block) } // If it's a SSA local then it cannot be address exposed and thus does not define SSA memory. - assert(!m_pCompiler->lvaVarAddrExposed(lclNode->GetLclNum())); + assert(!m_pCompiler->lvaVarAddrExposed(lclNum)); return; } diff --git a/src/coreclr/src/jit/valuenum.cpp b/src/coreclr/src/jit/valuenum.cpp index 2fb9c3ce14e46..2e65f36aa163b 100644 --- a/src/coreclr/src/jit/valuenum.cpp +++ b/src/coreclr/src/jit/valuenum.cpp @@ -6859,6 +6859,12 @@ void Compiler::fgValueNumberTree(GenTree* tree) unsigned lclNum = lcl->GetLclNum(); LclVarDsc* varDsc = &lvaTable[lclNum]; + if (varDsc->CanBeReplacedWithItsField(this)) + { + lclNum = varDsc->lvFieldLclStart; + varDsc = &lvaTable[lclNum]; + } + // Do we have a Use (read) of the LclVar? // if ((lcl->gtFlags & GTF_VAR_DEF) == 0 ||