From 46f829ee25ed0cba401cd759da684d3c4aa1478a Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 13 Dec 2013 20:47:37 +0000 Subject: [PATCH] [block-freq] Add the method APInt::nearestLogBase2(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197272 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APInt.h | 13 +++++++++++ unittests/ADT/APIntTest.cpp | 44 +++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 2073fa08cbf..2bb5c3e2a12 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -1507,6 +1507,19 @@ public: return BitWidth - (*this - 1).countLeadingZeros(); } + /// \returns the nearest log base 2 of this APInt. Ties round up. + 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. + + // 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. + unsigned lg = logBase2(); + return lg + unsigned(extractBit(std::min(lg - 1, BitWidth - 1))); + } + /// \returns the log base 2 of this APInt if its an exact power of two, -1 /// otherwise int32_t exactLogBase2() const { diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 1d330f0d369..36cbd868a2e 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -609,10 +609,10 @@ TEST(APIntTest, extractBit) { // Multiword check. integerPart E2[4] = { - 0xeb6eb136591cba21ULL, - 0x7b9358bd6a33f10aULL, - 0x7e7ffa5eadd8846ULL, - 0x305f341ca00b613dULL + 0xEB6EB136591CBA21ULL, + 0x7B9358BD6A33F10AULL, + 0x7E7FFA5EADD8846ULL, + 0x305F341CA00B613DULL }; APInt A2(integerPartWidth*4, ArrayRef(E2, 4)); for (unsigned i = 0; i < 4; ++i) { @@ -623,4 +623,40 @@ TEST(APIntTest, extractBit) { } } +TEST(APIntTest, nearestLogBase2) { + // Single word check. + + // Test round up. + uint64_t I1 = 0x1800001; + APInt A1(64, I1); + EXPECT_EQ(A1.nearestLogBase2(), A1.ceilLogBase2()); + + // Test round down. + uint64_t I2 = 0x1000011; + APInt A2(64, I2); + EXPECT_EQ(A2.nearestLogBase2(), A2.logBase2()); + + // Test ties round up. + uint64_t I3 = 0x1800000; + APInt A3(64, I3); + EXPECT_EQ(A3.nearestLogBase2(), A3.ceilLogBase2()); + + // Multiple word check. + + // Test round up. + integerPart I4[4] = {0x0, 0xF, 0x18, 0x0}; + APInt A4(integerPartWidth*4, ArrayRef(I4, 4)); + EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2()); + + // Test round down. + integerPart I5[4] = {0x0, 0xF, 0x10, 0x0}; + APInt A5(integerPartWidth*4, ArrayRef(I5, 4)); + EXPECT_EQ(A5.nearestLogBase2(), A5.logBase2()); + + // Test ties round up. + uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18}; + APInt A6(integerPartWidth*4, ArrayRef(I6, 4)); + EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2()); +} + } -- 2.34.1