[PATCH] D127140: [APFloat] Fix truncation of certain subnormal numbers
Danila Malyutin via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 6 11:33:22 PDT 2022
danilaml created this revision.
Herald added a subscriber: hiraditya.
Herald added a project: All.
danilaml requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
Certain subnormals would be incorrectly rounded away from zero.
Fixes #55838
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D127140
Files:
llvm/lib/Support/APFloat.cpp
llvm/test/Transforms/InstSimplify/ConstProp/cast.ll
llvm/unittests/ADT/APFloatTest.cpp
Index: llvm/unittests/ADT/APFloatTest.cpp
===================================================================
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -1859,6 +1859,32 @@
EXPECT_EQ(0x7fc00000, test.bitcastToAPInt());
EXPECT_TRUE(losesInfo);
EXPECT_EQ(status, APFloat::opOK);
+
+ // Test that subnormals are handled correctly in double to float conversion
+ test = APFloat(APFloat::IEEEdouble(), "0x0.0000010000000p-1022");
+ test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(0.0f, test.convertToFloat());
+ EXPECT_TRUE(losesInfo);
+
+ test = APFloat(APFloat::IEEEdouble(), "0x0.0000010000001p-1022");
+ test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(0.0f, test.convertToFloat());
+ EXPECT_TRUE(losesInfo);
+
+ test = APFloat(APFloat::IEEEdouble(), "-0x0.0000010000001p-1022");
+ test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(0.0f, test.convertToFloat());
+ EXPECT_TRUE(losesInfo);
+
+ test = APFloat(APFloat::IEEEdouble(), "0x0.0000020000000p-1022");
+ test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(0.0f, test.convertToFloat());
+ EXPECT_TRUE(losesInfo);
+
+ test = APFloat(APFloat::IEEEdouble(), "0x0.0000020000001p-1022");
+ test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(0.0f, test.convertToFloat());
+ EXPECT_TRUE(losesInfo);
}
TEST(APFloatTest, PPCDoubleDouble) {
Index: llvm/test/Transforms/InstSimplify/ConstProp/cast.ll
===================================================================
--- llvm/test/Transforms/InstSimplify/ConstProp/cast.ll
+++ llvm/test/Transforms/InstSimplify/ConstProp/cast.ll
@@ -79,21 +79,17 @@
ret float %b
}
-; FIXME: This should be 0.0.
-
define float @trunc_denorm_lost_fraction1() {
; CHECK-LABEL: @trunc_denorm_lost_fraction1(
-; CHECK-NEXT: ret float 0x36A0000000000000
+; CHECK-NEXT: ret float 0.000000e+00
;
%b = fptrunc double 0x0000000010000001 to float
ret float %b
}
-; FIXME: This should be 0.0.
-
define float @trunc_denorm_lost_fraction2() {
; CHECK-LABEL: @trunc_denorm_lost_fraction2(
-; CHECK-NEXT: ret float 0x36A0000000000000
+; CHECK-NEXT: ret float 0.000000e+00
;
%b = fptrunc double 0x000000001fffffff to float
ret float %b
@@ -107,11 +103,9 @@
ret float %b
}
-; FIXME: This should be -0.0.
-
define float @trunc_denorm_lost_fraction4() {
; CHECK-LABEL: @trunc_denorm_lost_fraction4(
-; CHECK-NEXT: ret float 0xB6A0000000000000
+; CHECK-NEXT: ret float -0.000000e+00
;
%b = fptrunc double 0x8000000010000001 to float
ret float %b
Index: llvm/lib/Support/APFloat.cpp
===================================================================
--- llvm/lib/Support/APFloat.cpp
+++ llvm/lib/Support/APFloat.cpp
@@ -2226,9 +2226,16 @@
}
// If this is a truncation, perform the shift before we narrow the storage.
- if (shift < 0 && (isFiniteNonZero() || category==fcNaN))
+ if (shift < 0 && (isFiniteNonZero() || category==fcNaN)) {
lostFraction = shiftRight(significandParts(), oldPartCount, -shift);
+ // If we are truncating a denormal, the lostFraction is not relevant when
+ // normalizing, but it can't be lfExactlyZero or lfMoreThanHalf, otherwise
+ // it would return incorrect result if the significand is zero after shift
+ if (isDenormal())
+ lostFraction = lfLessThanHalf;
+ }
+
// Fix the storage so it can hold to new value.
if (newPartCount > oldPartCount) {
// The new type requires more storage; make it available.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D127140.434550.patch
Type: text/x-patch
Size: 3676 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220606/2b1bcbb9/attachment.bin>
More information about the llvm-commits
mailing list