| author | |
| committer | |
| log | b2a1b4c085b93d508c51307f40444252b8cd4d52 |
| tree | 307c504b85c9aee16602e667db1a5db5c25e1fff |
| parent | eee989d2a00f99d95900515b48f981f2ea6bbe78 |
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 #111545 files changed, 324 insertions(+), 86 deletions(-)
src/Sema.zig+50-2| ... | ... | @@ -13276,7 +13276,7 @@ fn checkFloatType( |
| 13276 | 13276 | ty: Type, |
| 13277 | 13277 | ) CompileError!void { |
| 13278 | 13278 | switch (ty.zigTypeTag()) { |
| 13279 | .ComptimeFloat, .Float => {}, | |
| 13279 | .ComptimeInt, .ComptimeFloat, .Float => {}, | |
| 13280 | 13280 | else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty}), |
| 13281 | 13281 | } |
| 13282 | 13282 | } |
| ... | ... | @@ -17177,10 +17177,25 @@ fn storePtr2( |
| 17177 | 17177 | return; |
| 17178 | 17178 | } |
| 17179 | 17179 | |
| 17180 | // TODO do the same thing for anon structs as for tuples above. | |
| 17181 | ||
| 17182 | // Detect if we are storing an array operand to a bitcasted vector pointer. | |
| 17183 | // If so, we instead reach through the bitcasted pointer to the vector pointer, | |
| 17184 | // bitcast the array operand to a vector, and then lower this as a store of | |
| 17185 | // a vector value to a vector pointer. This generally results in better code, | |
| 17186 | // as well as working around an LLVM bug: | |
| 17187 | // https://github.com/ziglang/zig/issues/11154 | |
| 17188 | if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| { | |
| 17189 | const vector_ty = sema.typeOf(vector_ptr).childType(); | |
| 17190 | const vector = try sema.coerce(block, vector_ty, uncasted_operand, operand_src); | |
| 17191 | try sema.storePtr2(block, src, vector_ptr, ptr_src, vector, operand_src, .store); | |
| 17192 | return; | |
| 17193 | } | |
| 17194 | ||
| 17180 | 17195 | const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src); |
| 17196 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); | |
| 17181 | 17197 | |
| 17182 | 17198 | const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { |
| 17183 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, operand_src, operand); | |
| 17184 | 17199 | const operand_val = maybe_operand_val orelse { |
| 17185 | 17200 | try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); |
| 17186 | 17201 | break :rs operand_src; |
| ... | ... | @@ -17203,6 +17218,39 @@ fn storePtr2( |
| 17203 | 17218 | _ = try block.addBinOp(air_tag, ptr, operand); |
| 17204 | 17219 | } |
| 17205 | 17220 | |
| 17221 | /// Traverse an arbitrary number of bitcasted pointers and return the underyling vector | |
| 17222 | /// pointer. Only if the final element type matches the vector element type, and the | |
| 17223 | /// lengths match. | |
| 17224 | fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref { | |
| 17225 | const array_ty = sema.typeOf(ptr).childType(); | |
| 17226 | if (array_ty.zigTypeTag() != .Array) return null; | |
| 17227 | var ptr_inst = Air.refToIndex(ptr) orelse return null; | |
| 17228 | const air_datas = sema.air_instructions.items(.data); | |
| 17229 | const air_tags = sema.air_instructions.items(.tag); | |
| 17230 | const prev_ptr = while (air_tags[ptr_inst] == .bitcast) { | |
| 17231 | const prev_ptr = air_datas[ptr_inst].ty_op.operand; | |
| 17232 | const prev_ptr_ty = sema.typeOf(prev_ptr); | |
| 17233 | const prev_ptr_child_ty = switch (prev_ptr_ty.tag()) { | |
| 17234 | .single_mut_pointer => prev_ptr_ty.castTag(.single_mut_pointer).?.data, | |
| 17235 | .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type, | |
| 17236 | else => return null, | |
| 17237 | }; | |
| 17238 | if (prev_ptr_child_ty.zigTypeTag() == .Vector) break prev_ptr; | |
| 17239 | ptr_inst = Air.refToIndex(prev_ptr) orelse return null; | |
| 17240 | } else return null; | |
| 17241 | ||
| 17242 | // We have a pointer-to-array and a pointer-to-vector. If the elements and | |
| 17243 | // lengths match, return the result. | |
| 17244 | const vector_ty = sema.typeOf(prev_ptr).childType(); | |
| 17245 | if (array_ty.childType().eql(vector_ty.childType()) and | |
| 17246 | array_ty.arrayLen() == vector_ty.vectorLen()) | |
| 17247 | { | |
| 17248 | return prev_ptr; | |
| 17249 | } else { | |
| 17250 | return null; | |
| 17251 | } | |
| 17252 | } | |
| 17253 | ||
| 17206 | 17254 | /// Call when you have Value objects rather than Air instructions, and you want to |
| 17207 | 17255 | /// assert the store must be done at comptime. |
| 17208 | 17256 | fn storePtrVal( |
src/value.zig+2-17| ... | ... | @@ -3931,15 +3931,12 @@ pub const Value = extern union { |
| 3931 | 3931 | }, |
| 3932 | 3932 | 80 => { |
| 3933 | 3933 | if (true) { |
| 3934 | @panic("TODO implement compiler_rt fabs for f80"); | |
| 3934 | @panic("TODO implement compiler_rt fabs for f80 (__fabsx)"); | |
| 3935 | 3935 | } |
| 3936 | 3936 | const f = val.toFloat(f80); |
| 3937 | 3937 | return Value.Tag.float_80.create(arena, @fabs(f)); |
| 3938 | 3938 | }, |
| 3939 | 3939 | 128 => { |
| 3940 | if (true) { | |
| 3941 | @panic("TODO implement compiler_rt fabs for f128"); | |
| 3942 | } | |
| 3943 | 3940 | const f = val.toFloat(f128); |
| 3944 | 3941 | return Value.Tag.float_128.create(arena, @fabs(f)); |
| 3945 | 3942 | }, |
| ... | ... | @@ -3963,15 +3960,12 @@ pub const Value = extern union { |
| 3963 | 3960 | }, |
| 3964 | 3961 | 80 => { |
| 3965 | 3962 | if (true) { |
| 3966 | @panic("TODO implement compiler_rt floor for f80"); | |
| 3963 | @panic("TODO implement compiler_rt floor for f80 (__floorx)"); | |
| 3967 | 3964 | } |
| 3968 | 3965 | const f = val.toFloat(f80); |
| 3969 | 3966 | return Value.Tag.float_80.create(arena, @floor(f)); |
| 3970 | 3967 | }, |
| 3971 | 3968 | 128 => { |
| 3972 | if (true) { | |
| 3973 | @panic("TODO implement compiler_rt floor for f128"); | |
| 3974 | } | |
| 3975 | 3969 | const f = val.toFloat(f128); |
| 3976 | 3970 | return Value.Tag.float_128.create(arena, @floor(f)); |
| 3977 | 3971 | }, |
| ... | ... | @@ -4001,9 +3995,6 @@ pub const Value = extern union { |
| 4001 | 3995 | return Value.Tag.float_80.create(arena, @ceil(f)); |
| 4002 | 3996 | }, |
| 4003 | 3997 | 128 => { |
| 4004 | if (true) { | |
| 4005 | @panic("TODO implement compiler_rt ceil for f128"); | |
| 4006 | } | |
| 4007 | 3998 | const f = val.toFloat(f128); |
| 4008 | 3999 | return Value.Tag.float_128.create(arena, @ceil(f)); |
| 4009 | 4000 | }, |
| ... | ... | @@ -4033,9 +4024,6 @@ pub const Value = extern union { |
| 4033 | 4024 | return Value.Tag.float_80.create(arena, @round(f)); |
| 4034 | 4025 | }, |
| 4035 | 4026 | 128 => { |
| 4036 | if (true) { | |
| 4037 | @panic("TODO implement compiler_rt round for f128"); | |
| 4038 | } | |
| 4039 | 4027 | const f = val.toFloat(f128); |
| 4040 | 4028 | return Value.Tag.float_128.create(arena, @round(f)); |
| 4041 | 4029 | }, |
| ... | ... | @@ -4065,9 +4053,6 @@ pub const Value = extern union { |
| 4065 | 4053 | return Value.Tag.float_80.create(arena, @trunc(f)); |
| 4066 | 4054 | }, |
| 4067 | 4055 | 128 => { |
| 4068 | if (true) { | |
| 4069 | @panic("TODO implement compiler_rt trunc for f128"); | |
| 4070 | } | |
| 4071 | 4056 | const f = val.toFloat(f128); |
| 4072 | 4057 | return Value.Tag.float_128.create(arena, @trunc(f)); |
| 4073 | 4058 | }, |
test/behavior/cast.zig+22-3| ... | ... | @@ -95,8 +95,29 @@ test "comptime_int @intToFloat" { |
| 95 | 95 | } |
| 96 | 96 | } |
| 97 | 97 | |
| 98 | test "@intToFloat" { | |
| 99 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 100 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 101 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 102 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 103 | ||
| 104 | const S = struct { | |
| 105 | fn doTheTest() !void { | |
| 106 | try testIntToFloat(-2); | |
| 107 | } | |
| 108 | ||
| 109 | fn testIntToFloat(k: i32) !void { | |
| 110 | const f = @intToFloat(f32, k); | |
| 111 | const i = @floatToInt(i32, f); | |
| 112 | try expect(i == k); | |
| 113 | } | |
| 114 | }; | |
| 115 | try S.doTheTest(); | |
| 116 | comptime try S.doTheTest(); | |
| 117 | } | |
| 118 | ||
| 98 | 119 | test "@floatToInt" { |
| 99 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 120 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 100 | 121 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 101 | 122 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 102 | 123 | |
| ... | ... | @@ -1007,8 +1028,6 @@ test "peer type resolve array pointer and unknown pointer" { |
| 1007 | 1028 | } |
| 1008 | 1029 | |
| 1009 | 1030 | test "comptime float casts" { |
| 1010 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1011 | ||
| 1012 | 1031 | const a = @intToFloat(comptime_float, 1); |
| 1013 | 1032 | try expect(a == 1); |
| 1014 | 1033 | try expect(@TypeOf(a) == comptime_float); |
test/behavior/floatop.zig+124-21| ... | ... | @@ -333,7 +333,6 @@ fn testLog() !void { |
| 333 | 333 | } |
| 334 | 334 | |
| 335 | 335 | test "@log with vectors" { |
| 336 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO | |
| 337 | 336 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 338 | 337 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 339 | 338 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -343,15 +342,19 @@ test "@log with vectors" { |
| 343 | 342 | { |
| 344 | 343 | var v: @Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 345 | 344 | var result = @log(v); |
| 346 | try expect(math.approxEqAbs(f32, @log(@as(f32, 1.1)), result[0], epsilon)); | |
| 347 | try expect(math.approxEqAbs(f32, @log(@as(f32, 2.2)), result[1], epsilon)); | |
| 345 | try expect(@log(@as(f32, 1.1)) == result[0]); | |
| 346 | try expect(@log(@as(f32, 2.2)) == result[1]); | |
| 348 | 347 | try expect(@log(@as(f32, 0.3)) == result[2]); |
| 349 | try expect(math.approxEqAbs(f32, @log(@as(f32, 0.4)), result[3], epsilon)); | |
| 348 | try expect(@log(@as(f32, 0.4)) == result[3]); | |
| 350 | 349 | } |
| 351 | 350 | } |
| 352 | 351 | |
| 353 | 352 | test "@log2" { |
| 354 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 353 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 354 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 355 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 356 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 357 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 355 | 358 | |
| 356 | 359 | comptime try testLog2(); |
| 357 | 360 | try testLog2(); |
| ... | ... | @@ -368,15 +371,19 @@ fn testLog2() !void { |
| 368 | 371 | { |
| 369 | 372 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 370 | 373 | var result = @log2(v); |
| 371 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 1.1)), result[0], epsilon)); | |
| 372 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 2.2)), result[1], epsilon)); | |
| 373 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.3)), result[2], epsilon)); | |
| 374 | try expect(math.approxEqAbs(f32, @log2(@as(f32, 0.4)), result[3], epsilon)); | |
| 374 | try expect(@log2(@as(f32, 1.1)) == result[0]); | |
| 375 | try expect(@log2(@as(f32, 2.2)) == result[1]); | |
| 376 | try expect(@log2(@as(f32, 0.3)) == result[2]); | |
| 377 | try expect(@log2(@as(f32, 0.4)) == result[3]); | |
| 375 | 378 | } |
| 376 | 379 | } |
| 377 | 380 | |
| 378 | 381 | test "@log10" { |
| 379 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 382 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 383 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 384 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 385 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 386 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 380 | 387 | |
| 381 | 388 | comptime try testLog10(); |
| 382 | 389 | try testLog10(); |
| ... | ... | @@ -393,10 +400,10 @@ fn testLog10() !void { |
| 393 | 400 | { |
| 394 | 401 | var v: Vector(4, f32) = [_]f32{ 1.1, 2.2, 0.3, 0.4 }; |
| 395 | 402 | var result = @log10(v); |
| 396 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 1.1)), result[0], epsilon)); | |
| 397 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 2.2)), result[1], epsilon)); | |
| 398 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.3)), result[2], epsilon)); | |
| 399 | try expect(math.approxEqAbs(f32, @log10(@as(f32, 0.4)), result[3], epsilon)); | |
| 403 | try expect(@log10(@as(f32, 1.1)) == result[0]); | |
| 404 | try expect(@log10(@as(f32, 2.2)) == result[1]); | |
| 405 | try expect(@log10(@as(f32, 0.3)) == result[2]); | |
| 406 | try expect(@log10(@as(f32, 0.4)) == result[3]); | |
| 400 | 407 | } |
| 401 | 408 | } |
| 402 | 409 | |
| ... | ... | @@ -537,7 +544,71 @@ fn testTrunc() !void { |
| 537 | 544 | } |
| 538 | 545 | } |
| 539 | 546 | |
| 540 | test "negation" { | |
| 547 | test "negation f16" { | |
| 548 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 549 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 550 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 551 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 552 | ||
| 553 | if (builtin.os.tag == .freebsd) { | |
| 554 | // TODO file issue to track this failure | |
| 555 | return error.SkipZigTest; | |
| 556 | } | |
| 557 | ||
| 558 | const S = struct { | |
| 559 | fn doTheTest() !void { | |
| 560 | var a: f16 = 1; | |
| 561 | a = -a; | |
| 562 | try expect(a == -1); | |
| 563 | a = -a; | |
| 564 | try expect(a == 1); | |
| 565 | } | |
| 566 | }; | |
| 567 | ||
| 568 | try S.doTheTest(); | |
| 569 | comptime try S.doTheTest(); | |
| 570 | } | |
| 571 | ||
| 572 | test "negation f32" { | |
| 573 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 574 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 575 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 576 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 577 | ||
| 578 | const S = struct { | |
| 579 | fn doTheTest() !void { | |
| 580 | var a: f32 = 1; | |
| 581 | a = -a; | |
| 582 | try expect(a == -1); | |
| 583 | a = -a; | |
| 584 | try expect(a == 1); | |
| 585 | } | |
| 586 | }; | |
| 587 | ||
| 588 | try S.doTheTest(); | |
| 589 | comptime try S.doTheTest(); | |
| 590 | } | |
| 591 | ||
| 592 | test "negation f64" { | |
| 593 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 594 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 595 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 596 | ||
| 597 | const S = struct { | |
| 598 | fn doTheTest() !void { | |
| 599 | var a: f64 = 1; | |
| 600 | a = -a; | |
| 601 | try expect(a == -1); | |
| 602 | a = -a; | |
| 603 | try expect(a == 1); | |
| 604 | } | |
| 605 | }; | |
| 606 | ||
| 607 | try S.doTheTest(); | |
| 608 | comptime try S.doTheTest(); | |
| 609 | } | |
| 610 | ||
| 611 | test "negation f80" { | |
| 541 | 612 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 542 | 613 | |
| 543 | 614 | if (builtin.os.tag == .freebsd) { |
| ... | ... | @@ -547,11 +618,37 @@ test "negation" { |
| 547 | 618 | |
| 548 | 619 | const S = struct { |
| 549 | 620 | fn doTheTest() !void { |
| 550 | inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| { | |
| 551 | var a: T = 1; | |
| 552 | a = -a; | |
| 553 | try expect(a == -1); | |
| 554 | } | |
| 621 | var a: f80 = 1; | |
| 622 | a = -a; | |
| 623 | try expect(a == -1); | |
| 624 | a = -a; | |
| 625 | try expect(a == 1); | |
| 626 | } | |
| 627 | }; | |
| 628 | ||
| 629 | try S.doTheTest(); | |
| 630 | comptime try S.doTheTest(); | |
| 631 | } | |
| 632 | ||
| 633 | test "negation f128" { | |
| 634 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 635 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 636 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 637 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 638 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 639 | ||
| 640 | if (builtin.os.tag == .freebsd) { | |
| 641 | // TODO file issue to track this failure | |
| 642 | return error.SkipZigTest; | |
| 643 | } | |
| 644 | ||
| 645 | const S = struct { | |
| 646 | fn doTheTest() !void { | |
| 647 | var a: f128 = 1; | |
| 648 | a = -a; | |
| 649 | try expect(a == -1); | |
| 650 | a = -a; | |
| 651 | try expect(a == 1); | |
| 555 | 652 | } |
| 556 | 653 | }; |
| 557 | 654 | |
| ... | ... | @@ -583,7 +680,13 @@ test "float literal at compile time not lossy" { |
| 583 | 680 | } |
| 584 | 681 | |
| 585 | 682 | test "f128 at compile time is lossy" { |
| 586 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 683 | if (builtin.zig_backend != .stage1) { | |
| 684 | // this one is happening because we represent comptime-known f128 integers with | |
| 685 | // Value.Tag.bigint and only convert to f128 representation if it stops being an | |
| 686 | // integer. Is this something we want? need to have a lang spec discussion on this | |
| 687 | // topic. | |
| 688 | return error.SkipZigTest; // TODO | |
| 689 | } | |
| 587 | 690 | |
| 588 | 691 | try expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); |
| 589 | 692 | } |
test/behavior/math.zig+126-43| ... | ... | @@ -6,7 +6,6 @@ const expectEqualSlices = std.testing.expectEqualSlices; |
| 6 | 6 | const maxInt = std.math.maxInt; |
| 7 | 7 | const minInt = std.math.minInt; |
| 8 | 8 | const mem = std.mem; |
| 9 | const has_f80_rt = builtin.cpu.arch == .x86_64; | |
| 10 | 9 | |
| 11 | 10 | test "assignment operators" { |
| 12 | 11 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1046,12 +1045,14 @@ fn testSqrt(comptime T: type, x: T) !void { |
| 1046 | 1045 | } |
| 1047 | 1046 | |
| 1048 | 1047 | test "@fabs" { |
| 1049 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1048 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 1049 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 1050 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 1051 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1052 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1050 | 1053 | |
| 1051 | 1054 | try testFabs(f128, 12.0); |
| 1052 | 1055 | comptime try testFabs(f128, 12.0); |
| 1053 | if (has_f80_rt) try testFabs(f80, 12.0); | |
| 1054 | // comptime try testFabs(f80, 12.0); | |
| 1055 | 1056 | try testFabs(f64, 12.0); |
| 1056 | 1057 | comptime try testFabs(f64, 12.0); |
| 1057 | 1058 | try testFabs(f32, 12.0); |
| ... | ... | @@ -1065,20 +1066,25 @@ test "@fabs" { |
| 1065 | 1066 | comptime try expectEqual(x, z); |
| 1066 | 1067 | } |
| 1067 | 1068 | |
| 1069 | test "@fabs f80" { | |
| 1070 | if (true) { | |
| 1071 | // https://github.com/ziglang/zig/issues/11030 | |
| 1072 | return error.SkipZigTest; | |
| 1073 | } | |
| 1074 | ||
| 1075 | try testFabs(f80, 12.0); | |
| 1076 | comptime try testFabs(f80, 12.0); | |
| 1077 | } | |
| 1078 | ||
| 1068 | 1079 | fn testFabs(comptime T: type, x: T) !void { |
| 1069 | 1080 | const y = -x; |
| 1070 | 1081 | const z = @fabs(y); |
| 1071 | try expectEqual(x, z); | |
| 1082 | try expect(x == z); | |
| 1072 | 1083 | } |
| 1073 | 1084 | |
| 1074 | 1085 | test "@floor" { |
| 1075 | 1086 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1076 | 1087 | |
| 1077 | // FIXME: Generates a floorl function call | |
| 1078 | // testFloor(f128, 12.0); | |
| 1079 | comptime try testFloor(f128, 12.0); | |
| 1080 | // try testFloor(f80, 12.0); | |
| 1081 | comptime try testFloor(f80, 12.0); | |
| 1082 | 1088 | try testFloor(f64, 12.0); |
| 1083 | 1089 | comptime try testFloor(f64, 12.0); |
| 1084 | 1090 | try testFloor(f32, 12.0); |
| ... | ... | @@ -1089,23 +1095,39 @@ test "@floor" { |
| 1089 | 1095 | const x = 14.0; |
| 1090 | 1096 | const y = x + 0.7; |
| 1091 | 1097 | const z = @floor(y); |
| 1092 | comptime try expectEqual(x, z); | |
| 1098 | comptime try expect(x == z); | |
| 1099 | } | |
| 1100 | ||
| 1101 | test "@floor f80" { | |
| 1102 | if (true) { | |
| 1103 | // https://github.com/ziglang/zig/issues/11030 | |
| 1104 | return error.SkipZigTest; | |
| 1105 | } | |
| 1106 | try testFloor(f80, 12.0); | |
| 1107 | comptime try testFloor(f80, 12.0); | |
| 1108 | } | |
| 1109 | ||
| 1110 | test "@floor f128" { | |
| 1111 | if (builtin.zig_backend == .stage1) { | |
| 1112 | // Fails because it incorrectly lowers to a floorl function call. | |
| 1113 | return error.SkipZigTest; | |
| 1114 | } | |
| 1115 | ||
| 1116 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1117 | ||
| 1118 | testFloor(f128, 12.0); | |
| 1119 | comptime try testFloor(f128, 12.0); | |
| 1093 | 1120 | } |
| 1094 | 1121 | |
| 1095 | 1122 | fn testFloor(comptime T: type, x: T) !void { |
| 1096 | 1123 | const y = x + 0.6; |
| 1097 | 1124 | const z = @floor(y); |
| 1098 | try expectEqual(x, z); | |
| 1125 | try expect(x == z); | |
| 1099 | 1126 | } |
| 1100 | 1127 | |
| 1101 | 1128 | test "@ceil" { |
| 1102 | 1129 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1103 | 1130 | |
| 1104 | // FIXME: Generates a ceill function call | |
| 1105 | //testCeil(f128, 12.0); | |
| 1106 | comptime try testCeil(f128, 12.0); | |
| 1107 | // try testCeil(f80, 12.0); | |
| 1108 | comptime try testCeil(f80, 12.0); | |
| 1109 | 1131 | try testCeil(f64, 12.0); |
| 1110 | 1132 | comptime try testCeil(f64, 12.0); |
| 1111 | 1133 | try testCeil(f32, 12.0); |
| ... | ... | @@ -1116,29 +1138,40 @@ test "@ceil" { |
| 1116 | 1138 | const x = 14.0; |
| 1117 | 1139 | const y = x - 0.7; |
| 1118 | 1140 | const z = @ceil(y); |
| 1119 | comptime try expectEqual(x, z); | |
| 1141 | comptime try expect(x == z); | |
| 1142 | } | |
| 1143 | ||
| 1144 | test "@ceil f80" { | |
| 1145 | if (true) { | |
| 1146 | // https://github.com/ziglang/zig/issues/11030 | |
| 1147 | return error.SkipZigTest; | |
| 1148 | } | |
| 1149 | ||
| 1150 | try testCeil(f80, 12.0); | |
| 1151 | comptime try testCeil(f80, 12.0); | |
| 1152 | } | |
| 1153 | ||
| 1154 | test "@ceil f128" { | |
| 1155 | if (builtin.zig_backend == .stage1) { | |
| 1156 | // Fails because it incorrectly lowers to a ceill function call. | |
| 1157 | return error.SkipZigTest; | |
| 1158 | } | |
| 1159 | ||
| 1160 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1161 | ||
| 1162 | testCeil(f128, 12.0); | |
| 1163 | comptime try testCeil(f128, 12.0); | |
| 1120 | 1164 | } |
| 1121 | 1165 | |
| 1122 | 1166 | fn testCeil(comptime T: type, x: T) !void { |
| 1123 | 1167 | const y = x - 0.8; |
| 1124 | 1168 | const z = @ceil(y); |
| 1125 | try expectEqual(x, z); | |
| 1169 | try expect(x == z); | |
| 1126 | 1170 | } |
| 1127 | 1171 | |
| 1128 | 1172 | test "@trunc" { |
| 1129 | 1173 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1130 | 1174 | |
| 1131 | // FIXME: Generates a truncl function call | |
| 1132 | //testTrunc(f128, 12.0); | |
| 1133 | comptime try testTrunc(f128, 12.0); | |
| 1134 | // try testTrunc(f80, 12.0); | |
| 1135 | // comptime try testTrunc(f80, 12.0); | |
| 1136 | comptime { | |
| 1137 | const x: f80 = 12.0; | |
| 1138 | const y = x + 0.8; | |
| 1139 | const z = @trunc(y); | |
| 1140 | try expectEqual(x, z); | |
| 1141 | } | |
| 1142 | 1175 | try testTrunc(f64, 12.0); |
| 1143 | 1176 | comptime try testTrunc(f64, 12.0); |
| 1144 | 1177 | try testTrunc(f32, 12.0); |
| ... | ... | @@ -1149,31 +1182,54 @@ test "@trunc" { |
| 1149 | 1182 | const x = 14.0; |
| 1150 | 1183 | const y = x + 0.7; |
| 1151 | 1184 | const z = @trunc(y); |
| 1152 | comptime try expectEqual(x, z); | |
| 1185 | comptime try expect(x == z); | |
| 1186 | } | |
| 1187 | ||
| 1188 | test "@trunc f80" { | |
| 1189 | if (true) { | |
| 1190 | // https://github.com/ziglang/zig/issues/11030 | |
| 1191 | return error.SkipZigTest; | |
| 1192 | } | |
| 1193 | ||
| 1194 | try testTrunc(f80, 12.0); | |
| 1195 | comptime try testTrunc(f80, 12.0); | |
| 1196 | comptime { | |
| 1197 | const x: f80 = 12.0; | |
| 1198 | const y = x + 0.8; | |
| 1199 | const z = @trunc(y); | |
| 1200 | try expect(x == z); | |
| 1201 | } | |
| 1202 | } | |
| 1203 | ||
| 1204 | test "@trunc f128" { | |
| 1205 | if (builtin.zig_backend == .stage1) { | |
| 1206 | // Fails because it incorrectly lowers to a truncl function call. | |
| 1207 | return error.SkipZigTest; | |
| 1208 | } | |
| 1209 | ||
| 1210 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1211 | ||
| 1212 | testTrunc(f128, 12.0); | |
| 1213 | comptime try testTrunc(f128, 12.0); | |
| 1153 | 1214 | } |
| 1154 | 1215 | |
| 1155 | 1216 | fn testTrunc(comptime T: type, x: T) !void { |
| 1156 | 1217 | { |
| 1157 | 1218 | const y = x + 0.8; |
| 1158 | 1219 | const z = @trunc(y); |
| 1159 | try expectEqual(x, z); | |
| 1220 | try expect(x == z); | |
| 1160 | 1221 | } |
| 1161 | 1222 | |
| 1162 | 1223 | { |
| 1163 | 1224 | const y = -x - 0.8; |
| 1164 | 1225 | const z = @trunc(y); |
| 1165 | try expectEqual(-x, z); | |
| 1226 | try expect(-x == z); | |
| 1166 | 1227 | } |
| 1167 | 1228 | } |
| 1168 | 1229 | |
| 1169 | 1230 | test "@round" { |
| 1170 | 1231 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO |
| 1171 | 1232 | |
| 1172 | // FIXME: Generates a roundl function call | |
| 1173 | //testRound(f128, 12.0); | |
| 1174 | comptime try testRound(f128, 12.0); | |
| 1175 | // try testRound(f80, 12.0); | |
| 1176 | comptime try testRound(f80, 12.0); | |
| 1177 | 1233 | try testRound(f64, 12.0); |
| 1178 | 1234 | comptime try testRound(f64, 12.0); |
| 1179 | 1235 | try testRound(f32, 12.0); |
| ... | ... | @@ -1184,13 +1240,35 @@ test "@round" { |
| 1184 | 1240 | const x = 14.0; |
| 1185 | 1241 | const y = x + 0.4; |
| 1186 | 1242 | const z = @round(y); |
| 1187 | comptime try expectEqual(x, z); | |
| 1243 | comptime try expect(x == z); | |
| 1244 | } | |
| 1245 | ||
| 1246 | test "@round f80" { | |
| 1247 | if (true) { | |
| 1248 | // https://github.com/ziglang/zig/issues/11030 | |
| 1249 | return error.SkipZigTest; | |
| 1250 | } | |
| 1251 | ||
| 1252 | try testRound(f80, 12.0); | |
| 1253 | comptime try testRound(f80, 12.0); | |
| 1254 | } | |
| 1255 | ||
| 1256 | test "@round f128" { | |
| 1257 | if (builtin.zig_backend == .stage1) { | |
| 1258 | // Fails because it incorrectly lowers to a roundl function call. | |
| 1259 | return error.SkipZigTest; | |
| 1260 | } | |
| 1261 | ||
| 1262 | if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO | |
| 1263 | ||
| 1264 | testRound(f128, 12.0); | |
| 1265 | comptime try testRound(f128, 12.0); | |
| 1188 | 1266 | } |
| 1189 | 1267 | |
| 1190 | 1268 | fn testRound(comptime T: type, x: T) !void { |
| 1191 | 1269 | const y = x - 0.5; |
| 1192 | 1270 | const z = @round(y); |
| 1193 | try expectEqual(x, z); | |
| 1271 | try expect(x == z); | |
| 1194 | 1272 | } |
| 1195 | 1273 | |
| 1196 | 1274 | test "vector integer addition" { |
| ... | ... | @@ -1225,10 +1303,15 @@ test "NaN comparison" { |
| 1225 | 1303 | comptime try testNanEqNan(f32); |
| 1226 | 1304 | comptime try testNanEqNan(f64); |
| 1227 | 1305 | comptime try testNanEqNan(f128); |
| 1306 | } | |
| 1228 | 1307 | |
| 1229 | // TODO https://github.com/ziglang/zig/issues/11030 | |
| 1230 | // try testNanEqNan(f80); | |
| 1231 | // comptime try testNanEqNan(f80); | |
| 1308 | test "NaN comparison f80" { | |
| 1309 | if (true) { | |
| 1310 | // https://github.com/ziglang/zig/issues/11030 | |
| 1311 | return error.SkipZigTest; | |
| 1312 | } | |
| 1313 | try testNanEqNan(f80); | |
| 1314 | comptime try testNanEqNan(f80); | |
| 1232 | 1315 | } |
| 1233 | 1316 | |
| 1234 | 1317 | fn testNanEqNan(comptime F: type) !void { |