[llvm] 9d77ad5 - [APInt] Introduce APIntOps::GetMostSignificantDifferentBit()
Roman Lebedev via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 26 13:22:29 PDT 2019
Author: Roman Lebedev
Date: 2019-10-26T23:20:58+03:00
New Revision: 9d77ad57540c45b0a6e6ffcf8721a3189c0ed70e
URL: https://github.com/llvm/llvm-project/commit/9d77ad57540c45b0a6e6ffcf8721a3189c0ed70e
DIFF: https://github.com/llvm/llvm-project/commit/9d77ad57540c45b0a6e6ffcf8721a3189c0ed70e.diff
LOG: [APInt] Introduce APIntOps::GetMostSignificantDifferentBit()
Summary:
Compare two values, and if they are different, return the position of the
most significant bit that is different in the values.
Needed for D69387.
Reviewers: nikic, spatel, sanjoy, RKSimon
Reviewed By: nikic
Subscribers: xbolva00, hiraditya, dexonsmith, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69439
Added:
Modified:
llvm/include/llvm/ADT/APInt.h
llvm/lib/Support/APInt.cpp
llvm/unittests/ADT/APIntTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 6a08e6eed53d..07b2e80099e6 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -2220,6 +2220,12 @@ APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM);
/// coefficients.
Optional<APInt> SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
unsigned RangeWidth);
+
+/// Compare two values, and if they are
diff erent, return the position of the
+/// most significant bit that is
diff erent in the values.
+Optional<unsigned> GetMostSignificantDifferentBit(const APInt &A,
+ const APInt &B);
+
} // End of APIntOps namespace
// See friend declaration above. This additional declaration is required in
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 08e9757702af..5f2686c4055c 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -3027,6 +3027,14 @@ llvm::APIntOps::SolveQuadraticEquationWrap(APInt A, APInt B, APInt C,
return X;
}
+Optional<unsigned>
+llvm::APIntOps::GetMostSignificantDifferentBit(const APInt &A, const APInt &B) {
+ assert(A.getBitWidth() == B.getBitWidth() && "Must have the same bitwidth");
+ if (A == B)
+ return llvm::None;
+ return A.getBitWidth() - ((A ^ B).countLeadingZeros() + 1);
+}
+
/// StoreIntToMemory - Fills the StoreBytes bytes of memory starting from Dst
/// with the integer held in IntVal.
void llvm::StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp
index 5130b9420d67..fe4e74260990 100644
--- a/llvm/unittests/ADT/APIntTest.cpp
+++ b/llvm/unittests/ADT/APIntTest.cpp
@@ -2723,4 +2723,75 @@ TEST(APIntTest, MultiplicativeInverseExaustive) {
}
}
+TEST(APIntTest, GetMostSignificantDifferentBit) {
+ EXPECT_EQ(APIntOps::GetMostSignificantDifferentBit(APInt(8, 0), APInt(8, 0)),
+ llvm::None);
+ EXPECT_EQ(
+ APIntOps::GetMostSignificantDifferentBit(APInt(8, 42), APInt(8, 42)),
+ llvm::None);
+ EXPECT_EQ(*APIntOps::GetMostSignificantDifferentBit(APInt(8, 0), APInt(8, 1)),
+ 0u);
+ EXPECT_EQ(*APIntOps::GetMostSignificantDifferentBit(APInt(8, 0), APInt(8, 2)),
+ 1u);
+ EXPECT_EQ(*APIntOps::GetMostSignificantDifferentBit(APInt(8, 0), APInt(8, 3)),
+ 1u);
+ EXPECT_EQ(*APIntOps::GetMostSignificantDifferentBit(APInt(8, 1), APInt(8, 0)),
+ 0u);
+ EXPECT_EQ(APIntOps::GetMostSignificantDifferentBit(APInt(8, 1), APInt(8, 1)),
+ llvm::None);
+ EXPECT_EQ(*APIntOps::GetMostSignificantDifferentBit(APInt(8, 1), APInt(8, 2)),
+ 1u);
+ EXPECT_EQ(*APIntOps::GetMostSignificantDifferentBit(APInt(8, 1), APInt(8, 3)),
+ 1u);
+ EXPECT_EQ(
+ *APIntOps::GetMostSignificantDifferentBit(APInt(8, 42), APInt(8, 112)),
+ 6u);
+}
+
+TEST(APIntTest, GetMostSignificantDifferentBitExaustive) {
+ auto GetHighestDifferentBitBruteforce =
+ [](const APInt &V0, const APInt &V1) -> llvm::Optional<unsigned> {
+ assert(V0.getBitWidth() == V1.getBitWidth() && "Must have same bitwidth");
+ if (V0 == V1)
+ return llvm::None; // Bitwise identical.
+ // There is a mismatch. Let's find the most significant
diff erent bit.
+ for (int Bit = V0.getBitWidth() - 1; Bit >= 0; --Bit) {
+ if (V0[Bit] == V1[Bit])
+ continue;
+ return Bit;
+ }
+ llvm_unreachable("Must have found bit mismatch.");
+ };
+
+ for (unsigned BitWidth = 1; BitWidth <= 8; ++BitWidth) {
+ for (unsigned V0 = 0; V0 < (1u << BitWidth); ++V0) {
+ for (unsigned V1 = 0; V1 < (1u << BitWidth); ++V1) {
+ APInt A = APInt(BitWidth, V0);
+ APInt B = APInt(BitWidth, V1);
+
+ auto Bit = APIntOps::GetMostSignificantDifferentBit(A, B);
+ EXPECT_EQ(Bit, GetHighestDifferentBitBruteforce(A, B));
+
+ if (!Bit.hasValue())
+ EXPECT_EQ(A, B);
+ else {
+ EXPECT_NE(A, B);
+ for (unsigned NumLowBits = 0; NumLowBits <= BitWidth; ++NumLowBits) {
+ APInt Adash = A;
+ Adash.clearLowBits(NumLowBits);
+ APInt Bdash = B;
+ Bdash.clearLowBits(NumLowBits);
+ // Clearing only low bits up to and including *Bit is sufficient
+ // to make values equal.
+ if (NumLowBits >= 1 + *Bit)
+ EXPECT_EQ(Adash, Bdash);
+ else
+ EXPECT_NE(Adash, Bdash);
+ }
+ }
+ }
+ }
+ }
+}
+
} // end anonymous namespace
More information about the llvm-commits
mailing list