aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-03-14 00:10:35 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-14 00:11:46 -0700
commitb2a1b4c085b93d508c51307f40444252b8cd4d52 (patch)
tree307c504b85c9aee16602e667db1a5db5c25e1fff
parenteee989d2a00f99d95900515b48f981f2ea6bbe78 (diff)
downloadzig-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.zig52
-rw-r--r--src/value.zig19
-rw-r--r--test/behavior/cast.zig25
-rw-r--r--test/behavior/floatop.zig145
-rw-r--r--test/behavior/math.zig169
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 {