[llvm-commits] [llvm] r67979 - in /llvm/trunk/include/llvm: ADT/PointerIntPair.h Instruction.h Support/PointerLikeTypeTraits.h Use.h

Chris Lattner sabre at nondot.org
Sat Mar 28 21:32:38 PDT 2009


Author: lattner
Date: Sat Mar 28 23:32:37 2009
New Revision: 67979

URL: http://llvm.org/viewvc/llvm-project?rev=67979&view=rev
Log:
Replace the PointerLikeTypeTraits::getNumLowBitsAvailable
function with a new NumLowBitsAvailable enum, which makes the
value available as an integer constant expression.

Add PointerLikeTypeTraits specializations for Instruction* and
Use** since they are only guaranteed 4-byte aligned.

Enhance PointerIntPair to know about (and enforce) the alignment
specified by PointerLikeTypeTraits.  This should allow things 
like PointerIntPair<PointerIntPair<void*, 1,bool>, 1, bool> 
because the inner one knows that 2 low bits are free.


Modified:
    llvm/trunk/include/llvm/ADT/PointerIntPair.h
    llvm/trunk/include/llvm/Instruction.h
    llvm/trunk/include/llvm/Support/PointerLikeTypeTraits.h
    llvm/trunk/include/llvm/Use.h

Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PointerIntPair.h?rev=67979&r1=67978&r2=67979&view=diff

==============================================================================
--- llvm/trunk/include/llvm/ADT/PointerIntPair.h (original)
+++ llvm/trunk/include/llvm/ADT/PointerIntPair.h Sat Mar 28 23:32:37 2009
@@ -15,50 +15,77 @@
 #define LLVM_ADT_POINTERINTPAIR_H
 
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
 #include <cassert>
 
 namespace llvm {
 
 template<typename T>
 struct DenseMapInfo;
-template<typename>
-class PointerLikeTypeTraits;
 
 /// PointerIntPair - This class implements a pair of a pointer and small
 /// integer.  It is designed to represent this in the space required by one
 /// pointer by bitmangling the integer into the low part of the pointer.  This
 /// can only be done for small integers: typically up to 3 bits, but it depends
-/// on the alignment returned by the allocator in use.
+/// on the number of bits available according to PointerLikeTypeTraits for the
+/// type.
+///
+/// Note that PointerIntPair always puts the Int part in the highest bits
+/// possible.  For example, PointerIntPair<void*, 1,bool> will put the bit for
+/// the bool into bit #2, not bit #0, which allows the low two bits to be used
+/// for something else.  For example, this allows:
+///   PointerIntPair<PointerIntPair<void*, 1,bool>, 1, bool>
+/// ... and the two bools will land in different bits.
 ///
 template <typename PointerTy, unsigned IntBits, typename IntType=unsigned>
 class PointerIntPair {
   intptr_t Value;
+  typedef PointerLikeTypeTraits<PointerTy> PtrTraits;
+  enum {
+    /// PointerBitMask - The bits that come from the pointer.
+    PointerBitMask = ~(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1),
+    /// IntShift - The number of low bits that we reserve for other uses, and
+    /// keep zero.
+    IntShift = PtrTraits::NumLowBitsAvailable-IntBits,
+    
+    /// IntMask - This is the unshifted mask for valid bits of the int type.
+    IntMask = ((intptr_t)1 << IntBits)-1,
+    
+    // ShiftedIntMask - This is the bits for the integer shifted in place.
+    ShiftedIntMask = IntMask << IntShift
+  };
 public:
   PointerIntPair() : Value(0) {}
   PointerIntPair(PointerTy Ptr, IntType Int) : Value(0) {
+    assert(IntBits <= PtrTraits::NumLowBitsAvailable &&
+           "PointerIntPair formed with integer size too large for pointer");
     setPointer(Ptr);
     setInt(Int);
   }
 
   PointerTy getPointer() const {
-    return reinterpret_cast<PointerTy>(Value & ~((1 << IntBits)-1));
+    return reinterpret_cast<PointerTy>(Value & PointerBitMask);
   }
 
   IntType getInt() const {
-    return (IntType)(Value & ((1 << IntBits)-1));
+    return (IntType)((Value >> IntShift) & IntMask);
   }
 
   void setPointer(PointerTy Ptr) {
     intptr_t PtrVal = reinterpret_cast<intptr_t>(Ptr);
-    assert((PtrVal & ((1 << IntBits)-1)) == 0 &&
+    assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 &&
            "Pointer is not sufficiently aligned");
-    Value = PtrVal | (intptr_t)getInt();
+    // Preserve all low bits, just update the pointer.
+    Value = PtrVal | (Value & ~PointerBitMask);
   }
 
   void setInt(IntType Int) {
     intptr_t IntVal = Int;
     assert(IntVal < (1 << IntBits) && "Integer too large for field");
-    Value = reinterpret_cast<intptr_t>(getPointer()) | IntVal;
+    
+    // Preserve all bits other than the ones we are updating.
+    Value &= ~ShiftedIntMask;     // Remove integer field.
+    Value |= IntVal << IntShift;  // Set new integer.
   }
 
   void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); }
