aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
authorDanila Malyutin <dmalyutin@azul.com>2022-06-06 20:12:43 +0300
committerDanila Malyutin <dmalyutin@azul.com>2022-06-08 21:54:35 +0300
commited6c309d4bf60b8a6abcf37a4e9d5b4bef96191b (patch)
tree9e9a5684595580eaf7564909461e0a201be45fa6 /llvm/lib/Support/APFloat.cpp
parentd897a14c2ef756d99344f4fae8864108e0131007 (diff)
downloadllvm-ed6c309d4bf60b8a6abcf37a4e9d5b4bef96191b.zip
llvm-ed6c309d4bf60b8a6abcf37a4e9d5b4bef96191b.tar.gz
llvm-ed6c309d4bf60b8a6abcf37a4e9d5b4bef96191b.tar.bz2
[APFloat] Fix truncation of certain subnormal numbers
Certain subnormals would be incorrectly rounded away from zero. Fixes #55838 Differential Revision: https://reviews.llvm.org/D127140
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r--llvm/lib/Support/APFloat.cpp9
1 files changed, 8 insertions, 1 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 4b75c9d..2ae28fe 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -2213,8 +2213,11 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics,
// when truncating from PowerPC double-double to double format), the
// right shift could lose result mantissa bits. Adjust exponent instead
// of performing excessive shift.
+ // Also do a similar trick in case shifting denormal would produce zero
+ // significand as this case isn't handled correctly by normalize.
if (shift < 0 && isFiniteNonZero()) {
- int exponentChange = significandMSB() + 1 - fromSemantics.precision;
+ int omsb = significandMSB() + 1;
+ int exponentChange = omsb - fromSemantics.precision;
if (exponent + exponentChange < toSemantics.minExponent)
exponentChange = toSemantics.minExponent - exponent;
if (exponentChange < shift)
@@ -2222,6 +2225,10 @@ IEEEFloat::opStatus IEEEFloat::convert(const fltSemantics &toSemantics,
if (exponentChange < 0) {
shift -= exponentChange;
exponent += exponentChange;
+ } else if (omsb <= -shift) {
+ exponentChange = omsb + shift - 1; // leave at least one bit set
+ shift -= exponentChange;
+ exponent += exponentChange;
}
}