compiler-rt: Fix signedness mismatch in f128 mul impl
The `1 - shift` expression was computed using small unsigned types and then casted to i32, producing either an underflow error or an incorrect result. Reported by `@notviri` in #8733
This commit is contained in:
@@ -98,8 +98,8 @@ fn mulXf3(comptime T: type, a: T, b: T) T {
|
||||
// one or both of a or b is denormal, the other (if applicable) is a
|
||||
// normal number. Renormalize one or both of a and b, and set scale to
|
||||
// include the necessary exponent adjustment.
|
||||
if (aAbs < implicitBit) scale +%= normalize(T, &aSignificand);
|
||||
if (bAbs < implicitBit) scale +%= normalize(T, &bSignificand);
|
||||
if (aAbs < implicitBit) scale += normalize(T, &aSignificand);
|
||||
if (bAbs < implicitBit) scale += normalize(T, &bSignificand);
|
||||
}
|
||||
|
||||
// Or in the implicit significand bit. (If we fell through from the
|
||||
@@ -277,7 +277,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T
|
||||
|
||||
const shift = @clz(Z, significand.*) - @clz(Z, implicitBit);
|
||||
significand.* <<= @intCast(std.math.Log2Int(Z), shift);
|
||||
return 1 - shift;
|
||||
return @as(i32, 1) - shift;
|
||||
}
|
||||
|
||||
fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {
|
||||
@@ -285,15 +285,15 @@ fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {
|
||||
const typeWidth = @typeInfo(Z).Int.bits;
|
||||
const S = std.math.Log2Int(Z);
|
||||
if (count < typeWidth) {
|
||||
const sticky = @truncate(u8, lo.* << @intCast(S, typeWidth -% count));
|
||||
const sticky = @boolToInt((lo.* << @intCast(S, typeWidth -% count)) != 0);
|
||||
lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)) | sticky;
|
||||
hi.* = hi.* >> @intCast(S, count);
|
||||
} else if (count < 2 * typeWidth) {
|
||||
const sticky = @truncate(u8, hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*);
|
||||
const sticky = @boolToInt((hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0);
|
||||
lo.* = hi.* >> @intCast(S, count -% typeWidth) | sticky;
|
||||
hi.* = 0;
|
||||
} else {
|
||||
const sticky = @truncate(u8, hi.* | lo.*);
|
||||
const sticky = @boolToInt((hi.* | lo.*) != 0);
|
||||
lo.* = sticky;
|
||||
hi.* = 0;
|
||||
}
|
||||
|
||||
@@ -88,4 +88,18 @@ test "multf3" {
|
||||
);
|
||||
|
||||
try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0);
|
||||
|
||||
// Denormal operands.
|
||||
try test__multf3(
|
||||
0x0.0000000000000000000000000001p-16382,
|
||||
0x1.p16383,
|
||||
0x3f90000000000000,
|
||||
0x0,
|
||||
);
|
||||
try test__multf3(
|
||||
0x1.p16383,
|
||||
0x0.0000000000000000000000000001p-16382,
|
||||
0x3f90000000000000,
|
||||
0x0,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user