[llvm] 7a6435b - [DenseMap] Do not align pointer sentinel values (NFC) (#146595)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 7 03:47:45 PDT 2025
Author: Nikita Popov
Date: 2025-07-07T12:47:41+02:00
New Revision: 7a6435bec59010e4bb2e1e52a9ba840ed152b4ce
URL: https://github.com/llvm/llvm-project/commit/7a6435bec59010e4bb2e1e52a9ba840ed152b4ce
DIFF: https://github.com/llvm/llvm-project/commit/7a6435bec59010e4bb2e1e52a9ba840ed152b4ce.diff
LOG: [DenseMap] Do not align pointer sentinel values (NFC) (#146595)
DenseMapInfo for pointers currently uses empty/tombstone values that are
aligned (by assuming a very conservative alignment). However, this means
that we have to work with larger immediates.
This patch proposes to use the values -1 and -2 instead, without caring
about pointer alignment. (Non-roundtrip) integer to pointer casts are
implementation-defined in C++, but the general implementer consensus
(including Clang) is that raw pointers do not carry alignment
requirements, only memory accesses do.
We already have lots of places that rely on this using variations on
`reinterpret_cast<T*>(-1)`, so it seems odd to insist on properly
aligned pointers in this one place.
It is necessary to adjust a few other places after this change, which
currently assume that `DenseMapInfo<void *>` returns a highly-aligned
pointer.
This is a small improvement for both compile-time and clang binary size.
Added:
Modified:
clang/lib/AST/APValue.cpp
llvm/include/llvm/ADT/DenseMapInfo.h
llvm/include/llvm/ADT/PointerUnion.h
mlir/include/mlir/Support/TypeID.h
mlir/lib/Bindings/Python/NanobindUtils.h
Removed:
################################################################################
diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp
index c641ff6b99bab..acba55742a967 100644
--- a/clang/lib/AST/APValue.cpp
+++ b/clang/lib/AST/APValue.cpp
@@ -187,14 +187,14 @@ APValue::LValueBase::operator bool () const {
clang::APValue::LValueBase
llvm::DenseMapInfo<clang::APValue::LValueBase>::getEmptyKey() {
clang::APValue::LValueBase B;
- B.Ptr = DenseMapInfo<const ValueDecl*>::getEmptyKey();
+ B.Ptr = DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getEmptyKey();
return B;
}
clang::APValue::LValueBase
llvm::DenseMapInfo<clang::APValue::LValueBase>::getTombstoneKey() {
clang::APValue::LValueBase B;
- B.Ptr = DenseMapInfo<const ValueDecl*>::getTombstoneKey();
+ B.Ptr = DenseMapInfo<clang::APValue::LValueBase::PtrTy>::getTombstoneKey();
return B;
}
diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h
index 07c37e353a40b..b371611e7d948 100644
--- a/llvm/include/llvm/ADT/DenseMapInfo.h
+++ b/llvm/include/llvm/ADT/DenseMapInfo.h
@@ -56,30 +56,13 @@ struct DenseMapInfo {
//static bool isEqual(const T &LHS, const T &RHS);
};
-// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
-// that are aligned to alignof(T) bytes, but try to avoid requiring T to be
-// complete. This allows clients to instantiate DenseMap<T*, ...> with forward
-// declared key types. Assume that no pointer key type requires more than 4096
-// bytes of alignment.
-template<typename T>
-struct DenseMapInfo<T*> {
- // The following should hold, but it would require T to be complete:
- // static_assert(alignof(T) <= (1 << Log2MaxAlign),
- // "DenseMap does not support pointer keys requiring more than "
- // "Log2MaxAlign bits of alignment");
- static constexpr uintptr_t Log2MaxAlign = 12;
-
+template <typename T> struct DenseMapInfo<T *> {
static inline T* getEmptyKey() {
- uintptr_t Val = static_cast<uintptr_t>(-1);
- Val <<= Log2MaxAlign;
- return reinterpret_cast<T*>(Val);
+ // We assume that raw pointers do not carry alignment requirements.
+ return reinterpret_cast<T *>(-1);
}
- static inline T* getTombstoneKey() {
- uintptr_t Val = static_cast<uintptr_t>(-2);
- Val <<= Log2MaxAlign;
- return reinterpret_cast<T*>(Val);
- }
+ static inline T *getTombstoneKey() { return reinterpret_cast<T *>(-2); }
static unsigned getHashValue(const T *PtrVal) {
return (unsigned((uintptr_t)PtrVal) >> 4) ^
diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h
index cdbd76d7f505b..86248a2cf836f 100644
--- a/llvm/include/llvm/ADT/PointerUnion.h
+++ b/llvm/include/llvm/ADT/PointerUnion.h
@@ -286,13 +286,19 @@ struct PointerLikeTypeTraits<PointerUnion<PTs...>> {
// Teach DenseMap how to use PointerUnions as keys.
template <typename ...PTs> struct DenseMapInfo<PointerUnion<PTs...>> {
using Union = PointerUnion<PTs...>;
- using FirstInfo =
- DenseMapInfo<typename pointer_union_detail::GetFirstType<PTs...>::type>;
+ using FirstTypeTraits = PointerLikeTypeTraits<
+ typename pointer_union_detail::GetFirstType<PTs...>::type>;
- static inline Union getEmptyKey() { return Union(FirstInfo::getEmptyKey()); }
+ static inline Union getEmptyKey() {
+ uintptr_t Val = static_cast<uintptr_t>(-1);
+ Val <<= FirstTypeTraits::NumLowBitsAvailable;
+ return FirstTypeTraits::getFromVoidPointer(reinterpret_cast<void *>(Val));
+ }
static inline Union getTombstoneKey() {
- return Union(FirstInfo::getTombstoneKey());
+ uintptr_t Val = static_cast<uintptr_t>(-2);
+ Val <<= FirstTypeTraits::NumLowBitsAvailable;
+ return FirstTypeTraits::getFromVoidPointer(reinterpret_cast<void *>(Val));
}
static unsigned getHashValue(const Union &UnionVal) {
diff --git a/mlir/include/mlir/Support/TypeID.h b/mlir/include/mlir/Support/TypeID.h
index 459e9dae12a9f..e2c25474087ae 100644
--- a/mlir/include/mlir/Support/TypeID.h
+++ b/mlir/include/mlir/Support/TypeID.h
@@ -395,11 +395,12 @@ namespace llvm {
template <>
struct DenseMapInfo<mlir::TypeID> {
static inline mlir::TypeID getEmptyKey() {
- void *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
+ // Shift by 3 to satisfy the TypeID alignment requirement.
+ void *pointer = reinterpret_cast<void *>(uintptr_t(-1) << 3);
return mlir::TypeID::getFromOpaquePointer(pointer);
}
static inline mlir::TypeID getTombstoneKey() {
- void *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
+ void *pointer = reinterpret_cast<void *>(uintptr_t(-2) << 3);
return mlir::TypeID::getFromOpaquePointer(pointer);
}
static unsigned getHashValue(mlir::TypeID val) {
diff --git a/mlir/lib/Bindings/Python/NanobindUtils.h b/mlir/lib/Bindings/Python/NanobindUtils.h
index 64ea4329f65f1..535fc2328c482 100644
--- a/mlir/lib/Bindings/Python/NanobindUtils.h
+++ b/mlir/lib/Bindings/Python/NanobindUtils.h
@@ -408,11 +408,12 @@ namespace llvm {
template <>
struct DenseMapInfo<MlirTypeID> {
static inline MlirTypeID getEmptyKey() {
- auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
+ // Shift by 3 to satisfy the TypeID alignment requirement.
+ void *pointer = reinterpret_cast<void *>(uintptr_t(-1) << 3);
return mlirTypeIDCreate(pointer);
}
static inline MlirTypeID getTombstoneKey() {
- auto *pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
+ void *pointer = reinterpret_cast<void *>(uintptr_t(-2) << 3);
return mlirTypeIDCreate(pointer);
}
static inline unsigned getHashValue(const MlirTypeID &val) {
More information about the llvm-commits
mailing list