From 49fb5ac674c74de709db144d41b9c5e5d02e4173 Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Sat, 5 Oct 2019 07:22:09 -0700 Subject: [PATCH] Put single-def CSEs into SSA (dotnet/coreclr#26986) If we create a single-def temp during SSE, add it into SSA so uses of the temp can benefit from assertion prop and similar. Follow-up from some work proposed for dotnet/coreclr#21973. Commit migrated from https://github.com/dotnet/coreclr/commit/863b40ec595bc1db58d7000255d72180a43deacb --- src/coreclr/src/jit/optcse.cpp | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/coreclr/src/jit/optcse.cpp b/src/coreclr/src/jit/optcse.cpp index 2bceb57cc59..dffd1f7713f 100644 --- a/src/coreclr/src/jit/optcse.cpp +++ b/src/coreclr/src/jit/optcse.cpp @@ -2012,6 +2012,7 @@ public: // It will replace all of the CSE defs with assignments to a new "cse0" LclVar // and will replace all of the CSE uses with reads of the "cse0" LclVar // + // It will also put cse0 into SSA if there is just one def. void PerformCSE(CSE_Candidate* successfulCandidate) { unsigned cseRefCnt = (successfulCandidate->DefCount() * 2) + successfulCandidate->UseCount(); @@ -2072,6 +2073,21 @@ public: Compiler::CSEdsc* dsc = successfulCandidate->CseDsc(); Compiler::treeStmtLst* lst; + // If there's just a single def for the CSE, we'll put this + // CSE into SSA form on the fly. We won't need any PHIs. + unsigned cseSsaNum = SsaConfig::RESERVED_SSA_NUM; + + if (dsc->csdDefCount == 1) + { + JITDUMP("CSE #%02u is single-def, so associated cse temp V%02u will be in SSA\n", dsc->csdIndex, + cseLclVarNum); + m_pCompiler->lvaTable[cseLclVarNum].lvInSsa = true; + + // Allocate the ssa num + CompAllocator allocator = m_pCompiler->getAllocator(CMK_SSA); + cseSsaNum = m_pCompiler->lvaTable[cseLclVarNum].lvPerSsaData.AllocSsaNum(allocator); + } + #ifdef DEBUG // Verify that all of the ValueNumbers in this list are correct as // Morph will change them when it performs a mutating operation. @@ -2185,6 +2201,9 @@ public: ValueNumStore* vnStore = m_pCompiler->vnStore; cse = m_pCompiler->gtNewLclvNode(cseLclVarNum, cseLclVarTyp); + // Assign the ssa num for the use. Note it may be the reserved num. + cse->gtLclVarCommon.SetSsaNum(cseSsaNum); + // assign the proper ValueNumber, A CSE use discards any exceptions cse->gtVNPair = vnStore->VNPNormalPair(exp->gtVNPair); @@ -2348,10 +2367,30 @@ public: noway_assert(asg->gtOp.gtOp1->gtOper == GT_LCL_VAR); + // Backpatch the SSA def, if we're putting this cse temp into ssa. + asg->gtOp.gtOp1->AsLclVar()->SetSsaNum(cseSsaNum); + + if (cseSsaNum != SsaConfig::RESERVED_SSA_NUM) + { + LclSsaVarDsc* ssaVarDsc = m_pCompiler->lvaTable[cseLclVarNum].GetPerSsaData(cseSsaNum); + + // These should not have been set yet, since this is the first and + // only def for this CSE. + assert(ssaVarDsc->m_defLoc.m_blk == nullptr); + assert(ssaVarDsc->m_defLoc.m_tree == nullptr); + + ssaVarDsc->m_vnPair = val->gtVNPair; + ssaVarDsc->m_defLoc.m_blk = blk; + ssaVarDsc->m_defLoc.m_tree = asg; + } + /* Create a reference to the CSE temp */ GenTree* ref = m_pCompiler->gtNewLclvNode(cseLclVarNum, cseLclVarTyp); ref->gtVNPair = val->gtVNPair; // The new 'ref' is the same as 'val' + // Assign the ssa num for the ref use. Note it may be the reserved num. + ref->gtLclVarCommon.SetSsaNum(cseSsaNum); + // If it has a zero-offset field seq, copy annotation to the ref if (hasZeroMapAnnotation) { -- 2.34.1