From 3bb52cad65ae408d80b24051fc30fdbb0c5fcb10 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Thu, 19 Jul 2018 18:07:56 +0000 Subject: [PATCH] [APInt] Keep the original bit width in quotient and remainder Some trivial cases in udivrem were handled by directly assigning 0 or 1 to APInt objects. This would set the bit width to 1, instead of the bit width of the inputs. A potentially undesirable side effect of that is that with the bit width of 1, 1 equals -1. Differential Revision: https://reviews.llvm.org/D49554 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337478 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/APInt.cpp | 33 +++++++++++++++++---------------- unittests/ADT/APIntTest.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 60372736d78..1fae0e9b8d6 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -1735,25 +1735,25 @@ void APInt::udivrem(const APInt &LHS, const APInt &RHS, // Check the degenerate cases if (lhsWords == 0) { - Quotient = 0; // 0 / Y ===> 0 - Remainder = 0; // 0 % Y ===> 0 + Quotient = APInt(BitWidth, 0); // 0 / Y ===> 0 + Remainder = APInt(BitWidth, 0); // 0 % Y ===> 0 return; } if (rhsBits == 1) { - Quotient = LHS; // X / 1 ===> X - Remainder = 0; // X % 1 ===> 0 + Quotient = LHS; // X / 1 ===> X + Remainder = APInt(BitWidth, 0); // X % 1 ===> 0 } if (lhsWords < rhsWords || LHS.ult(RHS)) { - Remainder = LHS; // X % Y ===> X, iff X < Y - Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS; // X % Y ===> X, iff X < Y + Quotient = APInt(BitWidth, 0); // X / Y ===> 0, iff X < Y return; } if (LHS == RHS) { - Quotient = 1; // X / X ===> 1 - Remainder = 0; // X % X ===> 0; + Quotient = APInt(BitWidth, 1); // X / X ===> 1 + Remainder = APInt(BitWidth, 0); // X % X ===> 0; return; } @@ -1801,25 +1801,26 @@ void APInt::udivrem(const APInt &LHS, uint64_t RHS, APInt &Quotient, // Check the degenerate cases if (lhsWords == 0) { - Quotient = 0; // 0 / Y ===> 0 - Remainder = 0; // 0 % Y ===> 0 + Quotient = APInt(BitWidth, 0); // 0 / Y ===> 0 + Remainder = 0; // 0 % Y ===> 0 return; } if (RHS == 1) { - Quotient = LHS; // X / 1 ===> X - Remainder = 0; // X % 1 ===> 0 + Quotient = LHS; // X / 1 ===> X + Remainder = 0; // X % 1 ===> 0 + return; } if (LHS.ult(RHS)) { - Remainder = LHS.getZExtValue(); // X % Y ===> X, iff X < Y - Quotient = 0; // X / Y ===> 0, iff X < Y + Remainder = LHS.getZExtValue(); // X % Y ===> X, iff X < Y + Quotient = APInt(BitWidth, 0); // X / Y ===> 0, iff X < Y return; } if (LHS == RHS) { - Quotient = 1; // X / X ===> 1 - Remainder = 0; // X % X ===> 0; + Quotient = APInt(BitWidth, 1); // X / X ===> 1 + Remainder = 0; // X % X ===> 0; return; } diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 4eb6d676b8c..48f91195e44 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -1060,6 +1060,38 @@ TEST(APIntTest, divremuint) { APInt{1024, 1}); } +TEST(APIntTest, divrem_simple) { + // Test simple cases. + APInt A(65, 2), B(65, 2); + APInt Q, R; + + // X / X + APInt::sdivrem(A, B, Q, R); + EXPECT_EQ(Q, APInt(65, 1)); + EXPECT_EQ(R, APInt(65, 0)); + APInt::udivrem(A, B, Q, R); + EXPECT_EQ(Q, APInt(65, 1)); + EXPECT_EQ(R, APInt(65, 0)); + + // 0 / X + APInt O(65, 0); + APInt::sdivrem(O, B, Q, R); + EXPECT_EQ(Q, APInt(65, 0)); + EXPECT_EQ(R, APInt(65, 0)); + APInt::udivrem(O, B, Q, R); + EXPECT_EQ(Q, APInt(65, 0)); + EXPECT_EQ(R, APInt(65, 0)); + + // X / 1 + APInt I(65, 1); + APInt::sdivrem(A, I, Q, R); + EXPECT_EQ(Q, A); + EXPECT_EQ(R, APInt(65, 0)); + APInt::udivrem(A, I, Q, R); + EXPECT_EQ(Q, A); + EXPECT_EQ(R, APInt(65, 0)); +} + TEST(APIntTest, fromString) { EXPECT_EQ(APInt(32, 0), APInt(32, "0", 2)); EXPECT_EQ(APInt(32, 1), APInt(32, "1", 2)); -- 2.50.1