[PATCH] D89951: [ptr-traits] Add a LowPointerIntPair alias
Nathan James via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 22 04:56:12 PDT 2020
njames93 created this revision.
njames93 added a reviewer: chandlerc.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
njames93 requested review of this revision.
This adds an LowPointerIntPair alias that makes a PointerIntPair store the int in the lowest bit positions.
This partially limits chaining, but simplifies accessing the int by removing the need for shifts.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D89951
Files:
llvm/include/llvm/ADT/PointerIntPair.h
llvm/unittests/ADT/PointerIntPairTest.cpp
Index: llvm/unittests/ADT/PointerIntPairTest.cpp
===================================================================
--- llvm/unittests/ADT/PointerIntPairTest.cpp
+++ llvm/unittests/ADT/PointerIntPairTest.cpp
@@ -106,4 +106,22 @@
"trivially copyable");
}
+TEST(PointerIntPairTest, LowPointerIntPair) {
+ static_assert(PointerLikeTypeTraits<
+ LowPointerIntPair<void *, 1>>::NumLowBitsAvailable == 0,
+ "Using LowestBits");
+
+ // Use double as guaranteed 8 byte alignment on 32 or 64 bit, meaning 3 bits
+ // to play with.
+ LowPointerIntPair<PointerIntPair<double *, 1, bool>, 1, bool> P;
+ // Ensure they are both using different bits, and that the LowPointerIntPair
+ // is using the LSB.
+ P.setPointerAndInt({nullptr, true}, false);
+ EXPECT_EQ(reinterpret_cast<uintptr_t>(P.getOpaqueValue()), 0b100U);
+ P.setInt(true);
+ EXPECT_EQ(reinterpret_cast<uintptr_t>(P.getOpaqueValue()), 0b101U);
+ P.getAddrOfPointer()->setInt(false);
+ EXPECT_EQ(reinterpret_cast<uintptr_t>(P.getOpaqueValue()), 0b001U);
+}
+
} // end anonymous namespace
Index: llvm/include/llvm/ADT/PointerIntPair.h
===================================================================
--- llvm/include/llvm/ADT/PointerIntPair.h
+++ llvm/include/llvm/ADT/PointerIntPair.h
@@ -127,6 +127,36 @@
}
};
+namespace detail {
+template <typename T, unsigned Bits> struct ForceLowBitsPointerTraits {
+ using Base = llvm::PointerLikeTypeTraits<T>;
+ static_assert(Bits <= Base::NumLowBitsAvailable,
+ "Too many bits specified for Base Traits");
+
+ static inline void *getAsVoidPointer(T P) {
+ return Base::getAsVoidPointer(P);
+ }
+ static inline T getFromVoidPointer(void *P) {
+ return Base::getFromVoidPointer(P);
+ }
+
+ static constexpr int NumLowBitsAvailable = Bits;
+};
+} // namespace detail
+
+/// LowPointerIntPair - This is a \ref PointerIntPair that stores the IntVal in
+/// the lowest bits. This removes the need for shifts when accessing the stored
+/// IntVal. As it is using the lowest bits, this can't be used as a PointerType
+/// inside a nested PointerIntPair. However it can have nested PointerIntPairs
+/// used as its own PointerType, like this:
+/// LowPointerIntPair<PointerIntPair<void*, 1>, 1>
+/// LowPointerIntPair will use bit #0,
+/// PointerIntPair will use bit #1 or #2 depending on alignment of void*.
+template <typename PointerTy, unsigned IntBits, typename IntType = unsigned>
+using LowPointerIntPair =
+ PointerIntPair<PointerTy, IntBits, IntType,
+ detail::ForceLowBitsPointerTraits<PointerTy, IntBits>>;
+
// Specialize is_trivially_copyable to avoid limitation of llvm::is_trivially_copyable
// when compiled with gcc 4.9.
template <typename PointerTy, unsigned IntBits, typename IntType,
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D89951.299926.patch
Type: text/x-patch
Size: 2809 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201022/edbd1b0a/attachment.bin>
More information about the llvm-commits
mailing list