diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 9018933d5e5bc3..a62d9216395043 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -799,9 +799,7 @@ LinearScanInterface* getLinearScanAllocator(Compiler* comp) // LinearScan::LinearScan(Compiler* theCompiler) : compiler(theCompiler) - , intervals(theCompiler->getAllocator(CMK_LSRA_Interval)) , allocationPassComplete(false) - , refPositions(theCompiler->getAllocator(CMK_LSRA_RefPosition)) , killHead(nullptr) , killTail(&killHead) , listNodePool(theCompiler) diff --git a/src/coreclr/jit/lsra.h b/src/coreclr/jit/lsra.h index 5d49673ffc4bee..a7f9cb93160b12 100644 --- a/src/coreclr/jit/lsra.h +++ b/src/coreclr/jit/lsra.h @@ -443,10 +443,227 @@ inline bool RefTypeIsDef(RefType refType) typedef regNumberSmall* VarToRegMap; -typedef jitstd::list IntervalList; -typedef jitstd::list RefPositionList; -typedef jitstd::list::iterator RefPositionIterator; -typedef jitstd::list::reverse_iterator RefPositionReverseIterator; +// Like normal jitstd::list, but guarantees that the memory is zeroed. +template +class PreZeroedList +{ + struct Node + { + T Value; + Node* Prev; + Node* Next; + + template + Node(Args... args) + : Value(args...) + { + } + }; + +#ifdef DEBUG + size_t m_count = 0; +#endif + + Node* m_head = nullptr; + Node* m_tail = nullptr; + Node** m_tailSlot = &m_head; + + char* m_buffer = nullptr; + char* m_bufferEnd = nullptr; + +public: +#ifdef DEBUG + size_t size() + { + return m_count; + } +#endif + + template + T* Allocate(Compiler* comp, Args... args) + { + if (m_buffer == m_bufferEnd) + { + m_buffer = new (comp, MemKind) char[ChunkSize * sizeof(Node)]; + m_bufferEnd = m_buffer + ChunkSize * sizeof(Node); + memset(m_buffer, 0, ChunkSize * sizeof(Node)); + } + + Node* newNode = new (m_buffer, jitstd::placement_t()) Node(args...); + m_buffer += sizeof(Node); + + INDEBUG(m_count++); + + newNode->Prev = m_tail; + *m_tailSlot = m_tail = newNode; + m_tailSlot = &newNode->Next; + + return &newNode->Value; + } + + class iterator + { + friend class PreZeroedList; + Node* m_node; + + explicit iterator(Node* node) + : m_node(node) + { + } + + public: + iterator() + : m_node(nullptr) + { + } + + iterator& operator++() + { + m_node = m_node->Next; + return *this; + } + + iterator& operator++(int) + { + m_node = m_node->Next; + return *this; + } + + iterator& operator--() + { + m_node = m_node->Prev; + return *this; + } + + iterator& operator--(int) + { + m_node = m_node->Prev; + return *this; + } + + bool operator==(const iterator& it) + { + return m_node == it.m_node; + } + + bool operator!=(const iterator& it) + { + return m_node != it.m_node; + } + + T& operator*() + { + return m_node->Value; + } + + T* operator->() + { + return &m_node->Value; + } + + operator T*() + { + return &m_node->Value; + } + }; + + class reverse_iterator + { + friend class PreZeroedList; + Node* m_node; + + explicit reverse_iterator(Node* node) + : m_node(node) + { + } + + public: + reverse_iterator() + : m_node(nullptr) + { + } + + reverse_iterator& operator++() + { + m_node = m_node->Prev; + return *this; + } + + reverse_iterator& operator++(int) + { + m_node = m_node->Prev; + return *this; + } + + reverse_iterator& operator--() + { + m_node = m_node->Next; + return *this; + } + + reverse_iterator& operator--(int) + { + m_node = m_node->Next; + return *this; + } + + bool operator==(const reverse_iterator& it) + { + return m_node == it.m_node; + } + + bool operator!=(const reverse_iterator& it) + { + return m_node != it.m_node; + } + + T& operator*() + { + return m_node->Value; + } + + T* operator->() + { + return &m_node->Value; + } + + operator T*() + { + return &m_node->Value; + } + }; + + iterator begin() + { + return iterator(m_head); + } + + iterator end() + { + return iterator(nullptr); + } + + iterator backPosition() + { + return iterator(m_tail); + } + + reverse_iterator rbegin() + { + return reverse_iterator(m_tail); + } + + reverse_iterator rend() + { + return reverse_iterator(nullptr); + } +}; + +typedef PreZeroedList IntervalList; + +typedef PreZeroedList RefPositionList; +typedef PreZeroedList::iterator RefPositionIterator; +typedef PreZeroedList::reverse_iterator RefPositionReverseIterator; class Referenceable { @@ -2172,33 +2389,9 @@ class Interval : public Referenceable Interval(RegisterType registerType, SingleTypeRegSet registerPreferences) : Referenceable(registerType) , registerPreferences(registerPreferences) - , registerAversion(RBM_NONE) - , relatedInterval(nullptr) - , assignedReg(nullptr) - , varNum(0) , physReg(REG_COUNT) - , isActive(false) - , isLocalVar(false) - , isSplit(false) - , isSpilled(false) - , isInternal(false) - , isStructField(false) - , isPromotedStruct(false) - , hasConflictingDefUse(false) - , hasInterferingUses(false) - , isSpecialPutArg(false) - , preferCalleeSave(false) - , isConstant(false) -#if FEATURE_PARTIAL_SIMD_CALLEE_SAVE - , isUpperVector(false) - , isPartiallySpilled(false) -#endif - , isWriteThru(false) - , isSingleDef(false) -#ifdef DEBUG - , intervalIndex(0) -#endif { + // Intervals are allocated on top of zeroed memory, so all fields are already zero } #ifdef DEBUG @@ -2595,36 +2788,16 @@ class RefPosition LsraLocation nodeLocation, GenTree* treeNode, RefType refType DEBUG_ARG(GenTree* buildNode)) - : referent(nullptr) - , nextRefPosition(nullptr) - , treeNode(treeNode) - , registerAssignment(RBM_NONE) + : treeNode(treeNode) , bbNum(bbNum) , nodeLocation(nodeLocation) , refType(refType) - , multiRegIdx(0) -#ifdef TARGET_ARM64 - , needsConsecutive(false) - , regCount(0) -#endif - , lastUse(false) - , reload(false) - , spillAfter(false) - , singleDefSpill(false) - , writeThru(false) - , copyReg(false) - , moveReg(false) - , isPhysRegRef(false) - , isFixedRegRef(false) - , isLocalDefUse(false) - , delayRegFree(false) - , outOfOrder(false) #ifdef DEBUG , minRegCandidateCount(1) - , rpNum(0) , buildNode(buildNode) #endif { + // RefPositions are allocated on top of zeroed memory, so all fields are already zero } Interval* getInterval() diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 5e0473ca906a4c..72bab51e6fb69b 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -153,8 +153,7 @@ void RefInfoListNodePool::ReturnNode(RefInfoListNode* listNode) // Interval* LinearScan::newInterval(RegisterType theRegisterType) { - intervals.emplace_back(theRegisterType, allRegs(theRegisterType)); - Interval* newInt = &intervals.back(); + Interval* newInt = intervals.Allocate(compiler, theRegisterType, allRegs(theRegisterType)); #ifdef DEBUG newInt->intervalIndex = static_cast(intervals.size() - 1); @@ -178,8 +177,8 @@ Interval* LinearScan::newInterval(RegisterType theRegisterType) // RefPosition* LinearScan::newRefPositionRaw(LsraLocation nodeLocation, GenTree* treeNode, RefType refType) { - refPositions.emplace_back(curBBNum, nodeLocation, treeNode, refType DEBUG_ARG(currBuildNode)); - RefPosition* newRP = &refPositions.back(); + RefPosition* newRP = + refPositions.Allocate(compiler, curBBNum, nodeLocation, treeNode, refType DEBUG_ARG(currBuildNode)); #ifdef DEBUG // Reset currBuildNode so we do not set it for subsequent refpositions belonging // to the same treeNode and hence, avoid printing it for every refposition inside