| author | |
| committer | |
| log | d03e9d0b8347a74d674bdafadb71e7ddd8fdfad1 |
| tree | 497835a372d774c00ac1181f20886eaf94f6b34d |
| parent | 77ffffc7cc2c22ede60876281ea5d1cdfdf7afa2 |
LLVM and compiler-rt must agree on how the parameters are passed, it
turns out that in LLVM13 something changed and broke the test case for
AArch64 systems.
It has nothing to do with fma at all.
Closes #99006 files changed, 57 insertions(+), 22 deletions(-)
lib/std/special/compiler_rt/extendXfYf2.zig+13-10| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | 3 | const is_test = builtin.is_test; |
| 4 | const native_arch = builtin.cpu.arch; | ||
| 4 | 5 | ||
| 5 | pub fn __extendsfdf2(a: f32) callconv(.C) f64 { | 6 | pub fn __extendsfdf2(a: f32) callconv(.C) f64 { |
| 6 | return extendXfYf2(f64, f32, @bitCast(u32, a)); | 7 | return extendXfYf2(f64, f32, @bitCast(u32, a)); |
| ... | @@ -14,12 +15,16 @@ pub fn __extendsftf2(a: f32) callconv(.C) f128 { | ... | @@ -14,12 +15,16 @@ pub fn __extendsftf2(a: f32) callconv(.C) f128 { |
| 14 | return extendXfYf2(f128, f32, @bitCast(u32, a)); | 15 | return extendXfYf2(f128, f32, @bitCast(u32, a)); |
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | pub fn __extendhfsf2(a: u16) callconv(.C) f32 { | 18 | // AArch64 is the only ABI (at the moment) to support f16 arguments without the |
| 18 | return extendXfYf2(f32, f16, a); | 19 | // need for extending them to wider fp types. |
| 20 | pub const F16T = if (native_arch.isAARCH64()) f16 else u16; | ||
| 21 | |||
| 22 | pub fn __extendhfsf2(a: F16T) callconv(.C) f32 { | ||
| 23 | return extendXfYf2(f32, f16, @bitCast(u16, a)); | ||
| 19 | } | 24 | } |
| 20 | 25 | ||
| 21 | pub fn __extendhftf2(a: u16) callconv(.C) f128 { | 26 | pub fn __extendhftf2(a: F16T) callconv(.C) f128 { |
| 22 | return extendXfYf2(f128, f16, a); | 27 | return extendXfYf2(f128, f16, @bitCast(u16, a)); |
| 23 | } | 28 | } |
| 24 | 29 | ||
| 25 | pub fn __extendxftf2(a: c_longdouble) callconv(.C) f128 { | 30 | pub fn __extendxftf2(a: c_longdouble) callconv(.C) f128 { |
| ... | @@ -29,16 +34,14 @@ pub fn __extendxftf2(a: c_longdouble) callconv(.C) f128 { | ... | @@ -29,16 +34,14 @@ pub fn __extendxftf2(a: c_longdouble) callconv(.C) f128 { |
| 29 | 34 | ||
| 30 | pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 { | 35 | pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 { |
| 31 | @setRuntimeSafety(false); | 36 | @setRuntimeSafety(false); |
| 32 | return @call(.{ .modifier = .always_inline }, __extendhfsf2, .{arg}); | 37 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, arg }); |
| 33 | } | 38 | } |
| 34 | 39 | ||
| 35 | pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 { | 40 | pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 { |
| 36 | @setRuntimeSafety(false); | 41 | @setRuntimeSafety(false); |
| 37 | return @call(.{ .modifier = .always_inline }, __extendsfdf2, .{arg}); | 42 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f64, f32, @bitCast(u32, arg) }); |
| 38 | } | 43 | } |
| 39 | 44 | ||
| 40 | const CHAR_BIT = 8; | ||
| 41 | |||
| 42 | inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) dst_t { | 45 | inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) dst_t { |
| 43 | @setRuntimeSafety(builtin.is_test); | 46 | @setRuntimeSafety(builtin.is_test); |
| 44 | 47 | ||
| ... | @@ -50,7 +53,7 @@ inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.In | ... | @@ -50,7 +53,7 @@ inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.In |
| 50 | 53 | ||
| 51 | // Various constants whose values follow from the type parameters. | 54 | // Various constants whose values follow from the type parameters. |
| 52 | // Any reasonable optimizer will fold and propagate all of these. | 55 | // Any reasonable optimizer will fold and propagate all of these. |
| 53 | const srcBits = @sizeOf(src_t) * CHAR_BIT; | 56 | const srcBits = @bitSizeOf(src_t); |
| 54 | const srcExpBits = srcBits - srcSigBits - 1; | 57 | const srcExpBits = srcBits - srcSigBits - 1; |
| 55 | const srcInfExp = (1 << srcExpBits) - 1; | 58 | const srcInfExp = (1 << srcExpBits) - 1; |
| 56 | const srcExpBias = srcInfExp >> 1; | 59 | const srcExpBias = srcInfExp >> 1; |
| ... | @@ -62,7 +65,7 @@ inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.In | ... | @@ -62,7 +65,7 @@ inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.In |
| 62 | const srcQNaN = 1 << (srcSigBits - 1); | 65 | const srcQNaN = 1 << (srcSigBits - 1); |
| 63 | const srcNaNCode = srcQNaN - 1; | 66 | const srcNaNCode = srcQNaN - 1; |
| 64 | 67 | ||
| 65 | const dstBits = @sizeOf(dst_t) * CHAR_BIT; | 68 | const dstBits = @bitSizeOf(dst_t); |
| 66 | const dstExpBits = dstBits - dstSigBits - 1; | 69 | const dstExpBits = dstBits - dstSigBits - 1; |
| 67 | const dstInfExp = (1 << dstExpBits) - 1; | 70 | const dstInfExp = (1 << dstExpBits) - 1; |
| 68 | const dstExpBias = dstInfExp >> 1; | 71 | const dstExpBias = dstInfExp >> 1; |
lib/std/special/compiler_rt/extendXfYf2_test.zig+3-2| ... | @@ -3,6 +3,7 @@ const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; | ... | @@ -3,6 +3,7 @@ const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; |
| 3 | const __extendhftf2 = @import("extendXfYf2.zig").__extendhftf2; | 3 | const __extendhftf2 = @import("extendXfYf2.zig").__extendhftf2; |
| 4 | const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2; | 4 | const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2; |
| 5 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; | 5 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; |
| 6 | const F16T = @import("extendXfYf2.zig").F16T; | ||
| 6 | 7 | ||
| 7 | fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) !void { | 8 | fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) !void { |
| 8 | const x = __extenddftf2(a); | 9 | const x = __extenddftf2(a); |
| ... | @@ -27,7 +28,7 @@ fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) !void { | ... | @@ -27,7 +28,7 @@ fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) !void { |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | fn test__extendhfsf2(a: u16, expected: u32) !void { | 30 | fn test__extendhfsf2(a: u16, expected: u32) !void { |
| 30 | const x = __extendhfsf2(a); | 31 | const x = __extendhfsf2(@bitCast(F16T, a)); |
| 31 | const rep = @bitCast(u32, x); | 32 | const rep = @bitCast(u32, x); |
| 32 | 33 | ||
| 33 | if (rep == expected) { | 34 | if (rep == expected) { |
| ... | @@ -159,7 +160,7 @@ fn makeInf32() f32 { | ... | @@ -159,7 +160,7 @@ fn makeInf32() f32 { |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | fn test__extendhftf2(a: u16, expectedHi: u64, expectedLo: u64) !void { | 162 | fn test__extendhftf2(a: u16, expectedHi: u64, expectedLo: u64) !void { |
| 162 | const x = __extendhftf2(a); | 163 | const x = __extendhftf2(@bitCast(F16T, a)); |
| 163 | 164 | ||
| 164 | const rep = @bitCast(u128, x); | 165 | const rep = @bitCast(u128, x); |
| 165 | const hi = @intCast(u64, rep >> 64); | 166 | const hi = @intCast(u64, rep >> 64); |
lib/std/special/compiler_rt/truncXfYf2.zig+12-6| ... | @@ -1,15 +1,21 @@ | ... | @@ -1,15 +1,21 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 3 | const native_arch = builtin.cpu.arch; | ||
| 2 | 4 | ||
| 3 | pub fn __truncsfhf2(a: f32) callconv(.C) u16 { | 5 | // AArch64 is the only ABI (at the moment) to support f16 arguments without the |
| 4 | return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f32, a })); | 6 | // need for extending them to wider fp types. |
| 7 | pub const F16T = if (native_arch.isAARCH64()) f16 else u16; | ||
| 8 | |||
| 9 | pub fn __truncsfhf2(a: f32) callconv(.C) F16T { | ||
| 10 | return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f32, a })); | ||
| 5 | } | 11 | } |
| 6 | 12 | ||
| 7 | pub fn __truncdfhf2(a: f64) callconv(.C) u16 { | 13 | pub fn __truncdfhf2(a: f64) callconv(.C) F16T { |
| 8 | return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a })); | 14 | return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a })); |
| 9 | } | 15 | } |
| 10 | 16 | ||
| 11 | pub fn __trunctfhf2(a: f128) callconv(.C) u16 { | 17 | pub fn __trunctfhf2(a: f128) callconv(.C) F16T { |
| 12 | return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f128, a })); | 18 | return @bitCast(F16T, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f128, a })); |
| 13 | } | 19 | } |
| 14 | 20 | ||
| 15 | pub fn __trunctfsf2(a: f128) callconv(.C) f32 { | 21 | pub fn __trunctfsf2(a: f128) callconv(.C) f32 { |
lib/std/special/compiler_rt/truncXfYf2_test.zig+2-2| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2; | 1 | const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2; |
| 2 | 2 | ||
| 3 | fn test__truncsfhf2(a: u32, expected: u16) !void { | 3 | fn test__truncsfhf2(a: u32, expected: u16) !void { |
| 4 | const actual = __truncsfhf2(@bitCast(f32, a)); | 4 | const actual = @bitCast(u16, __truncsfhf2(@bitCast(f32, a))); |
| 5 | 5 | ||
| 6 | if (actual == expected) { | 6 | if (actual == expected) { |
| 7 | return; | 7 | return; |
| ... | @@ -82,7 +82,7 @@ fn test__truncdfhf2(a: f64, expected: u16) void { | ... | @@ -82,7 +82,7 @@ fn test__truncdfhf2(a: f64, expected: u16) void { |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | fn test__truncdfhf2_raw(a: u64, expected: u16) void { | 84 | fn test__truncdfhf2_raw(a: u64, expected: u16) void { |
| 85 | const actual = __truncdfhf2(@bitCast(f64, a)); | 85 | const actual = @bitCast(u16, __truncdfhf2(@bitCast(f64, a))); |
| 86 | 86 | ||
| 87 | if (actual == expected) { | 87 | if (actual == expected) { |
| 88 | return; | 88 | return; |
test/behavior/cast_stage1.zig+26| ... | @@ -263,6 +263,32 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | ... | @@ -263,6 +263,32 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" { |
| 263 | try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name")); | 263 | try expect(mem.eql(u8, std.mem.spanZ(@ptrCast([*:0]const u8, x[0].?)), "window name")); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | test "cast f16 to wider types" { | ||
| 267 | const S = struct { | ||
| 268 | fn doTheTest() !void { | ||
| 269 | var x: f16 = 1234.0; | ||
| 270 | try std.testing.expectEqual(@as(f32, 1234.0), x); | ||
| 271 | try std.testing.expectEqual(@as(f64, 1234.0), x); | ||
| 272 | try std.testing.expectEqual(@as(f128, 1234.0), x); | ||
| 273 | } | ||
| 274 | }; | ||
| 275 | try S.doTheTest(); | ||
| 276 | comptime try S.doTheTest(); | ||
| 277 | } | ||
| 278 | |||
| 279 | test "cast f128 to narrower types" { | ||
| 280 | const S = struct { | ||
| 281 | fn doTheTest() !void { | ||
| 282 | var x: f128 = 1234.0; | ||
| 283 | try std.testing.expectEqual(@as(f16, 1234.0), @floatCast(f16, x)); | ||
| 284 | try std.testing.expectEqual(@as(f32, 1234.0), @floatCast(f32, x)); | ||
| 285 | try std.testing.expectEqual(@as(f64, 1234.0), @floatCast(f64, x)); | ||
| 286 | } | ||
| 287 | }; | ||
| 288 | try S.doTheTest(); | ||
| 289 | comptime try S.doTheTest(); | ||
| 290 | } | ||
| 291 | |||
| 266 | test "vector casts" { | 292 | test "vector casts" { |
| 267 | const S = struct { | 293 | const S = struct { |
| 268 | fn doTheTest() !void { | 294 | fn doTheTest() !void { |
test/behavior/muladd.zig+1-2| ... | @@ -24,8 +24,7 @@ fn testMulAdd() !void { | ... | @@ -24,8 +24,7 @@ fn testMulAdd() !void { |
| 24 | var c: f64 = 6.25; | 24 | var c: f64 = 6.25; |
| 25 | try expect(@mulAdd(f64, a, b, c) == 20); | 25 | try expect(@mulAdd(f64, a, b, c) == 20); |
| 26 | } | 26 | } |
| 27 | // TODO https://github.com/ziglang/zig/issues/9900 | 27 | { |
| 28 | if (@import("builtin").cpu.arch != .aarch64) { | ||
| 29 | var a: f16 = 5.5; | 28 | var a: f16 = 5.5; |
| 30 | var b: f128 = 2.5; | 29 | var b: f128 = 2.5; |
| 31 | var c: f128 = 6.25; | 30 | var c: f128 = 6.25; |