summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-10-07 23:40:49 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-10-07 23:40:49 +0000
commit9eb6b4d91b83448ec818089754c74bbdcf7dfd7a (patch)
treebc23b23e593554a3b01ef19bded7a7f71ff22db6
parentd2fdb4a28560688be5cbc5b2b0c305ec7207cbd0 (diff)
downloadllvm-9eb6b4d91b83448ec818089754c74bbdcf7dfd7a.tar.gz
llvm-9eb6b4d91b83448ec818089754c74bbdcf7dfd7a.tar.bz2
llvm-9eb6b4d91b83448ec818089754c74bbdcf7dfd7a.tar.xz
Fix APInt::operator*= so that it computes the correct result for large integers where there is unsigned overflow. Fix APFloat::toString so that it doesn't depend on the incorrect behavior in common cases (and computes the correct result in some rare cases). Fixes PR11086.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141441 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Support/APFloat.cpp2
-rw-r--r--lib/Support/APInt.cpp3
-rw-r--r--unittests/ADT/APIntTest.cpp9
3 files changed, 12 insertions, 2 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index b32dfeb956..5307829ed8 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -3455,7 +3455,7 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
// <= semantics->precision + e * 137 / 59
// (log_2(5) ~ 2.321928 < 2.322034 ~ 137/59)
- unsigned precision = semantics->precision + 137 * texp / 59;
+ unsigned precision = semantics->precision + (137 * texp + 136) / 59;
// Multiply significand by 5^e.
// N * 5^0101 == N * 5^(1*1) * 5^(0*2) * 5^(1*4) * 5^(0*8)
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index 6eadaafd5f..3774c5223c 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -386,6 +386,7 @@ APInt& APInt::operator*=(const APInt& RHS) {
clearAllBits();
unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords;
memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE);
+ clearUnusedBits();
// delete dest array and return
delete[] dest;
@@ -471,7 +472,7 @@ APInt APInt::operator*(const APInt& RHS) const {
return APInt(BitWidth, VAL * RHS.VAL);
APInt Result(*this);
Result *= RHS;
- return Result.clearUnusedBits();
+ return Result;
}
APInt APInt::operator+(const APInt& RHS) const {
diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp
index 11bb5e1545..490811deb8 100644
--- a/unittests/ADT/APIntTest.cpp
+++ b/unittests/ADT/APIntTest.cpp
@@ -441,4 +441,13 @@ TEST(APIntTest, StringDeath) {
#endif
#endif
+TEST(APIntTest, mul_clear) {
+ APInt ValA(65, -1ULL);
+ APInt ValB(65, 4);
+ APInt ValC(65, 0);
+ ValC = ValA * ValB;
+ ValA *= ValB;
+ EXPECT_EQ(ValA.toString(10, false), ValC.toString(10, false));
+}
+
}