Skip to content

Commit

Permalink
[APFloat] Fix IEEEFloat::addOrSubtractSignificand and `IEEEFloat::n…
Browse files Browse the repository at this point in the history
…ormalize`
  • Loading branch information
beetrees committed Jul 13, 2024
1 parent 7d1b6b2 commit ecd06e2
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 15 deletions.
51 changes: 36 additions & 15 deletions llvm/lib/Support/APFloat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1607,7 +1607,8 @@ IEEEFloat::opStatus IEEEFloat::normalize(roundingMode rounding_mode,
/* Before rounding normalize the exponent of fcNormal numbers. */
omsb = significandMSB() + 1;

if (omsb) {
// Only skip this `if` if the value is exactly zero.
if (omsb || lost_fraction != lfExactlyZero) {
/* OMSB is numbered from 1. We want to place it in the integer
bit numbered PRECISION if possible, with a compensating change in
the exponent. */
Expand Down Expand Up @@ -1782,7 +1783,7 @@ IEEEFloat::opStatus IEEEFloat::addOrSubtractSpecials(const IEEEFloat &rhs,
/* Add or subtract two normal numbers. */
lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
bool subtract) {
integerPart carry;
integerPart carry = 0;
lostFraction lost_fraction;
int bits;

Expand All @@ -1796,35 +1797,55 @@ lostFraction IEEEFloat::addOrSubtractSignificand(const IEEEFloat &rhs,
/* Subtraction is more subtle than one might naively expect. */
if (subtract) {
IEEEFloat temp_rhs(rhs);
bool lost_fraction_is_from_rhs = false;

if (bits == 0)
lost_fraction = lfExactlyZero;
else if (bits > 0) {
lost_fraction = temp_rhs.shiftSignificandRight(bits - 1);
lost_fraction_is_from_rhs = true;
shiftSignificandLeft(1);
} else {
lost_fraction = shiftSignificandRight(-bits - 1);
temp_rhs.shiftSignificandLeft(1);
}

// Should we reverse the subtraction.
if (compareAbsoluteValue(temp_rhs) == cmpLessThan) {
carry = temp_rhs.subtractSignificand
(*this, lost_fraction != lfExactlyZero);
cmpResult cmp_result = compareAbsoluteValue(temp_rhs);
if (cmp_result == cmpLessThan) {
bool borrow = false;
if (lost_fraction != lfExactlyZero && !lost_fraction_is_from_rhs) {
// The lost fraction is being subtracted, borrow from the significand
// and invert `lost_fraction`.
borrow = true;
if (lost_fraction == lfLessThanHalf)
lost_fraction = lfMoreThanHalf;
else if (lost_fraction == lfMoreThanHalf)
lost_fraction = lfLessThanHalf;
}
carry = temp_rhs.subtractSignificand(*this, borrow);
copySignificand(temp_rhs);
sign = !sign;
} else {
carry = subtractSignificand
(temp_rhs, lost_fraction != lfExactlyZero);
} else if (cmp_result == cmpGreaterThan) {
bool borrow = false;
if (lost_fraction != lfExactlyZero && lost_fraction_is_from_rhs) {
// The lost fraction is being subtracted, borrow from the significand
// and invert `lost_fraction`.
borrow = true;
if (lost_fraction == lfLessThanHalf)
lost_fraction = lfMoreThanHalf;
else if (lost_fraction == lfMoreThanHalf)
lost_fraction = lfLessThanHalf;
}
carry = subtractSignificand(temp_rhs, borrow);
} else { // cmpEqual
zeroSignificand();
if (lost_fraction != lfExactlyZero && lost_fraction_is_from_rhs) {
// rhs is slightly larger due to the lost fraction, flip the sign.
sign = !sign;
}
}

/* Invert the lost fraction - it was on the RHS and
subtracted. */
if (lost_fraction == lfLessThanHalf)
lost_fraction = lfMoreThanHalf;
else if (lost_fraction == lfMoreThanHalf)
lost_fraction = lfLessThanHalf;

/* The code above is intended to ensure that no borrow is
necessary. */
assert(!carry);
Expand Down
10 changes: 10 additions & 0 deletions llvm/unittests/ADT/APFloatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,16 @@ TEST(APFloatTest, FMA) {
EXPECT_EQ(-8.85242279E-41f, f1.convertToFloat());
}

// Regression test for failing the `assert(!carry)` in
// `addOrSubtractSignificand`.
{
APFloat f1(-1.4728589E-38f);
APFloat f2(3.7105144E-6f);
APFloat f3(5.5E-44f);
f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
EXPECT_EQ(-0.0f, f1.convertToFloat());
}

// Test using only a single instance of APFloat.
{
APFloat F(1.5);
Expand Down

0 comments on commit ecd06e2

Please sign in to comment.