[clang] Remove type-punning in LazyOffsetPtr. (PR #112806)
Jessica Clarke via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 17 18:24:04 PDT 2024
================
@@ -321,50 +322,87 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
/// external AST source itself.
template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
struct LazyOffsetPtr {
- /// Either a pointer to an AST node or the offset within the
- /// external AST source where the AST node can be found.
- ///
- /// If the low bit is clear, a pointer to the AST node. If the low
- /// bit is set, the upper 63 bits are the offset.
- mutable uint64_t Ptr = 0;
+ /// Storage for a pointer or an offset, for the case where pointers are 64
+ /// bits wide. The least-significant bit is used as the discriminator. If the
+ /// bit is clear, a pointer to the AST node. If the bit is set, the upper 63
+ /// bits are the offset.
+ union StorageType64 {
+ StorageType64(uint64_t Offset) : ShiftedOffset((Offset << 1) | 1) {
+ assert(isOffset());
+ }
+ StorageType64(T *Ptr) : Pointer(Ptr) { assert(!isOffset()); }
+
+ bool isOffset() { return llvm::bit_cast<uint64_t>(*this) & 1; }
+ uint64_t offset() { return ShiftedOffset >> 1; }
+ T *&pointer() { return Pointer; }
+
+ uint64_t ShiftedOffset;
+ T *Pointer;
+ };
+
+ /// Storage for a pointer or an offset, for the case where pointers are not 64
+ /// bits wide.
+ union StorageType32 {
+ StorageType32(uint64_t Off) : Offset{true, Off} {}
+ StorageType32(T *Ptr) : Pointer{false, Ptr} {}
+
+ bool isOffset() { return Offset.IsOffset; }
+ uint64_t offset() { return Offset.Offset; }
+ T *&pointer() { return Pointer.Pointer; }
+
+ struct OffsetType {
+ uint64_t IsOffset : 1;
+ uint64_t Offset : 63;
+ } Offset;
+ struct PointerType {
+ uint64_t IsOffset : 1;
+ T *Pointer;
+ } Pointer;
+ };
+
+ mutable std::conditional_t<sizeof(uint64_t) == sizeof(T *), StorageType64,
+ StorageType32>
----------------
jrtc27 wrote:
Systems where `sizeof(void *) > 8` end up using StorageType32 which is highly inefficient, as PointerType will be two pointers in size rather than just using a single pointer as storage.
https://github.com/llvm/llvm-project/pull/112806
More information about the cfe-commits
mailing list