summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Support/APFloat.cpp2
-rw-r--r--llvm/unittests/ADT/APFloatTest.cpp41
2 files changed, 42 insertions, 1 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 295b16c55e2..393ecf4784c 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -1823,7 +1823,7 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand,
/* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
positive zero unless rounding to minus infinity, except that
adding two like-signed zeroes gives that zero. */
- if (category == fcZero && sign != addend.sign)
+ if (category == fcZero && !(fs & opUnderflow) && sign != addend.sign)
sign = (rounding_mode == rmTowardNegative);
} else {
fs = multiplySpecials(multiplicand);
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index c7ec16ba803..8b82fb2f4ed 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -475,6 +475,47 @@ TEST(APFloatTest, FMA) {
EXPECT_EQ(12.0f, f1.convertToFloat());
}
+ // Test for correct zero sign when answer is exactly zero.
+ // fma(1.0, -1.0, 1.0) -> +ve 0.
+ {
+ APFloat f1(1.0);
+ APFloat f2(-1.0);
+ APFloat f3(1.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_TRUE(!f1.isNegative() && f1.isZero());
+ }
+
+ // Test for correct zero sign when answer is exactly zero and rounding towards
+ // negative.
+ // fma(1.0, -1.0, 1.0) -> +ve 0.
+ {
+ APFloat f1(1.0);
+ APFloat f2(-1.0);
+ APFloat f3(1.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmTowardNegative);
+ EXPECT_TRUE(f1.isNegative() && f1.isZero());
+ }
+
+ // Test for correct (in this case -ve) sign when adding like signed zeros.
+ // Test fma(0.0, -0.0, -0.0) -> -ve 0.
+ {
+ APFloat f1(0.0);
+ APFloat f2(-0.0);
+ APFloat f3(-0.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_TRUE(f1.isNegative() && f1.isZero());
+ }
+
+ // Test -ve sign preservation when small negative results underflow.
+ {
+ APFloat f1(APFloat::IEEEdouble, "-0x1p-1074");
+ APFloat f2(APFloat::IEEEdouble, "+0x1p-1074");
+ APFloat f3(0.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_TRUE(f1.isNegative() && f1.isZero());
+ }
+
+ // Test x87 extended precision case from http://llvm.org/PR20728.
{
APFloat M1(APFloat::x87DoubleExtended, 1.0);
APFloat M2(APFloat::x87DoubleExtended, 1.0);
OpenPOWER on IntegriCloud