Author: Arthur Eubanks Date: 2022-01-26T10:35:28-08:00 New Revision: b1613f05ae0ce4efc6b6475ea4459957ebcb0150
URL: https://github.com/llvm/llvm-project/commit/b1613f05ae0ce4efc6b6475ea4459957ebcb0150 DIFF: https://github.com/llvm/llvm-project/commit/b1613f05ae0ce4efc6b6475ea4459957ebcb0150.diff LOG: [NFC] Store Address's alignment into PointerIntPairs This mitigates the extra memory caused by D115725. On 32-bit arches where we only have 2 bits per PointerIntPair we fall back to simply storing alignment separately. Reviewed By: rnk, nikic Differential Revision: https://reviews.llvm.org/D117262 Added: Modified: clang/lib/CodeGen/Address.h Removed: ################################################################################ diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index 37c20291c0e80..06b82e404cce4 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -14,30 +14,79 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H -#include "llvm/IR/Constants.h" #include "clang/AST/CharUnits.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/IR/Constants.h" +#include "llvm/Support/MathExtras.h" namespace clang { namespace CodeGen { -/// An aligned address. -class Address { +namespace { +// We try to save some space by using 6 bits over two PointerIntPairs to store +// the alignment. However, some arches don't support 3 bits in a PointerIntPair +// so we fallback to storing the alignment separately. +template <typename T, bool = alignof(llvm::Value *) >= 8> class AddressImpl {}; + +template <typename T> class AddressImpl<T, false> { llvm::Value *Pointer; llvm::Type *ElementType; CharUnits Alignment; +public: + AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType, + CharUnits Alignment) + : Pointer(Pointer), ElementType(ElementType), Alignment(Alignment) {} + llvm::Value *getPointer() const { return Pointer; } + llvm::Type *getElementType() const { return ElementType; } + CharUnits getAlignment() const { return Alignment; } +}; + +template <typename T> class AddressImpl<T, true> { + // Int portion stores upper 3 bits of the log of the alignment. + llvm::PointerIntPair<llvm::Value *, 3, unsigned> Pointer; + // Int portion stores lower 3 bits of the log of the alignment. + llvm::PointerIntPair<llvm::Type *, 3, unsigned> ElementType; + +public: + AddressImpl(llvm::Value *Pointer, llvm::Type *ElementType, + CharUnits Alignment) + : Pointer(Pointer), ElementType(ElementType) { + if (Alignment.isZero()) + return; + // Currently the max supported alignment is much less than 1 << 63 and is + // guaranteed to be a power of 2, so we can store the log of the alignment + // into 6 bits. + assert(Alignment.isPowerOfTwo() && "Alignment cannot be zero"); + auto AlignLog = llvm::Log2_64(Alignment.getQuantity()); + assert(AlignLog < (1 << 6) && "cannot fit alignment into 6 bits"); + this->Pointer.setInt(AlignLog >> 3); + this->ElementType.setInt(AlignLog & 7); + } + llvm::Value *getPointer() const { return Pointer.getPointer(); } + llvm::Type *getElementType() const { return ElementType.getPointer(); } + CharUnits getAlignment() const { + unsigned AlignLog = (Pointer.getInt() << 3) | ElementType.getInt(); + return CharUnits::fromQuantity(1UL << AlignLog); + } +}; +} // namespace + +/// An aligned address. +class Address { + AddressImpl<void> A; + protected: - Address(std::nullptr_t) : Pointer(nullptr), ElementType(nullptr) {} + Address(std::nullptr_t) : A(nullptr, nullptr, CharUnits::Zero()) {} public: - Address(llvm::Value *pointer, llvm::Type *elementType, CharUnits alignment) - : Pointer(pointer), ElementType(elementType), Alignment(alignment) { - assert(pointer != nullptr && "Pointer cannot be null"); - assert(elementType != nullptr && "Element type cannot be null"); - assert(llvm::cast<llvm::PointerType>(pointer->getType()) - ->isOpaqueOrPointeeTypeMatches(elementType) && + Address(llvm::Value *Pointer, llvm::Type *ElementType, CharUnits Alignment) + : A(Pointer, ElementType, Alignment) { + assert(Pointer != nullptr && "Pointer cannot be null"); + assert(ElementType != nullptr && "Element type cannot be null"); + assert(llvm::cast<llvm::PointerType>(Pointer->getType()) + ->isOpaqueOrPointeeTypeMatches(ElementType) && "Incorrect pointer element type"); - assert(!alignment.isZero() && "Alignment cannot be zero"); } // Deprecated: Use constructor with explicit element type instead. @@ -46,11 +95,11 @@ class Address { Alignment) {} static Address invalid() { return Address(nullptr); } - bool isValid() const { return Pointer != nullptr; } + bool isValid() const { return A.getPointer() != nullptr; } llvm::Value *getPointer() const { assert(isValid()); - return Pointer; + return A.getPointer(); } /// Return the type of the pointer value. @@ -61,7 +110,7 @@ class Address { /// Return the type of the values stored in this address. llvm::Type *getElementType() const { assert(isValid()); - return ElementType; + return A.getElementType(); } /// Return the address space that this address resides in. @@ -77,19 +126,19 @@ class Address { /// Return the alignment of this pointer. CharUnits getAlignment() const { assert(isValid()); - return Alignment; + return A.getAlignment(); } /// Return address with diff erent pointer, but same element type and /// alignment. Address withPointer(llvm::Value *NewPointer) const { - return Address(NewPointer, ElementType, Alignment); + return Address(NewPointer, getElementType(), getAlignment()); } /// Return address with diff erent alignment, but same pointer and element /// type. Address withAlignment(CharUnits NewAlignment) const { - return Address(Pointer, ElementType, NewAlignment); + return Address(getPointer(), getElementType(), NewAlignment); } }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits