llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> If the array is small enough, use the initmap pointer directly for storage instead of heap-allocating it. --- Full diff: https://github.com/llvm/llvm-project/pull/171093.diff 2 Files Affected: - (modified) clang/lib/AST/ByteCode/Descriptor.h (+27) - (modified) clang/lib/AST/ByteCode/Pointer.cpp (+16-10) ``````````diff diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h index 2807f92335dc2..05be3d403cbae 100644 --- a/clang/lib/AST/ByteCode/Descriptor.h +++ b/clang/lib/AST/ByteCode/Descriptor.h @@ -278,6 +278,11 @@ struct Descriptor final { }; /// Bitfield tracking the initialisation status of elements of primitive arrays. +/// +/// InitMaps are saved for primitive arrays, so we don't have to have a +/// per-element InlineDescriptor. When the number of elements in the array +/// is small enough (see InitMap::isInline()), we use the pointer value +/// directly instead of allocating an InitMap. struct alignas(alignof(uint64_t)) InitMap final { private: /// Type packing bits. @@ -289,6 +294,28 @@ struct alignas(alignof(uint64_t)) InitMap final { /// Initializes the map with no fields set. explicit InitMap(unsigned N); + static bool isInline(size_t N) { + return N < (sizeof(uintptr_t) * CHAR_BIT - 1); + } + + static bool isInlineElementInitialized(uintptr_t BucketValue, unsigned I) { + return BucketValue & (uintptr_t(1) << I); + } + + static bool initializeInlineElement(InitMap *&IMPtr, size_t NumElems, + unsigned I) { + assert(isInline(NumElems)); + assert(I < NumElems); + uintptr_t BucketValue = reinterpret_cast<uintptr_t>(IMPtr); + uintptr_t Mask = uintptr_t(1) << I; + if (!(BucketValue & Mask)) { + BucketValue |= Mask; + IMPtr = reinterpret_cast<InitMap *>(BucketValue); + return static_cast<unsigned>(llvm::popcount(BucketValue)) == NumElems; + } + return false; + } + /// Checks if all elements have been initialized. static bool allInitialized(const InitMap *IM) { return reinterpret_cast<uintptr_t>(IM) == diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 8fa17aed29d9e..d2c579a94129b 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -454,17 +454,10 @@ bool Pointer::isInitialized() const { const Descriptor *Desc = getFieldDesc(); assert(Desc); - if (Desc->isPrimitiveArray()) { - InitMap *&IM = getInitMap(); - if (!IM) - return false; + if (Desc->isPrimitiveArray()) + return this->isElementInitialized(getIndex()); - if (InitMap::allInitialized(IM)) - return true; - return IM->isElementInitialized(getIndex()); - } - - if (asBlockPointer().Base == 0) + if (BS.Base == 0) return true; // Field has its bit in an inline descriptor. return getInlineDesc()->IsInitialized; @@ -477,6 +470,13 @@ bool Pointer::isElementInitialized(unsigned Index) const { if (Desc->isPrimitiveArray()) { assert(getFieldDesc()->isPrimitiveArray()); InitMap *&IM = getInitMap(); + unsigned NumElems = Desc->getNumElems(); + + if (InitMap::isInline(NumElems)) { + return InitMap::allInitialized(IM) || + InitMap::isInlineElementInitialized( + reinterpret_cast<uintptr_t>(IM), Index); + } if (!IM) return false; @@ -528,6 +528,12 @@ void Pointer::initializeElement(InterpState &S, unsigned Index) const { if (InitMap::allInitialized(IM)) return; + unsigned NumElems = getFieldDesc()->getNumElems(); + if (InitMap::isInline(NumElems)) { + if (InitMap::initializeInlineElement(IM, NumElems, Index)) + InitMap::markAllInitialized(IM); + return; + } // nullptr means no initmap yet. if (!IM) { unsigned NumElems = getFieldDesc()->getNumElems(); `````````` </details> https://github.com/llvm/llvm-project/pull/171093 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
