diff --git a/src/coreclr/jit/jitstd/vector.h b/src/coreclr/jit/jitstd/vector.h index cc0afdc20d27ff..69f67817ecb6e9 100644 --- a/src/coreclr/jit/jitstd/vector.h +++ b/src/coreclr/jit/jitstd/vector.h @@ -305,36 +305,29 @@ template template vector::vector(const vector& vec) : m_allocator(vec.m_allocator) - , m_pArray(NULL) - , m_nSize(0) - , m_nCapacity(0) + , m_pArray(m_allocator.allocate(vec.m_nSize)) + , m_nSize(vec.m_nSize) + , m_nCapacity(vec.m_nSize) { - ensure_capacity(vec.m_nSize); - for (size_type i = 0, j = 0; i < vec.m_nSize; ++i, ++j) + for (size_type i = 0; i < vec.m_nSize; ++i) { - new (m_pArray + i, placement_t()) T((T) vec.m_pArray[j]); + new (m_pArray + i, placement_t()) T((T) vec.m_pArray[i]); } - - m_nSize = vec.m_nSize; } template vector::vector(const vector& vec) : m_allocator(vec.m_allocator) - , m_pArray(NULL) - , m_nSize(0) - , m_nCapacity(0) + , m_pArray(m_allocator.allocate(vec.m_nSize)) + , m_nSize(vec.m_nSize) + , m_nCapacity(vec.m_nSize) { - ensure_capacity(vec.m_nSize); - for (size_type i = 0, j = 0; i < vec.m_nSize; ++i, ++j) + for (size_type i = 0; i < vec.m_nSize; ++i) { - new (m_pArray + i, placement_t()) T(vec.m_pArray[j]); + new (m_pArray + i, placement_t()) T(vec.m_pArray[i]); } - - m_nSize = vec.m_nSize; } - template vector::~vector() { diff --git a/src/coreclr/jit/promotion.cpp b/src/coreclr/jit/promotion.cpp index b94feb571ce16a..f630a47a7a90f0 100644 --- a/src/coreclr/jit/promotion.cpp +++ b/src/coreclr/jit/promotion.cpp @@ -1056,7 +1056,7 @@ class LocalsUseVisitor : public GenTreeVisitor JITDUMP("Computing unpromoted remainder for V%02u\n", agg->LclNum); StructSegments unpromotedParts = - Promotion::SignificantSegments(m_compiler, m_compiler->lvaGetDesc(agg->LclNum)->GetLayout()); + m_prom->SignificantSegments(m_compiler->lvaGetDesc(agg->LclNum)->GetLayout()); for (Replacement& rep : reps) { unpromotedParts.Subtract(StructSegments::Segment(rep.Offset, rep.Offset + genTypeSize(rep.AccessType))); @@ -1531,42 +1531,6 @@ bool StructSegments::CoveringSegment(Segment* result) } #ifdef DEBUG -//------------------------------------------------------------------------ -// Check: -// Validate that the data structure is normalized and that it equals a -// specific fixed bit vector. -// -// Parameters: -// vect - The bit vector -// -// Remarks: -// This validates that the internal representation is normalized (i.e. -// all adjacent intervals are merged) and that it contains an index iff -// the specified vector contains that index. -// -void StructSegments::Check(FixedBitVect* vect) -{ - bool first = true; - unsigned last = 0; - for (const Segment& segment : m_segments) - { - assert(first || (last < segment.Start)); - assert(segment.End <= vect->bitVectGetSize()); - - for (unsigned i = last; i < segment.Start; i++) - assert(!vect->bitVectTest(i)); - - for (unsigned i = segment.Start; i < segment.End; i++) - assert(vect->bitVectTest(i)); - - first = false; - last = segment.End; - } - - for (unsigned i = last, size = vect->bitVectGetSize(); i < size; i++) - assert(!vect->bitVectTest(i)); -} - //------------------------------------------------------------------------ // Dump: // Dump a string representation of the segment tree to stdout. @@ -1595,18 +1559,20 @@ void StructSegments::Dump() // for the specified class layout. // // Parameters: -// compiler - Compiler instance // layout - The layout -// bitVectRept - In debug, a bit vector that represents the same segments as the returned segment tree. -// Used for verification purposes. // // Returns: // Segment tree containing all significant parts of the layout. // -StructSegments Promotion::SignificantSegments(Compiler* compiler, - ClassLayout* layout DEBUGARG(FixedBitVect** bitVectRepr)) +StructSegments Promotion::SignificantSegments(ClassLayout* layout) { - COMP_HANDLE compHnd = compiler->info.compCompHnd; + StructSegments* cached; + if ((m_significantSegmentsCache != nullptr) && m_significantSegmentsCache->Lookup(layout, &cached)) + { + return StructSegments(*cached); + } + + COMP_HANDLE compHnd = m_compiler->info.compCompHnd; bool significantPadding; if (layout->IsBlockLayout()) @@ -1638,19 +1604,11 @@ StructSegments Promotion::SignificantSegments(Compiler* compiler, } } - StructSegments segments(compiler->getAllocator(CMK_Promotion)); - - // Validate with "obviously correct" but less scalable fixed bit vector implementation. - INDEBUG(FixedBitVect* segmentBitVect = FixedBitVect::bitVectInit(layout->GetSize(), compiler)); + StructSegments segments(m_compiler->getAllocator(CMK_Promotion)); if (significantPadding) { segments.Add(StructSegments::Segment(0, layout->GetSize())); - -#ifdef DEBUG - for (unsigned i = 0; i < layout->GetSize(); i++) - segmentBitVect->bitVectSet(i); -#endif } else { @@ -1675,19 +1633,16 @@ StructSegments Promotion::SignificantSegments(Compiler* compiler, } segments.Add(StructSegments::Segment(fldOffset, fldOffset + size)); -#ifdef DEBUG - for (unsigned i = 0; i < size; i++) - segmentBitVect->bitVectSet(fldOffset + i); -#endif } } -#ifdef DEBUG - if (bitVectRepr != nullptr) + if (m_significantSegmentsCache == nullptr) { - *bitVectRepr = segmentBitVect; + m_significantSegmentsCache = + new (m_compiler, CMK_Promotion) ClassLayoutStructSegmentsMap(m_compiler->getAllocator(CMK_Promotion)); } -#endif + + m_significantSegmentsCache->Set(layout, new (m_compiler, CMK_Promotion) StructSegments(segments)); return segments; } diff --git a/src/coreclr/jit/promotion.h b/src/coreclr/jit/promotion.h index 98c7f7a6b500f4..4cc5daa9525377 100644 --- a/src/coreclr/jit/promotion.h +++ b/src/coreclr/jit/promotion.h @@ -72,7 +72,6 @@ class StructSegments bool CoveringSegment(Segment* result); #ifdef DEBUG - void Check(FixedBitVect* vect); void Dump(); #endif }; @@ -97,9 +96,12 @@ struct AggregateInfo Replacement** endReplacement); }; +typedef JitHashTable, class StructSegments*> ClassLayoutStructSegmentsMap; + class Promotion { - Compiler* m_compiler; + Compiler* m_compiler; + ClassLayoutStructSegmentsMap* m_significantSegmentsCache = nullptr; friend class LocalUses; friend class LocalsUseVisitor; @@ -109,8 +111,7 @@ class Promotion friend class DecompositionPlan; friend class StructSegments; - static StructSegments SignificantSegments(Compiler* compiler, - ClassLayout* layout DEBUGARG(FixedBitVect** bitVectRepr = nullptr)); + StructSegments SignificantSegments(ClassLayout* layout); void InsertInitialReadBack(unsigned lclNum, const jitstd::vector& replacements, Statement** prevStmt); void ExplicitlyZeroInitReplacementLocals(unsigned lclNum, @@ -244,6 +245,7 @@ class ReplaceVisitor : public GenTreeVisitor { friend class DecompositionPlan; + Promotion* m_promotion; jitstd::vector& m_aggregates; PromotionLiveness* m_liveness; bool m_madeChanges = false; @@ -260,7 +262,7 @@ class ReplaceVisitor : public GenTreeVisitor }; ReplaceVisitor(Promotion* prom, jitstd::vector& aggregates, PromotionLiveness* liveness) - : GenTreeVisitor(prom->m_compiler), m_aggregates(aggregates), m_liveness(liveness) + : GenTreeVisitor(prom->m_compiler), m_promotion(prom), m_aggregates(aggregates), m_liveness(liveness) { } diff --git a/src/coreclr/jit/promotiondecomposition.cpp b/src/coreclr/jit/promotiondecomposition.cpp index 9be8ed9c8b0955..b545b51afce45f 100644 --- a/src/coreclr/jit/promotiondecomposition.cpp +++ b/src/coreclr/jit/promotiondecomposition.cpp @@ -49,6 +49,7 @@ class DecompositionPlan var_types Type; }; + Promotion* m_promotion; Compiler* m_compiler; ReplaceVisitor* m_replacer; jitstd::vector& m_aggregates; @@ -61,7 +62,7 @@ class DecompositionPlan bool m_hasNonRemainderUseOfStructLocal = false; public: - DecompositionPlan(Compiler* comp, + DecompositionPlan(Promotion* prom, ReplaceVisitor* replacer, jitstd::vector& aggregates, PromotionLiveness* liveness, @@ -69,7 +70,8 @@ class DecompositionPlan GenTree* src, bool dstInvolvesReplacements, bool srcInvolvesReplacements) - : m_compiler(comp) + : m_promotion(prom) + , m_compiler(prom->m_compiler) , m_replacer(replacer) , m_aggregates(aggregates) , m_liveness(liveness) @@ -77,7 +79,7 @@ class DecompositionPlan , m_src(src) , m_dstInvolvesReplacements(dstInvolvesReplacements) , m_srcInvolvesReplacements(srcInvolvesReplacements) - , m_entries(comp->getAllocator(CMK_Promotion)) + , m_entries(prom->m_compiler->getAllocator(CMK_Promotion)) { } @@ -274,25 +276,16 @@ class DecompositionPlan { ClassLayout* dstLayout = m_store->GetLayout(m_compiler); - // Validate with "obviously correct" but less scalable fixed bit vector implementation. - INDEBUG(FixedBitVect * segmentBitVect); - StructSegments segments = Promotion::SignificantSegments(m_compiler, dstLayout DEBUGARG(&segmentBitVect)); + StructSegments segments = m_promotion->SignificantSegments(dstLayout); for (int i = 0; i < m_entries.Height(); i++) { const Entry& entry = m_entries.BottomRef(i); segments.Subtract(StructSegments::Segment(entry.Offset, entry.Offset + genTypeSize(entry.Type))); - -#ifdef DEBUG - for (unsigned i = 0; i < genTypeSize(entry.Type); i++) - segmentBitVect->bitVectClear(entry.Offset + i); -#endif } #ifdef DEBUG - segments.Check(segmentBitVect); - if (m_compiler->verbose) { printf(" Remainder: "); @@ -1087,7 +1080,7 @@ void ReplaceVisitor::HandleStore(GenTree** use, GenTree* user) DecompositionStatementList result; EliminateCommasInBlockOp(store, &result); - DecompositionPlan plan(m_compiler, this, m_aggregates, m_liveness, store, src, dstInvolvesReplacements, + DecompositionPlan plan(m_promotion, this, m_aggregates, m_liveness, store, src, dstInvolvesReplacements, srcInvolvesReplacements); if (dstInvolvesReplacements)