Open andrewrk opened 2 years ago
Sorry if this is noise but I think this issue comes from +=
for type f80
.
When doing f1 -= 0
nothing changes but doing f1 += 0
breaks f1
when f1
is of type f80
on Windows.
f64
and f128
work fine.
const builtin = @import("builtin");
const std = @import("std");
test "coerce between pointers of compatible differently-named floats" {
std.debug.print("\n", .{});
std.debug.print("stage: {d}\n", .{builtin.zig_backend});
std.debug.print("12.34: {d}\n", .{@bitCast(u80, @as(f80, 12.34))});
std.debug.print("12.34 +0: {d}\n", .{@bitCast(u80, @as(f80, 12.34) + 0)});
std.debug.print("12.34 -0: {d}\n", .{@bitCast(u80, @as(f80, 12.34) - 0)});
std.debug.print("\n", .{});
var f1: f80 = 12.34;
std.debug.print("f1 (12.34): {d}\n", .{@bitCast(u80, f1)});
f1 -= 0;
std.debug.print("f1 (12.34 -0): {d}\n", .{@bitCast(u80, f1)});
f1 += 0; // gives 302282575443171561271296
// but should be 302282575443171561271460
std.debug.print("f1 (12.34 +0): {d}\n", .{@bitCast(u80, f1)});
}
// # Windows (zig 0.10.0-dev.3475+b3d463c9e)
//PS C:\Users\user> C:\Users\user\zig\zig.exe test .\src\test\behavior\cast.zig
//Test [1/1] test "coerce between pointers of compatible differently-named floats"...
//stage: std.builtin.CompilerBackend.stage1
//12.34: 302282575443171561271460
//12.34 +0: 302282575443171561271460
//12.34 -0: 302282575443171561271460
//
//f1 (12.34): 302282575443171561271460
//f1 (12.34 -0): 302282575443171561271460
//f1 (12.34 +0): 302282575443171561271296 <--- diff
//All 1 tests passed.
// # Linux (zig 0.10.0-dev.1740+971ef7b9c)
//Test [1/1] test "coerce between pointers of compatible differently-named floats"...
//stage: std.builtin.CompilerBackend.stage1
//12.34: 302282575443171561271460
//12.34 +0: 302282575443171561271460
//12.34 -0: 302282575443171561271460
//
//f1 (12.34): 302282575443171561271460
//f1 (12.34 -0): 302282575443171561271460
//f1 (12.34 +0): 302282575443171561271460
//All 1 tests passed.
This problem has been ongoing but masked by #12380.
While 12380 did mask the issue of the "+=
on f80
" highlighted by the test 6fde2fc coerce between pointers of compatible differently-named floats
(2022-05-08) the issue predates 02902cc (2022-02-17).
// zig v0.10.0-dev.765+02902cc09
// zig run test.zig
const std = @import("std");
pub fn main() void {
var f1: f80 = 12.34;
std.debug.print("{d}\n", .{@bitCast(u80, f1)}); // 302282575443171561271460
f1 += 0;
std.debug.print("{d}\n", .{@bitCast(u80, f1)}); // 302282575443171561271296
std.debug.print("{d}\n", .{@bitCast(u80, @as(f80, 12.34))}); // 302282575443171561271460
}
+= 0
on type f80 is now fixed in version 0.11.0-dev.1025+aadd1b252, but += 1
is still broken.
For what it's worth, the problem only appears in Debug mode with no Link Time Optimization (LTO).
// zig version 0.11.0-dev.1025+aadd1b252
// test.zig
const std = @import("std");
pub fn main() void {
var f1: f80 = 12.34;
std.debug.print("{d}\n", .{@bitCast(u80, f1)});
f1 += 1;
std.debug.print("{d}\n", .{@bitCast(u80, f1)});
std.debug.print("{d}\n", .{@bitCast(u80, @as(f80, 12.34) + 1)});
}
// $ zig2.exe run -ODebug -flto test.zig
// 302282575443171561271460
// 302283728364676168118436
// 302283728364676168118436
//
// $ zig2.exe run -ODebug -fno-lto test.zig
// 302282575443171561271460
// 302283728364676168118272 <--- this is wrong (last bits of f80 seem truncated)
// 302283728364676168118436
//
// -OReleaseFast and -OReleaseSmall work with or without LTO
When launching the failing test with LTO, the test "coerce between pointers of compatible differently-named floats" passed on Windows.
.\build\zig2.exe test .\test\behavior.zig -flto --test-name-prefix behavior-native-Debug-bare-multi-default --name test
I think I found the issue.
On Windows, the FPU Control Word (fctrl) register is set to double precision (0x027f) by default instead of double extended-precision (0x037f).
Changing the precision to double extended-precision or using finit
at the beginning of the program should fix the problem.
As a side note, linking to libc -lc
also fixes the problem; my guess is that libc initializes fctrl correctly at the start.
This problem has been ongoing but masked by #12380.