[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