llvm.org GIT mirror llvm / a46dd58
[APFloat][ADT] Fix sign handling logic for FMA results that truncate to zero. This patch adds a check for underflow when truncating results back to lower precision at the end of an FMA. The additional sign handling logic in APFloat::fusedMultiplyAdd should only be performed when the result of the addition step of the FMA (in full precision) is exactly zero, not when the result underflows to zero. Unit tests for this case and related signed zero FMA results are included. Fixes <rdar://problem/18925551>. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225123 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 4 years ago
2 changed file(s) with 42 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
18221822 /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a
18231823 positive zero unless rounding to minus infinity, except that
18241824 adding two like-signed zeroes gives that zero. */
1825 if (category == fcZero && sign != addend.sign)
1825 if (category == fcZero && !(fs & opUnderflow) && sign != addend.sign)
18261826 sign = (rounding_mode == rmTowardNegative);
18271827 } else {
18281828 fs = multiplySpecials(multiplicand);
474474 EXPECT_EQ(12.0f, f1.convertToFloat());
475475 }
476476
477 // Test for correct zero sign when answer is exactly zero.
478 // fma(1.0, -1.0, 1.0) -> +ve 0.
479 {
480 APFloat f1(1.0);
481 APFloat f2(-1.0);
482 APFloat f3(1.0);
483 f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
484 EXPECT_TRUE(!f1.isNegative() && f1.isZero());
485 }
486
487 // Test for correct zero sign when answer is exactly zero and rounding towards
488 // negative.
489 // fma(1.0, -1.0, 1.0) -> +ve 0.
490 {
491 APFloat f1(1.0);
492 APFloat f2(-1.0);
493 APFloat f3(1.0);
494 f1.fusedMultiplyAdd(f2, f3, APFloat::rmTowardNegative);
495 EXPECT_TRUE(f1.isNegative() && f1.isZero());
496 }
497
498 // Test for correct (in this case -ve) sign when adding like signed zeros.
499 // Test fma(0.0, -0.0, -0.0) -> -ve 0.
500 {
501 APFloat f1(0.0);
502 APFloat f2(-0.0);
503 APFloat f3(-0.0);
504 f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
505 EXPECT_TRUE(f1.isNegative() && f1.isZero());
506 }
507
508 // Test -ve sign preservation when small negative results underflow.
509 {
510 APFloat f1(APFloat::IEEEdouble, "-0x1p-1074");
511 APFloat f2(APFloat::IEEEdouble, "+0x1p-1074");
512 APFloat f3(0.0);
513 f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
514 EXPECT_TRUE(f1.isNegative() && f1.isZero());
515 }
516
517 // Test x87 extended precision case from http://llvm.org/PR20728.
477518 {
478519 APFloat M1(APFloat::x87DoubleExtended, 1.0);
479520 APFloat M2(APFloat::x87DoubleExtended, 1.0);