Fix a limitation of SmallPtrSet. Before it would assert if the smallsize
authorChris Lattner <sabre@nondot.org>
Sat, 27 Jan 2007 07:52:27 +0000 (07:52 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 27 Jan 2007 07:52:27 +0000 (07:52 +0000)
was not a power of two.  Now it rounds up to the next power of two internally.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33580 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/SmallPtrSet.h

index d617d6b3b0b5ad8278d2a8283353cc2bac0cbfba..d2a68ff90f388d6e36f9be31f98df5faf9053b93 100644 (file)
@@ -161,13 +161,41 @@ public:
   }
 };
 
+/// NextPowerOfTwo - This is a helper template that rounds N up to the next
+/// power of two.
+template<unsigned N>
+struct NextPowerOfTwo;
+
+/// NextPowerOfTwoH - If N is not a power of two, increase it.  This is a helper
+/// template used to implement NextPowerOfTwo.
+template<unsigned N, bool isPowerTwo>
+struct NextPowerOfTwoH {
+  enum { Val = N };
+};
+template<unsigned N>
+struct NextPowerOfTwoH<N, false> {
+  enum {
+    // We could just use NextVal = N+1, but this converges faster.  N|(N-1) sets
+    // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111.
+    NextVal = (N|(N-1)) + 1,
+    Val = NextPowerOfTwo<NextVal>::Val
+  };
+};
+
+template<unsigned N>
+struct NextPowerOfTwo {
+  enum { Val = NextPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
+};
+
 
 /// SmallPtrSet - This class implements 
 template<class PtrType, unsigned SmallSize>
 class SmallPtrSet : public SmallPtrSetImpl {
-  void *SmallArray[SmallSize];
+  // Make sure that SmallSize is a power of two, round up if not.
+  enum { SmallSizePowTwo = NextPowerOfTwo<SmallSize>::Val };
+  void *SmallArray[SmallSizePowTwo];
 public:
-  SmallPtrSet() : SmallPtrSetImpl(SmallSize) {}
+  SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {}
   
   typedef SmallPtrSetIterator<PtrType> iterator;
   typedef SmallPtrSetIterator<PtrType> const_iterator;