diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -1218,7 +1218,7 @@ /// Truncate to new width. /// /// Truncate the APInt to a specified width. It is an error to specify a width - /// that is greater than or equal to the current width. + /// that is greater than the current width. APInt trunc(unsigned width) const; /// Truncate to new width with unsigned saturation. @@ -1238,7 +1238,7 @@ /// /// This operation sign extends the APInt to a new width. If the high order /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. - /// It is an error to specify a width that is less than or equal to the + /// It is an error to specify a width that is less than the /// current width. APInt sext(unsigned width) const; @@ -1246,7 +1246,7 @@ /// /// This operation zero extends the APInt to a new width. The high order bits /// are filled with 0 bits. It is an error to specify a width that is less - /// than or equal to the current width. + /// than the current width. APInt zext(unsigned width) const; /// Sign extend or truncate to width diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -896,11 +896,14 @@ // Truncate to new width. APInt APInt::trunc(unsigned width) const { - assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width <= BitWidth && "Invalid APInt Truncate request"); if (width <= APINT_BITS_PER_WORD) return APInt(width, getRawData()[0]); + if (width == BitWidth) + return *this; + APInt Result(getMemory(getNumWords(width)), width); // Copy full words. @@ -918,7 +921,7 @@ // Truncate to new width with unsigned saturation. APInt APInt::truncUSat(unsigned width) const { - assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width <= BitWidth && "Invalid APInt Truncate request"); // Can we just losslessly truncate it? if (isIntN(width)) @@ -929,7 +932,7 @@ // Truncate to new width with signed saturation. APInt APInt::truncSSat(unsigned width) const { - assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width <= BitWidth && "Invalid APInt Truncate request"); // Can we just losslessly truncate it? if (isSignedIntN(width)) @@ -941,11 +944,14 @@ // Sign extend to a new width. APInt APInt::sext(unsigned Width) const { - assert(Width > BitWidth && "Invalid APInt SignExtend request"); + assert(Width >= BitWidth && "Invalid APInt SignExtend request"); if (Width <= APINT_BITS_PER_WORD) return APInt(Width, SignExtend64(U.VAL, BitWidth)); + if (Width == BitWidth) + return *this; + APInt Result(getMemory(getNumWords(Width)), Width); // Copy words. @@ -965,11 +971,14 @@ // Zero extend to a new width. APInt APInt::zext(unsigned width) const { - assert(width > BitWidth && "Invalid APInt ZeroExtend request"); + assert(width >= BitWidth && "Invalid APInt ZeroExtend request"); if (width <= APINT_BITS_PER_WORD) return APInt(width, U.VAL); + if (width == BitWidth) + return *this; + APInt Result(getMemory(getNumWords(width)), width); // Copy words. diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -1181,18 +1181,22 @@ APInt AP_100 = APInt(8, 100); APInt AP_200 = APInt(8, 200); + EXPECT_EQ(APInt(8, 100), AP_100.truncUSat(8)); EXPECT_EQ(APInt(7, 100), AP_100.truncUSat(7)); EXPECT_EQ(APInt(6, 63), AP_100.truncUSat(6)); EXPECT_EQ(APInt(5, 31), AP_100.truncUSat(5)); + EXPECT_EQ(APInt(8, 200), AP_200.truncUSat(8)); EXPECT_EQ(APInt(7, 127), AP_200.truncUSat(7)); EXPECT_EQ(APInt(6, 63), AP_200.truncUSat(6)); EXPECT_EQ(APInt(5, 31), AP_200.truncUSat(5)); + EXPECT_EQ(APInt(8, 42), AP_42.truncSSat(8)); EXPECT_EQ(APInt(7, 42), AP_42.truncSSat(7)); EXPECT_EQ(APInt(6, 31), AP_42.truncSSat(6)); EXPECT_EQ(APInt(5, 15), AP_42.truncSSat(5)); + EXPECT_EQ(APInt(8, -56), AP_200.truncSSat(8)); EXPECT_EQ(APInt(7, -56), AP_200.truncSSat(7)); EXPECT_EQ(APInt(6, -32), AP_200.truncSSat(6)); EXPECT_EQ(APInt(5, -16), AP_200.truncSSat(5)); @@ -2637,23 +2641,28 @@ EXPECT_EQ(~uint64_t(0), APInt(1, 1).sext(64)); APInt i32_max(APInt::getSignedMaxValue(32).sext(63)); + EXPECT_EQ(i32_max, i32_max.sext(63)); EXPECT_EQ(32U, i32_max.countLeadingZeros()); EXPECT_EQ(0U, i32_max.countTrailingZeros()); EXPECT_EQ(31U, i32_max.countPopulation()); APInt i32_min(APInt::getSignedMinValue(32).sext(63)); + EXPECT_EQ(i32_min, i32_min.sext(63)); EXPECT_EQ(32U, i32_min.countLeadingOnes()); EXPECT_EQ(31U, i32_min.countTrailingZeros()); EXPECT_EQ(32U, i32_min.countPopulation()); APInt i32_neg1(APInt(32, ~uint64_t(0)).sext(63)); + EXPECT_EQ(i32_neg1, i32_neg1.sext(63)); EXPECT_EQ(63U, i32_neg1.countLeadingOnes()); EXPECT_EQ(0U, i32_neg1.countTrailingZeros()); EXPECT_EQ(63U, i32_neg1.countPopulation()); } -TEST(APIntTest, truncOrSelf) { +TEST(APIntTest, trunc) { APInt val(32, 0xFFFFFFFF); + EXPECT_EQ(0xFFFF, val.trunc(16)); + EXPECT_EQ(0xFFFFFFFF, val.trunc(32)); EXPECT_EQ(0xFFFF, val.truncOrSelf(16)); EXPECT_EQ(0xFFFFFFFF, val.truncOrSelf(32)); EXPECT_EQ(0xFFFFFFFF, val.truncOrSelf(64));