aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/ADT/APIntTest.cpp
diff options
context:
space:
mode:
authorChris Lattner <clattner@nondot.org>2021-09-09 16:20:25 -0700
committerChris Lattner <clattner@nondot.org>2021-09-09 22:43:54 -0700
commit704a39569346401e96a6a3978ddc490dfa828ccc (patch)
treee1a478506950c7b0ae058478cdff80b43a204964 /llvm/unittests/ADT/APIntTest.cpp
parent7f793b102c9a11eddcf247da8043a3556581e7c1 (diff)
downloadllvm-704a39569346401e96a6a3978ddc490dfa828ccc.zip
llvm-704a39569346401e96a6a3978ddc490dfa828ccc.tar.gz
llvm-704a39569346401e96a6a3978ddc490dfa828ccc.tar.bz2
[APInt] Enable APInt to support zero bit integers.
Motivation: APInt not supporting zero bit values leads to a lot of special cases in various bits of code, particularly when using APInt as a bit vector (where you want to start with zero bits and then concat on more. This is particularly challenging in the CIRCT project, where the absence of zero-bit ConstantOp forces duplication of ops and makes instcombine-like logic far more complicated. Approach: zero bit integers are weird. There are two reasonable approaches: either make it illegal to do general arithmetic on them (e.g. sign extends), or treat them as as implicitly having a zero value. This patch takes the conservative approach, which enables their use in bitvector applications. Differential Revision: https://reviews.llvm.org/D109555
Diffstat (limited to 'llvm/unittests/ADT/APIntTest.cpp')
-rw-r--r--llvm/unittests/ADT/APIntTest.cpp76
1 files changed, 75 insertions, 1 deletions
diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp
index 74e0c46..0f8f462 100644
--- a/llvm/unittests/ADT/APIntTest.cpp
+++ b/llvm/unittests/ADT/APIntTest.cpp
@@ -1422,7 +1422,6 @@ TEST(APIntTest, Log2) {
#ifdef GTEST_HAS_DEATH_TEST
#ifndef NDEBUG
TEST(APIntTest, StringDeath) {
- EXPECT_DEATH((void)APInt(0, "", 0), "Bitwidth too small");
EXPECT_DEATH((void)APInt(32, "", 0), "Invalid string length");
EXPECT_DEATH((void)APInt(32, "0", 0), "Radix should be 2, 8, 10, 16, or 36!");
EXPECT_DEATH((void)APInt(32, "", 10), "Invalid string length");
@@ -2908,4 +2907,79 @@ TEST(APIntTest, SignbitZeroChecks) {
EXPECT_FALSE(APInt(8, 1).isNonPositive());
}
+TEST(APIntTest, ZeroWidth) {
+ // Zero width Constructors.
+ auto ZW = APInt::getZeroWidth();
+ EXPECT_EQ(0U, ZW.getBitWidth());
+ EXPECT_EQ(0U, APInt(0, ArrayRef<uint64_t>({0, 1, 2})).getBitWidth());
+ EXPECT_EQ(0U, APInt(0, "0", 10).getBitWidth());
+
+ // Default constructor is single bit wide.
+ EXPECT_EQ(1U, APInt().getBitWidth());
+
+ // Copy ctor (move is down below).
+ APInt ZW2(ZW);
+ EXPECT_EQ(0U, ZW2.getBitWidth());
+ // Assignment
+ ZW = ZW2;
+ EXPECT_EQ(0U, ZW.getBitWidth());
+
+ // Methods like getLowBitsSet work with zero bits.
+ EXPECT_EQ(0U, APInt::getLowBitsSet(0, 0).getBitWidth());
+ EXPECT_EQ(0U, APInt::getSplat(0, ZW).getBitWidth());
+
+ // Logical operators.
+ ZW |= ZW2;
+ ZW &= ZW2;
+ ZW ^= ZW2;
+ ZW |= 42; // These ignore high bits of the literal.
+ ZW &= 42;
+ ZW ^= 42;
+ EXPECT_EQ(1, ZW.isIntN(0));
+
+ // Modulo Arithmetic. Divide/Rem aren't defined on division by zero, so they
+ // aren't supported.
+ ZW += ZW2;
+ ZW -= ZW2;
+ ZW *= ZW2;
+
+ // Logical Shifts and rotates, the amount must be <= bitwidth.
+ ZW <<= 0;
+ ZW.lshrInPlace(0);
+ (void)ZW.rotl(0);
+ (void)ZW.rotr(0);
+
+ // Comparisons.
+ EXPECT_EQ(1, ZW == ZW);
+ EXPECT_EQ(0, ZW != ZW);
+ EXPECT_EQ(0, ZW.ult(ZW));
+
+ // Mutations.
+ ZW.setBitsWithWrap(0, 0);
+ ZW.setBits(0, 0);
+ ZW.clearAllBits();
+ ZW.flipAllBits();
+
+ // Leading, trailing, ctpop, etc
+ EXPECT_EQ(0U, ZW.countLeadingZeros());
+ EXPECT_EQ(0U, ZW.countLeadingOnes());
+ EXPECT_EQ(0U, ZW.countPopulation());
+ EXPECT_EQ(0U, ZW.reverseBits().getBitWidth());
+ EXPECT_EQ(0U, ZW.getHiBits(0).getBitWidth());
+ EXPECT_EQ(0U, ZW.getLoBits(0).getBitWidth());
+ EXPECT_EQ(0, ZW.zext(4));
+ EXPECT_EQ(0U, APInt(4, 3).trunc(0).getBitWidth());
+
+ SmallString<42> STR;
+ ZW.toStringUnsigned(STR);
+ EXPECT_EQ("0", STR);
+
+ // Move ctor (keep at the end of the method since moves are destructive).
+ APInt MZW1(std::move(ZW));
+ EXPECT_EQ(0U, MZW1.getBitWidth());
+ // Move Assignment
+ MZW1 = std::move(ZW2);
+ EXPECT_EQ(0U, MZW1.getBitWidth());
+}
+
} // end anonymous namespace