diff options
author | Danila Malyutin <dmalyutin@azul.com> | 2022-06-06 20:12:43 +0300 |
---|---|---|
committer | Danila Malyutin <dmalyutin@azul.com> | 2022-06-08 21:54:35 +0300 |
commit | ed6c309d4bf60b8a6abcf37a4e9d5b4bef96191b (patch) | |
tree | 9e9a5684595580eaf7564909461e0a201be45fa6 /llvm/lib/Support/APFloat.cpp | |
parent | d897a14c2ef756d99344f4fae8864108e0131007 (diff) | |
download | llvm-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.cpp | 9 |
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; } } |