authorgravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-04-25 16:42:13-07:00
committergravatar for topolarity@tapscott.meCody Tapscott <topolarity@tapscott.me> 2022-04-25 17:21:09-07:00
log96d86e346517b1917165b6f817b2147524a9a0b5
tree8567ee8f6fb90d402d19762dffbb9503d5064237
parentf5540778b56636cffd89f794c6b1a9266d7d36f8

compiler_rt: Fix rounding edge case for __mulxf3


5 files changed, 37 insertions(+), 25 deletions(-)

lib/std/special/compiler_rt/README.md+17-17
...@@ -152,53 +152,53 @@ Bugs should be solved by trying to duplicate the bug upstream, if possible....@@ -152,53 +152,53 @@ Bugs should be solved by trying to duplicate the bug upstream, if possible.
152- todo todo __fixsfsi // convert a to i32, rounding towards zero152- todo todo __fixsfsi // convert a to i32, rounding towards zero
153- todo todo __fixdfsi //153- todo todo __fixdfsi //
154- todo todo __fixtfsi //154- todo todo __fixtfsi //
155- none none __fixxfsi // missing155- todo todo __fixxfsi //
156- todo todo __fixsfdi // convert a to i64, rounding towards zero156- todo todo __fixsfdi // convert a to i64, rounding towards zero
157- todo todo __fixdfdi //157- todo todo __fixdfdi //
158- todo todo __fixtfdi //158- todo todo __fixtfdi //
159- none none __fixxfdi // missing159- todo todo __fixxfdi //
160- todo todo __fixsfti // convert a to i128, rounding towards zero160- todo todo __fixsfti // convert a to i128, rounding towards zero
161- todo todo __fixdfti //161- todo todo __fixdfti //
162- todo todo __fixtfdi //162- todo todo __fixtfdi //
163- none none __fixxfti // missing163- todo todo __fixxfti //
164164
165- __fixunssfsi // convert to u32, rounding towards zero. negative values become 0.165- __fixunssfsi // convert to u32, rounding towards zero. negative values become 0.
166- __fixunsdfsi //166- __fixunsdfsi //
167- __fixunstfsi //167- __fixunstfsi //
168- __fixunsxfsi // missing168- __fixunsxfsi //
169- __fixunssfdi // convert to u64, rounding towards zero. negative values become 0.169- __fixunssfdi // convert to u64, rounding towards zero. negative values become 0.
170- __fixunsdfdi //170- __fixunsdfdi //
171- __fixunstfdi //171- __fixunstfdi //
172- __fixunsxfdi // missing172- __fixunsxfdi //
173- __fixunssfti // convert to u128, rounding towards zero. negative values become 0.173- __fixunssfti // convert to u128, rounding towards zero. negative values become 0.
174- __fixunsdfti //174- __fixunsdfti //
175- __fixunstfdi //175- __fixunstfdi //
176- __fixunsxfti // missing176- __fixunsxfti //
177177
178- __floatsisf // convert i32 to floating point178- __floatsisf // convert i32 to floating point
179- __floatsidf //179- __floatsidf //
180- __floatsitf //180- __floatsitf //
181- __floatsixf // missing181- __floatsixf //
182- __floatdisf // convert i64 to floating point182- __floatdisf // convert i64 to floating point
183- __floatdidf //183- __floatdidf //
184- __floatditf //184- __floatditf //
185- __floatdixf // missing185- __floatdixf //
186- __floattisf // convert i128 to floating point186- __floattisf // convert i128 to floating point
187- __floattidf //187- __floattidf //
188- __floattixf // missing188- __floattixf //
189189
190- __floatunsisf // convert i32 to floating point190- __floatunsisf // convert u32 to floating point
191- __floatunsidf //191- __floatunsidf //
192- __floatunsitf //192- __floatunsitf //
193- __floatunsixf // missing193- __floatunsixf //
194- __floatundisf // convert i64 to floating point194- __floatundisf // convert u64 to floating point
195- __floatundidf //195- __floatundidf //
196- __floatunditf //196- __floatunditf //
197- __floatundixf // missing197- __floatundixf //
198- __floatuntisf // convert i128 to floating point198- __floatuntisf // convert u128 to floating point
199- __floatuntidf //199- __floatuntidf //
200- __floatuntitf //200- __floatuntitf //
201- __floatuntixf // missing201- __floatuntixf //
202202
203#### Float Comparison203#### Float Comparison
204- __cmpsf2 // return (a<b)=>-1,(a==b)=>0,(a>b)=>1,Nan=>1 dont rely on this204- __cmpsf2 // return (a<b)=>-1,(a==b)=>0,(a>b)=>1,Nan=>1 dont rely on this
...@@ -242,11 +242,11 @@ Bugs should be solved by trying to duplicate the bug upstream, if possible....@@ -242,11 +242,11 @@ Bugs should be solved by trying to duplicate the bug upstream, if possible.
242- __mulsf3 // a * b242- __mulsf3 // a * b
243- __muldf3 // a * b243- __muldf3 // a * b
244- __multf3 // a * b244- __multf3 // a * b
245- __mulxf3 // a * b missing245- __mulxf3 // a * b
246- __divsf3 // a / b246- __divsf3 // a / b
247- __divdf3 // a / b247- __divdf3 // a / b
248- __divtf3 // a / b248- __divtf3 // a / b
249- __divxf3 // a / b missing249- __divxf3 // a / b
250- __negsf2 // -a symbol-level compatibility: libgcc uses this for the rl78250- __negsf2 // -a symbol-level compatibility: libgcc uses this for the rl78
251- __negdf2 // -a unnecessary: can be lowered directly to a xor251- __negdf2 // -a unnecessary: can be lowered directly to a xor
252- __negtf2 // -a252- __negtf2 // -a
lib/std/special/compiler_rt/addXf3.zig+5-7
...@@ -74,7 +74,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T...@@ -74,7 +74,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T
7474
75 const shift = @clz(std.meta.Int(.unsigned, bits), significand.*) - @clz(Z, integerBit);75 const shift = @clz(std.meta.Int(.unsigned, bits), significand.*) - @clz(Z, integerBit);
76 significand.* <<= @intCast(S, shift);76 significand.* <<= @intCast(S, shift);
77 return 1 - shift;77 return @as(i32, 1) - shift;
78}78}
7979
80// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/215480// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
...@@ -210,12 +210,10 @@ fn addXf3(comptime T: type, a: T, b: T) T {...@@ -210,12 +210,10 @@ fn addXf3(comptime T: type, a: T, b: T) T {
210 if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign);210 if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign);
211211
212 if (aExponent <= 0) {212 if (aExponent <= 0) {
213 // Result is denormal before rounding; the exponent is zero and we213 // Result is denormal; the exponent and round/sticky bits are zero.
214 // need to shift the significand.214 // All we need to do is shift the significand and apply the correct sign.
215 const shift = @intCast(Z, 1 - aExponent);215 aSignificand >>= @intCast(S, 4 - aExponent);
216 const sticky = if (aSignificand << @intCast(S, typeWidth - shift) != 0) @as(Z, 1) else 0;216 return @bitCast(T, resultSign | aSignificand);
217 aSignificand = aSignificand >> @intCast(S, shift | sticky);
218 aExponent = 0;
219 }217 }
220218
221 // Low three bits are round, guard, and sticky.219 // Low three bits are round, guard, and sticky.
lib/std/special/compiler_rt/addXf3_test.zig+2
...@@ -152,4 +152,6 @@ test "addxf3" {...@@ -152,4 +152,6 @@ test "addxf3" {
152 try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.8p-63, 0x3FFF_8800000000000000); // round down to even152 try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.8p-63, 0x3FFF_8800000000000000); // round down to even
153 try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.9p-63, 0x3FFF_8800000000000001); // round up153 try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.9p-63, 0x3FFF_8800000000000001); // round up
154 try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x2.0p-63, 0x3FFF_8800000000000001); // exact154 try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x2.0p-63, 0x3FFF_8800000000000001); // exact
155 try test__addxf3(0x0.ffff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_7FFFFFFFFFFFFFFF); // exact
156 try test__addxf3(0x0.1fff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_0FFFFFFFFFFFFFFF); // exact
155}157}
lib/std/special/compiler_rt/mulXf3.zig+9-1
...@@ -152,6 +152,10 @@ fn mulXf3(comptime T: type, a: T, b: T) T {...@@ -152,6 +152,10 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
152 const sticky = wideShrWithTruncation(ZSignificand, &productHi, &productLo, shift);152 const sticky = wideShrWithTruncation(ZSignificand, &productHi, &productLo, shift);
153 productLo |= @boolToInt(sticky);153 productLo |= @boolToInt(sticky);
154 result = productHi;154 result = productHi;
155
156 // We include the integer bit so that rounding will carry to the exponent,
157 // but it will be removed later if the result is still denormal
158 if (significandBits != fractionalBits) result |= integerBit;
155 } else {159 } else {
156 // Result is normal before rounding; insert the exponent.160 // Result is normal before rounding; insert the exponent.
157 result = productHi & significandMask;161 result = productHi & significandMask;
...@@ -166,7 +170,11 @@ fn mulXf3(comptime T: type, a: T, b: T) T {...@@ -166,7 +170,11 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
166170
167 // Restore any explicit integer bit, if it was rounded off171 // Restore any explicit integer bit, if it was rounded off
168 if (significandBits != fractionalBits) {172 if (significandBits != fractionalBits) {
169 if ((result >> significandBits) != 0) result |= integerBit;173 if ((result >> significandBits) != 0) {
174 result |= integerBit;
175 } else {
176 result &= ~integerBit;
177 }
170 }178 }
171179
172 // Insert the sign of the result:180 // Insert the sign of the result:
lib/std/special/compiler_rt/mulXf3_test.zig+4
...@@ -105,6 +105,7 @@ test "multf3" {...@@ -105,6 +105,7 @@ test "multf3" {
105105
106 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002);106 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002);
107 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003);107 try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003);
108 try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002);
108}109}
109110
110const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));111const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
...@@ -164,4 +165,7 @@ test "mulxf3" {...@@ -164,4 +165,7 @@ test "mulxf3" {
164165
165 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even166 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even
166 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up167 try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up
168 try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal
169 try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal
170 try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal
167}171}