diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-03-14 00:10:35 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-14 00:11:46 -0700 |
| commit | b2a1b4c085b93d508c51307f40444252b8cd4d52 (patch) | |
| tree | 307c504b85c9aee16602e667db1a5db5c25e1fff | |
| parent | eee989d2a00f99d95900515b48f981f2ea6bbe78 (diff) | |
| download | zig-b2a1b4c085b93d508c51307f40444252b8cd4d52.tar.gz zig-b2a1b4c085b93d508c51307f40444252b8cd4d52.zip | |
Sema: improve lowering of stores to bitcasted vector pointers
Detect if we are storing an array operand to a bitcasted vector pointer.
If so, we instead reach through the bitcasted pointer to the vector pointer,
bitcast the array operand to a vector, and then lower this as a store of
a vector value to a vector pointer. This generally results in better code,
as well as working around an LLVM bug.
See #11154
| -rw-r--r-- | src/Sema.zig | 52 | ||||
| -rw-r--r-- | src/value.zig | 19 | ||||
| -rw-r--r-- | test/behavior/cast.zig | 25 | ||||
| -rw-r--r-- | test/behavior/floatop.zig | 145 | ||||
| -rw-r--r-- | test/behavior/math.zig | 169 |
5 files changed, 324 insertions, 86 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 448f7c0c0c..99519cd562 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -13276,7 +13276,7 @@ fn checkFloatType( ty: Type, ) CompileError!void { switch (ty.zigTypeTag()) { - .ComptimeFloat, .Float => {}, + .ComptimeInt, .ComptimeFloat, .Float => {}, else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty}), } } @@ -17177,10 +17177,25 @@ fn storePtr2( return; } + // TODO do the same thing for anon structs as for tuples above. + + // Detect if we are storing an array operand to a bitcasted vector pointer. + // If so, we instead reach through the bitcasted pointer to the vector pointer, + // bitcast the array operand to a vector, and then lower this as a store of + // a vector value to a vector pointer. This generally results in better code, + // as well as working around an LLVM bug: + // https://github.com/ziglang/zig/issues/11154 + if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| { + const vector_ty = sema.typeOf(vector_ptr).childType(); + const vector = try sema.coerce(block, vector_ty, uncasted_operand, operand_src); + try sema.storePtr2(block, src, vector_ptr, ptr_src, vector, operand_src, .store); + return; + } + const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src); + const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { - const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); const operand_val = maybe_operand_val orelse { try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); break :rs operand_src; @@ -17203,6 +17218,39 @@ fn storePtr2( _ = try block.addBinOp(air_tag, ptr, operand); } +/// Traverse an arbitrary number of bitcasted pointers and return the underyling vector +/// pointer. Only if the final element type matches the vector element type, and the +/// lengths match. +fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { + const array_ty = sema.typeOf(ptr).childType(); + if (array_ty.zigTypeTag() != .Array) return null; + var ptr_inst = Air.refToIndex(ptr) orelse return null; + const air_datas = sema.air_instructions.items(.data); + const air_tags = sema.air_instructions.items(.tag); + const prev_ptr = while (air_tags[ptr_inst] == .bitcast) { + const prev_ptr = air_datas[ptr_inst].ty_op.operand; + const prev_ptr_ty = sema.typeOf(prev_ptr); + const prev_ptr_child_ty = switch (prev_ptr_ty.tag()) { + .single_mut_pointer => prev_ptr_ty.castTag(.single_mut_pointer).?.data, + .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type, + else => return null, + }; + if (prev_ptr_child_ty.zigTypeTag() == .Vector) break prev_ptr; + ptr_inst = Air.refToIndex(prev_ptr) orelse return null; + } else return null; + + // We have a pointer-to-array and a pointer-to-vector. If the elements and + // lengths match, return the result. + const vector_ty = sema.typeOf(prev_ptr).childType(); + if (array_ty.childType().eql(vector_ty.childType()) and + array_ty.arrayLen() == vector_ty.vectorLen()) + { + return prev_ptr; + } else { + return null; + } +} + /// Call when you have Value objects rather than Air instructions, and you want to /// assert the store must be done at comptime. fn storePtrVal( diff --git a/src/value.zig b/src/value.zig index 9117ef78df..6ab3adba36 100644 --- a/src/value.zig +++ b/src/value.zig @@ -3931,15 +3931,12 @@ pub const Value = extern union { }, 80 => { if (true) { - @panic("TODO implement compiler_rt fabs for f80"); + @panic("TODO implement compiler_rt fabs for f80 (__fabsx)"); } const f = val.toFloat(f80); return Value.Tag.float_80.create(arena, @fabs(f)); }, 128 => { - if (true) { - @panic("TODO implement compiler_rt fabs for f128"); - } const f = val.toFloat(f128); return Value.Tag.float_128.create(arena, @fabs(f)); }, @@ -3963,15 +3960,12 @@ pub const Value = extern union { }, 80 => { if (true) { - @panic("TODO implement compiler_rt floor for f80"); + @panic("TODO implement compiler_rt floor for f80 (__floorx)"); } const f = val.toFloat(f80); return Value.Tag.float_80.create(arena, @floor(f)); }, 128 => { - if (true) { - @panic("TODO implement compiler_rt floor for f128"); - } const f = val.toFloat(f128); return Value.Tag.float_128.create(arena, @floor(f)); }, @@ -4001,9 +3995,6 @@ pub const Value = extern union { return Value.Tag.float_80.create(arena, @ceil(f)); }, 128 => { - if (true) { - @panic("TODO implement compiler_rt ceil for f128"); - } const f = val.toFloat(f128); return Value.Tag.float_128.create(arena, @ceil(f)); }, @@ -4033,9 +4024,6 @@ pub const Value = extern union { return Value.Tag.float_80.create(arena, @round(f)); }, 128 => { - if (true) { - @panic("TODO implement compiler_rt round for f128"); - } const f = val.toFloat(f128); return Value.Tag.float_128.create(arena, @round(f)); }, @@ -4065,9 +4053,6 @@ pub const Value = extern union { return Value.Tag.float_80.create(arena, @trunc(f)); }, 128 => { - if (true) { - @panic("TODO implement compiler_rt trunc for f128"); - } const f = val.toFloat(f128); return Value.Tag.float_128.create(arena, @trunc(f)); }, diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 1f92a0214f..69e64b8973 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -95,8 +95,29 @@ test "comptime_int @intToFloat" { } } +test "@intToFloat" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + try testIntToFloat(-2); + } + + fn testIntToFloat(k: i32) !void { + const f = @intToFloat(f32, k); + const i = @floatToInt(i32, f); + try expect(i == k); + } + }; + try S.doTheTest(); + comptime try S.doTheTest(); +} + test "@floatToInt" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO @@ -1007,8 +1028,6 @@ test "peer type resolve array pointer and unknown pointer" { } test "comptime float casts" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - const a = @intToFloat(comptime_float, 1); try expect(a == 1); try expect(@TypeOf(a) == comptime_float); diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index d82637b24d..424677ea1c 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -333,7 +333,6 @@ fn testLog() !void { } test "@log with vectors" { - if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO @@ -343,15 +342,19 @@ test "@log with vectors" { { var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @log(v); - try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon)); - try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon)); + try expect(@log(@as(f32, 1.1)) == result[0]); + try expect(@log(@as(f32, 2.2)) == result[1]); try expect(@log(@as(f32, 0.3)) == result[2]); - try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon)); + try expect(@log(@as(f32, 0.4)) == result[3]); } } test "@log2" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO comptime try testLog2(); try testLog2(); @@ -368,15 +371,19 @@ fn testLog2() !void { { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @log2(v); - try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon)); - try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon)); - try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon)); - try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon)); + try expect(@log2(@as(f32, 1.1)) == result[0]); + try expect(@log2(@as(f32, 2.2)) == result[1]); + try expect(@log2(@as(f32, 0.3)) == result[2]); + try expect(@log2(@as(f32, 0.4)) == result[3]); } } test "@log10" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO comptime try testLog10(); try testLog10(); @@ -393,10 +400,10 @@ fn testLog10() !void { { var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; var result = @log10(v); - try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon)); - try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon)); - try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon)); - try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon)); + try expect(@log10(@as(f32, 1.1)) == result[0]); + try expect(@log10(@as(f32, 2.2)) == result[1]); + try expect(@log10(@as(f32, 0.3)) == result[2]); + try expect(@log10(@as(f32, 0.4)) == result[3]); } } @@ -537,7 +544,71 @@ fn testTrunc() !void { } } -test "negation" { +test "negation f16" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + + if (builtin.os.tag == .freebsd) { + // TODO file issue to track this failure + return error.SkipZigTest; + } + + const S = struct { + fn doTheTest() !void { + var a: f16 = 1; + a = -a; + try expect(a == -1); + a = -a; + try expect(a == 1); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "negation f32" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var a: f32 = 1; + a = -a; + try expect(a == -1); + a = -a; + try expect(a == 1); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "negation f64" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + + const S = struct { + fn doTheTest() !void { + var a: f64 = 1; + a = -a; + try expect(a == -1); + a = -a; + try expect(a == 1); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "negation f80" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO if (builtin.os.tag == .freebsd) { @@ -547,11 +618,37 @@ test "negation" { const S = struct { fn doTheTest() !void { - inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { - var a: T = 1; - a = -a; - try expect(a == -1); - } + var a: f80 = 1; + a = -a; + try expect(a == -1); + a = -a; + try expect(a == 1); + } + }; + + try S.doTheTest(); + comptime try S.doTheTest(); +} + +test "negation f128" { + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + + if (builtin.os.tag == .freebsd) { + // TODO file issue to track this failure + return error.SkipZigTest; + } + + const S = struct { + fn doTheTest() !void { + var a: f128 = 1; + a = -a; + try expect(a == -1); + a = -a; + try expect(a == 1); } }; @@ -583,7 +680,13 @@ test "float literal at compile time not lossy" { } test "f128 at compile time is lossy" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend != .stage1) { + // this one is happening because we represent comptime-known f128 integers with + // Value.Tag.bigint and only convert to f128 representation if it stops being an + // integer. Is this something we want? need to have a lang spec discussion on this + // topic. + return error.SkipZigTest; // TODO + } try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); } diff --git a/test/behavior/math.zig b/test/behavior/math.zig index c6fc43e38c..31dd6d09f3 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -6,7 +6,6 @@ const expectEqualSlices = std.testing.expectEqualSlices; const maxInt = std.math.maxInt; const minInt = std.math.minInt; const mem = std.mem; -const has_f80_rt = builtin.cpu.arch == .x86_64; test "assignment operators" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO @@ -1046,12 +1045,14 @@ fn testSqrt(comptime T: type, x: T) !void { } test "@fabs" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try testFabs(f128, 12.0); comptime try testFabs(f128, 12.0); - if (has_f80_rt) try testFabs(f80, 12.0); - // comptime try testFabs(f80, 12.0); try testFabs(f64, 12.0); comptime try testFabs(f64, 12.0); try testFabs(f32, 12.0); @@ -1065,20 +1066,25 @@ test "@fabs" { comptime try expectEqual(x, z); } +test "@fabs f80" { + if (true) { + // https://github.com/ziglang/zig/issues/11030 + return error.SkipZigTest; + } + + try testFabs(f80, 12.0); + comptime try testFabs(f80, 12.0); +} + fn testFabs(comptime T: type, x: T) !void { const y = -x; const z = @fabs(y); - try expectEqual(x, z); + try expect(x == z); } test "@floor" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - // FIXME: Generates a floorl function call - // testFloor(f128, 12.0); - comptime try testFloor(f128, 12.0); - // try testFloor(f80, 12.0); - comptime try testFloor(f80, 12.0); try testFloor(f64, 12.0); comptime try testFloor(f64, 12.0); try testFloor(f32, 12.0); @@ -1089,23 +1095,39 @@ test "@floor" { const x = 14.0; const y = x + 0.7; const z = @floor(y); - comptime try expectEqual(x, z); + comptime try expect(x == z); +} + +test "@floor f80" { + if (true) { + // https://github.com/ziglang/zig/issues/11030 + return error.SkipZigTest; + } + try testFloor(f80, 12.0); + comptime try testFloor(f80, 12.0); +} + +test "@floor f128" { + if (builtin.zig_backend == .stage1) { + // Fails because it incorrectly lowers to a floorl function call. + return error.SkipZigTest; + } + + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + testFloor(f128, 12.0); + comptime try testFloor(f128, 12.0); } fn testFloor(comptime T: type, x: T) !void { const y = x + 0.6; const z = @floor(y); - try expectEqual(x, z); + try expect(x == z); } test "@ceil" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - // FIXME: Generates a ceill function call - //testCeil(f128, 12.0); - comptime try testCeil(f128, 12.0); - // try testCeil(f80, 12.0); - comptime try testCeil(f80, 12.0); try testCeil(f64, 12.0); comptime try testCeil(f64, 12.0); try testCeil(f32, 12.0); @@ -1116,29 +1138,40 @@ test "@ceil" { const x = 14.0; const y = x - 0.7; const z = @ceil(y); - comptime try expectEqual(x, z); + comptime try expect(x == z); +} + +test "@ceil f80" { + if (true) { + // https://github.com/ziglang/zig/issues/11030 + return error.SkipZigTest; + } + + try testCeil(f80, 12.0); + comptime try testCeil(f80, 12.0); +} + +test "@ceil f128" { + if (builtin.zig_backend == .stage1) { + // Fails because it incorrectly lowers to a ceill function call. + return error.SkipZigTest; + } + + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + testCeil(f128, 12.0); + comptime try testCeil(f128, 12.0); } fn testCeil(comptime T: type, x: T) !void { const y = x - 0.8; const z = @ceil(y); - try expectEqual(x, z); + try expect(x == z); } test "@trunc" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - // FIXME: Generates a truncl function call - //testTrunc(f128, 12.0); - comptime try testTrunc(f128, 12.0); - // try testTrunc(f80, 12.0); - // comptime try testTrunc(f80, 12.0); - comptime { - const x: f80 = 12.0; - const y = x + 0.8; - const z = @trunc(y); - try expectEqual(x, z); - } try testTrunc(f64, 12.0); comptime try testTrunc(f64, 12.0); try testTrunc(f32, 12.0); @@ -1149,31 +1182,54 @@ test "@trunc" { const x = 14.0; const y = x + 0.7; const z = @trunc(y); - comptime try expectEqual(x, z); + comptime try expect(x == z); +} + +test "@trunc f80" { + if (true) { + // https://github.com/ziglang/zig/issues/11030 + return error.SkipZigTest; + } + + try testTrunc(f80, 12.0); + comptime try testTrunc(f80, 12.0); + comptime { + const x: f80 = 12.0; + const y = x + 0.8; + const z = @trunc(y); + try expect(x == z); + } +} + +test "@trunc f128" { + if (builtin.zig_backend == .stage1) { + // Fails because it incorrectly lowers to a truncl function call. + return error.SkipZigTest; + } + + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + testTrunc(f128, 12.0); + comptime try testTrunc(f128, 12.0); } fn testTrunc(comptime T: type, x: T) !void { { const y = x + 0.8; const z = @trunc(y); - try expectEqual(x, z); + try expect(x == z); } { const y = -x - 0.8; const z = @trunc(y); - try expectEqual(-x, z); + try expect(-x == z); } } test "@round" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO - // FIXME: Generates a roundl function call - //testRound(f128, 12.0); - comptime try testRound(f128, 12.0); - // try testRound(f80, 12.0); - comptime try testRound(f80, 12.0); try testRound(f64, 12.0); comptime try testRound(f64, 12.0); try testRound(f32, 12.0); @@ -1184,13 +1240,35 @@ test "@round" { const x = 14.0; const y = x + 0.4; const z = @round(y); - comptime try expectEqual(x, z); + comptime try expect(x == z); +} + +test "@round f80" { + if (true) { + // https://github.com/ziglang/zig/issues/11030 + return error.SkipZigTest; + } + + try testRound(f80, 12.0); + comptime try testRound(f80, 12.0); +} + +test "@round f128" { + if (builtin.zig_backend == .stage1) { + // Fails because it incorrectly lowers to a roundl function call. + return error.SkipZigTest; + } + + if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO + + testRound(f128, 12.0); + comptime try testRound(f128, 12.0); } fn testRound(comptime T: type, x: T) !void { const y = x - 0.5; const z = @round(y); - try expectEqual(x, z); + try expect(x == z); } test "vector integer addition" { @@ -1225,10 +1303,15 @@ test "NaN comparison" { comptime try testNanEqNan(f32); comptime try testNanEqNan(f64); comptime try testNanEqNan(f128); +} - // TODO https://github.com/ziglang/zig/issues/11030 - // try testNanEqNan(f80); - // comptime try testNanEqNan(f80); +test "NaN comparison f80" { + if (true) { + // https://github.com/ziglang/zig/issues/11030 + return error.SkipZigTest; + } + try testNanEqNan(f80); + comptime try testNanEqNan(f80); } fn testNanEqNan(comptime F: type) !void { |