@@ -107,7 +134,10 @@
   getFromVoidPointer(void *P) {
     return PointerIntPair<PointerTy, IntBits, IntType>::getFromOpaqueValue(P);
   }
-  static inline unsigned getNumLowBitsAvailable() { return 0; }
+  enum {
+    NumLowBitsAvailable = 
+           PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable - IntBits
+  };
 };
 
 } // end namespace llvm

Modified: llvm/trunk/include/llvm/Instruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instruction.h?rev=67979&r1=67978&r2=67979&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Instruction.h (original)
+++ llvm/trunk/include/llvm/Instruction.h Sat Mar 28 23:32:37 2009
@@ -227,6 +227,18 @@
   };
 };
 
+// Instruction* is only 4-byte aligned.
+template<>
+class PointerLikeTypeTraits<Instruction*> {
+  typedef Instruction* PT;
+public:
+  static inline void *getAsVoidPointer(PT P) { return P; }
+  static inline PT getFromVoidPointer(void *P) {
+    return static_cast<PT>(P);
+  }
+  enum { NumLowBitsAvailable = 2 };
+};
+  
 } // End llvm namespace
 
 #endif

Modified: llvm/trunk/include/llvm/Support/PointerLikeTypeTraits.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/PointerLikeTypeTraits.h?rev=67979&r1=67978&r2=67979&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Support/PointerLikeTypeTraits.h (original)
+++ llvm/trunk/include/llvm/Support/PointerLikeTypeTraits.h Sat Mar 28 23:32:37 2009
@@ -42,7 +42,7 @@
   ///
   /// All clients should use assertions to do a run-time check to ensure that
   /// this is actually true.
-  static inline unsigned getNumLowBitsAvailable() { return 3; }
+  enum { NumLowBitsAvailable = 3 };
 };
   
 // Provide PointerLikeTypeTraits for const pointers.
@@ -53,7 +53,7 @@
   static inline const T *getFromVoidPointer(const void *P) {
     return static_cast<const T*>(P);
   }
-  static inline unsigned getNumLowBitsAvailable() { return 3; }
+  enum { NumLowBitsAvailable = 3 };
 };
   
 } // end namespace llvm

Modified: llvm/trunk/include/llvm/Use.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Use.h?rev=67979&r1=67978&r2=67979&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Use.h (original)
+++ llvm/trunk/include/llvm/Use.h Sat Mar 28 23:32:37 2009
@@ -24,11 +24,21 @@
 
 class Value;
 class User;
-
+class Use;
 
 /// Tag - generic tag type for (at least 32 bit) pointers
 enum Tag { noTag, tagOne, tagTwo, tagThree };
 
+// Use** is only 4-byte aligned.
+template<>
+class PointerLikeTypeTraits<Use**> {
+public:
+  static inline void *getAsVoidPointer(Use** P) { return P; }
+  static inline Use **getFromVoidPointer(void *P) {
+    return static_cast<Use**>(P);
+  }
+  enum { NumLowBitsAvailable = 2 };
+};
 
 //===----------------------------------------------------------------------===//
 //                                  Use Class
@@ -212,7 +222,7 @@
 
 template<> struct simplify_type<const value_use_iterator<const User> >
   : public simplify_type<value_use_iterator<const User> > {};
-
+ 
 } // End llvm namespace
 
 #endif





More information about the llvm-commits mailing list