diff --git a/src/coreclr/jit/lowerwasm.cpp b/src/coreclr/jit/lowerwasm.cpp index ab9c56164fa1a8..904736bb2d87cf 100644 --- a/src/coreclr/jit/lowerwasm.cpp +++ b/src/coreclr/jit/lowerwasm.cpp @@ -552,6 +552,9 @@ void Lowering::AfterLowerBlocks() { assert(IsDataFlowRoot(node)); node = StackifyTree(node); + // We don't track liveness of temporaries more precisely since introducing eairler uses + // may interfere with later (by that point already inserted and stackified) stores. + ReleaseTemporaries(); } m_lower->m_block = nullptr; @@ -567,7 +570,6 @@ void Lowering::AfterLowerBlocks() // Simple greedy algorithm working backwards. The invariant is that the stack top must be placed right next // to (in normal linear order - before) the node we last stackified. m_stack.Push(&root); - ReleaseTemporariesDefinedBy(root); GenTree* lastStackified = root->gtNext; while (m_stack.Height() != initialDepth) @@ -668,8 +670,6 @@ void Lowering::AfterLowerBlocks() *use = lclNode; JITDUMP("Replaced [%06u] with a temporary:\n", Compiler::dspTreeID(node)); - DISPNODE(node); - DISPNODE(lclNode); if ((node->gtLIRFlags & LIR::Flags::MultiplyUsed) == LIR::Flags::MultiplyUsed) { @@ -704,33 +704,37 @@ void Lowering::AfterLowerBlocks() return lclNum; } - void ReleaseTemporariesDefinedBy(GenTree* node) + void ReleaseTemporaries() { - // We rely in this function on the lifetime of temporaries beginning (recall this is backwards traversal) - // at exactly "node"'s position, and not shrinking or extending after this call. This is currently true - // because we never move dataflow roots, and we only begin processing them after all subsequent nodes - // have already been stackified and thus won't move either. - assert(IsDataFlowRoot(node)); - if (!node->OperIs(GT_STORE_LCL_VAR)) + if (m_minimumTempLclNum == m_compiler->lvaCount) { + // No temporaries were created return; } + assert(m_minimumTempLclNum < m_compiler->lvaCount); - unsigned lclNum = node->AsLclVar()->GetLclNum(); - if (lclNum < m_minimumTempLclNum) + // Recycle all available temporaries as unused nodes + for (int i = 0; i < TYP_COUNT; i++) { - return; + while (m_availableTemps[i] != nullptr) + { + Temporary* temp = Remove(&m_availableTemps[i]); + Append(&m_unusedTempNodes, temp); + } } - Temporary* local = Remove(&m_unusedTempNodes); // See if we have any free nodes in the pool. - if (local == nullptr) + for (unsigned lclNum = m_minimumTempLclNum; lclNum < m_compiler->lvaCount; lclNum++) { - local = new (m_compiler, CMK_Lower) Temporary(); - } - local->LclNum = lclNum; + Temporary* local = Remove(&m_unusedTempNodes); // See if we have any free nodes in the pool. + if (local == nullptr) + { + local = new (m_compiler, CMK_Lower) Temporary(); + } + local->LclNum = lclNum; - JITDUMP("Temporary V%02u is now free and can be re-used\n", lclNum); - Append(&m_availableTemps[genActualType(node->TypeGet())], local); + JITDUMP("Temporary V%02u is now free and can be re-used\n", lclNum); + Append(&m_availableTemps[genActualType(m_compiler->lvaGetDesc(lclNum)->TypeGet())], local); + } } Temporary* Remove(Temporary** pTemps)