[llvm] r199610 - [APInt] Fix nearestLogBase2 to return correct answers for very large APInt and APInt with a bitwidth of 1.

Michael Gottesman mgottesman at apple.com
Sun Jan 19 12:33:48 PST 2014


Author: mgottesman
Date: Sun Jan 19 14:33:48 2014
New Revision: 199610

URL: http://llvm.org/viewvc/llvm-project?rev=199610&view=rev
Log:
[APInt] Fix nearestLogBase2 to return correct answers for very large APInt and APInt with a bitwidth of 1.

I also improved the comments, added some more tests, etc.

Modified:
    llvm/trunk/include/llvm/ADT/APInt.h
    llvm/trunk/unittests/ADT/APIntTest.cpp

Modified: llvm/trunk/include/llvm/ADT/APInt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=199610&r1=199609&r2=199610&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APInt.h (original)
+++ llvm/trunk/include/llvm/ADT/APInt.h Sun Jan 19 14:33:48 2014
@@ -1505,16 +1505,32 @@ public:
   }
 
   /// \returns the nearest log base 2 of this APInt. Ties round up.
+  ///
+  /// NOTE: When we have a BitWidth of 1, we define:
+  /// 
+  ///   log2(0) = UINT32_MAX
+  ///   log2(1) = 0
+  ///
+  /// to get around any mathematical concerns resulting from
+  /// referencing 2 in a space where 2 does no exist.
   unsigned nearestLogBase2() const {
-    // This is implemented by taking the normal log 2 of a number and adding 1
-    // to it if MSB - 1 is set.
+    // Special case when we have a bitwidth of 1. If VAL is 1, then we
+    // get 0. If VAL is 0, we get UINT64_MAX which gets truncated to
+    // UINT32_MAX.
+    if (BitWidth == 1)
+      return VAL - 1;
 
-    // We follow the model from logBase2 that logBase2(0) == UINT32_MAX. This
-    // works since if we have 0, MSB will be 0. Then we subtract one yielding
-    // UINT32_MAX. Finally extractBit of MSB - 1 will be UINT32_MAX implying
-    // that we get BitWidth - 1.
+    // Handle the zero case.
+    if (!getBoolValue())
+      return UINT32_MAX;
+
+    // The non-zero case is handled by computing:
+    //
+    //   nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1].
+    //
+    // where x[i] is referring to the value of the ith bit of x.
     unsigned lg = logBase2();
-    return lg + unsigned((*this)[std::min(lg - 1, BitWidth - 1)]);
+    return lg + unsigned((*this)[lg - 1]);
   }
 
   /// \returns the log base 2 of this APInt if its an exact power of two, -1

Modified: llvm/trunk/unittests/ADT/APIntTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=199610&r1=199609&r2=199610&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APIntTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APIntTest.cpp Sun Jan 19 14:33:48 2014
@@ -665,6 +665,17 @@ TEST(APIntTest, nearestLogBase2) {
   uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18};
   APInt A6(integerPartWidth*4, ArrayRef<integerPart>(I6, 4));
   EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2());
+
+  // Test BitWidth == 1 special cases.
+  APInt A7(1, 1);
+  EXPECT_EQ(A7.nearestLogBase2(), 0ULL);
+  APInt A8(1, 0);
+  EXPECT_EQ(A8.nearestLogBase2(), UINT32_MAX);
+
+  // Test the zero case when we have a bit width large enough such
+  // that the bit width is larger than UINT32_MAX-1.
+  APInt A9(UINT32_MAX, 0);
+  EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX);
 }
 
 }





More information about the llvm-commits mailing list