[PATCH] D29346: Fix APFloat mod
Simon Byrne via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 31 13:19:25 PST 2017
simonbyrne created this revision.
The existing code for APFloat mod was incorrect in two ways:
- intermediate rounding gave incorrect results in some cases (e.g. frem double 0.3 0.01)
- the method of integer truncation could cause intermediate overflow
This caused subsequent errors in the constant propagation pass, see https://llvm.org/bugs/show_bug.cgi?id=3316
Repository:
rL LLVM
https://reviews.llvm.org/D29346
Files:
lib/Support/APFloat.cpp
Index: lib/Support/APFloat.cpp
===================================================================
--- lib/Support/APFloat.cpp
+++ lib/Support/APFloat.cpp
@@ -1739,43 +1739,30 @@
return fs;
}
-/* Normalized llvm frem (C fmod).
- This is not currently correct in all cases. */
+/* Normalized llvm frem (C fmod). */
IEEEFloat::opStatus IEEEFloat::mod(const IEEEFloat &rhs) {
opStatus fs;
fs = modSpecials(rhs);
if (isFiniteNonZero() && rhs.isFiniteNonZero()) {
- IEEEFloat V = *this;
- unsigned int origSign = sign;
-
- fs = V.divide(rhs, rmNearestTiesToEven);
- if (fs == opDivByZero)
- return fs;
-
- int parts = partCount();
- integerPart *x = new integerPart[parts];
- bool ignored;
- fs = V.convertToInteger(x, parts * integerPartWidth, true,
- rmTowardZero, &ignored);
- if (fs==opInvalidOp) {
- delete[] x;
- return fs;
- }
-
- fs = V.convertFromZeroExtendedInteger(x, parts * integerPartWidth, true,
- rmNearestTiesToEven);
- assert(fs==opOK); // should always work
-
- fs = V.multiply(rhs, rmNearestTiesToEven);
- assert(fs==opOK || fs==opInexact); // should not overflow or underflow
+ while (true) {
+ IEEEFloat V = *this;
- fs = subtract(V, rmNearestTiesToEven);
- assert(fs==opOK || fs==opInexact); // likewise
+ fs = V.divide(rhs, rmTowardZero);
+ if (fs == opDivByZero)
+ return fs;
+ V.roundToIntegral(rmTowardZero);
+ if (V.isZero())
+ break;
- if (isZero())
- sign = origSign; // IEEE754 requires this
- delete[] x;
+ /* *this = *this - V*rhs */
+ V.sign = !V.sign;
+ lostFraction lost_fraction;
+ lost_fraction = V.multiplySignificand(rhs, this);
+ fs = normalize(rmTowardZero, lost_fraction);
+ assert(fs==opOK); // should always be exact
+ *this = V;
+ }
}
return fs;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D29346.86483.patch
Type: text/x-patch
Size: 1959 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170131/3d7e7fbb/attachment.bin>
More information about the llvm-commits
mailing list