Skip to content

Commit a57f4c7

Browse files
authored
[compiler-rt] Fix a bug in fp_div_impl when an intermediate result is out of expected range. (#119449)
Before this fix, `1.0L / (1.0L - 0x1.0p-113L)` will return `2 * (1 + eps(1))`.
1 parent e8a6563 commit a57f4c7

File tree

4 files changed

+19
-1
lines changed

4 files changed

+19
-1
lines changed

compiler-rt/lib/builtins/fp_div_impl.inc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,6 @@ static __inline fp_t __divXf3__(fp_t a, fp_t b) {
334334
// Suppose 1/b - P * 2^-W < x < 1/b + P * 2^-W
335335
x_UQ0 -= RECIPROCAL_PRECISION;
336336
// Now 1/b - (2*P) * 2^-W < x < 1/b
337-
// FIXME Is x_UQ0 still >= 0.5?
338337

339338
rep_t quotient_UQ1, dummy;
340339
wideMultiply(x_UQ0, aSignificand << 1, &quotient_UQ1, &dummy);
@@ -344,6 +343,12 @@ static __inline fp_t __divXf3__(fp_t a, fp_t b) {
344343
// adjust it to be in [1.0, 2.0) as UQ1.SB.
345344
rep_t residualLo;
346345
if (quotient_UQ1 < (implicitBit << 1)) {
346+
if (quotient_UQ1 < implicitBit) {
347+
// In a rare case where quotient is < 0.5, we can adjust the quotient and
348+
// the written exponent, and then treat them the same way as in [0.5, 1.0)
349+
quotient_UQ1 <<= 1;
350+
writtenExponent -= 1;
351+
}
347352
// Highest bit is 0, so just reinterpret quotient_UQ1 as UQ1.SB,
348353
// effectively doubling its value as well as its error estimation.
349354
residualLo = (aSignificand << (significandBits + 1)) - quotient_UQ1 * bSignificand;

compiler-rt/test/builtins/Unit/divdf3_test.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,5 +113,9 @@ int main()
113113
if (test__divdf3(0x1.0p-1022, 0x1.0028p+52, UINT64_C(0x1)))
114114
return 1;
115115

116+
// test 1 / (1 - eps(0.5)) = 1 + eps(1)
117+
if (test__divdf3(1.0, 0x1.fffffffffffffp-1, UINT64_C(0x3ff0000000000001)))
118+
return 1;
119+
116120
return 0;
117121
}

compiler-rt/test/builtins/Unit/divsf3_test.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,9 @@ int main()
107107
if (test__divsf3(0x1.fffffep-126F, 2.F, UINT32_C(0x00800000)))
108108
return 1;
109109

110+
// test 1 / (1 - eps(0.5)) = 1 + eps(1)
111+
if (test__divsf3(1.0F, 0x1.fffffep-1F, UINT32_C(0x3f800001)))
112+
return 1;
113+
110114
return 0;
111115
}

compiler-rt/test/builtins/Unit/divtf3_test.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ int main() {
156156
UINT64_C(0x0001000000000000), UINT64_C(0)))
157157
return 1;
158158

159+
// test 1 / (1 - eps(0.5)) = 1 + eps(1).
160+
if (test__divtf3(1.0L, TF_C(0x1.ffffffffffffffffffffffffffffp-1),
161+
UINT64_C(0x3FFF000000000000), UINT64_C(1)))
162+
return 1;
163+
159164
#else
160165
printf("skipped\n");
161166

0 commit comments

Comments
 (0)