authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-02 02:41:14-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-07-14 23:02:35-07:00
log5a2c547fc1eedcec52e9e7259449d9a093e21ab1
tree31d0e7a34098171e408ab7d38c77bddfef959cf4
parent09e9812086073d9e8ebfe6f61c227f1ab5859f40
signaturelock-open Commit is signed but in an unrecognized format.

riscv: vectors part 3


10 files changed, 193 insertions(+), 148 deletions(-)

lib/std/start.zig+20-1
......@@ -221,7 +221,26 @@ fn riscv_start() callconv(.C) noreturn {
221221 }
222222 break :ret root.main();
223223 },
224 else => @compileError("expected return type of main to be 'void', 'noreturn', 'u8'"),
224 .ErrorUnion => ret: {
225 const result = root.main() catch {
226 const stderr = std.io.getStdErr().writer();
227 stderr.writeAll("failed with error\n") catch {
228 @panic("failed to print when main returned error");
229 };
230 break :ret 1;
231 };
232 switch (@typeInfo(@TypeOf(result))) {
233 .Void => break :ret 0,
234 .Int => |info| {
235 if (info.bits != 8 or info.signedness == .signed) {
236 @compileError(bad_main_ret);
237 }
238 return result;
239 },
240 else => @compileError(bad_main_ret),
241 }
242 },
243 else => @compileError(bad_main_ret),
225244 });
226245}
227246
src/arch/riscv64/CodeGen.zig+131-116
......@@ -88,8 +88,9 @@ exitlude_jump_relocs: std.ArrayListUnmanaged(usize) = .{},
8888/// across each runtime branch upon joining.
8989branch_stack: *std.ArrayList(Branch),
9090
91// The current bit length of vector registers.
92vec_len: u32,
91// Currently set vector properties, null means they haven't been set yet in the function.
92avl: ?u64,
93vtype: ?bits.VType,
9394
9495// Key is the block instruction
9596blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .{},
......@@ -751,7 +752,8 @@ pub fn generate(
751752 .end_di_line = func.rbrace_line,
752753 .end_di_column = func.rbrace_column,
753754 .scope_generation = 0,
754 .vec_len = 16 * 8, // TODO: set this per cpu
755 .avl = null,
756 .vtype = null,
755757 };
756758 defer {
757759 function.frame_allocs.deinit(gpa);
......@@ -1064,8 +1066,17 @@ fn getCsr(func: *Func, csr: CSR) !Register {
10641066 return dst_reg;
10651067}
10661068
1067fn setVl(func: *Func, dst_reg: Register, avl: u5, options: bits.VType) !void {
1069fn setVl(func: *Func, dst_reg: Register, avl: u64, options: bits.VType) !void {
1070 if (func.avl == avl) if (func.vtype) |vtype| {
1071 // it's already set, we don't need to do anything
1072 if (@as(u8, @bitCast(vtype)) == @as(u8, @bitCast(options))) return;
1073 };
1074
1075 func.avl = avl;
1076 func.vtype = options;
1077
10681078 if (avl == 0) {
1079 // the caller means to do "vsetvli zero, zero ..." which keeps the avl to whatever it was before
10691080 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));
10701081 _ = try func.addInst(.{
10711082 .tag = .vsetvli,
......@@ -1077,18 +1088,33 @@ fn setVl(func: *Func, dst_reg: Register, avl: u5, options: bits.VType) !void {
10771088 } },
10781089 });
10791090 } else {
1080 const options_int: u12 = (~@as(u12, 0) << 10) | @as(u8, @bitCast(options));
1081 _ = try func.addInst(.{
1082 .tag = .vsetivli,
1083 .ops = .rri,
1084 .data = .{
1085 .i_type = .{
1091 // if the avl can fit into u5 we can use vsetivli otherwise use vsetvli
1092 if (avl <= std.math.maxInt(u5)) {
1093 const options_int: u12 = (~@as(u12, 0) << 10) | @as(u8, @bitCast(options));
1094 _ = try func.addInst(.{
1095 .tag = .vsetivli,
1096 .ops = .rri,
1097 .data = .{
1098 .i_type = .{
1099 .rd = dst_reg,
1100 .rs1 = @enumFromInt(avl),
1101 .imm12 = Immediate.u(options_int),
1102 },
1103 },
1104 });
1105 } else {
1106 const options_int: u12 = @as(u12, 0) | @as(u8, @bitCast(options));
1107 const temp_reg = try func.copyToTmpRegister(Type.usize, .{ .immediate = avl });
1108 _ = try func.addInst(.{
1109 .tag = .vsetvli,
1110 .ops = .rri,
1111 .data = .{ .i_type = .{
10861112 .rd = dst_reg,
1087 .rs1 = @enumFromInt(avl),
1113 .rs1 = temp_reg,
10881114 .imm12 = Immediate.u(options_int),
1089 },
1090 },
1091 });
1115 } },
1116 });
1117 }
10921118 }
10931119}
10941120
......@@ -1939,7 +1965,7 @@ fn allocRegOrMem(func: *Func, elem_ty: Type, inst: ?Air.Inst.Index, reg_ok: bool
19391965 const bit_size = elem_ty.bitSize(pt);
19401966 const min_size: u64 = switch (elem_ty.zigTypeTag(pt.zcu)) {
19411967 .Float => if (func.hasFeature(.d)) 64 else 32,
1942 .Vector => func.vec_len,
1968 .Vector => 256, // TODO: calculate it from avl * vsew
19431969 else => 64,
19441970 };
19451971
......@@ -2293,7 +2319,11 @@ fn binOp(
22932319 return func.fail("binOp libcall runtime-float ops", .{});
22942320 }
22952321
2296 if (lhs_ty.bitSize(pt) > 64) return func.fail("TODO: binOp >= 64 bits", .{});
2322 // don't have support for certain sizes of addition
2323 switch (lhs_ty.zigTypeTag(pt.zcu)) {
2324 .Vector => {}, // works differently and fails in a different place
2325 else => if (lhs_ty.bitSize(pt) > 64) return func.fail("TODO: binOp >= 64 bits", .{}),
2326 }
22972327
22982328 const lhs_mcv = try func.resolveInst(lhs_air);
22992329 const rhs_mcv = try func.resolveInst(rhs_air);
......@@ -2442,17 +2472,25 @@ fn genBinOp(
24422472 });
24432473 },
24442474 .Vector => {
2475 const num_elem = lhs_ty.vectorLen(zcu);
2476 const elem_size = lhs_ty.childType(zcu).bitSize(pt);
2477
2478 const child_ty = lhs_ty.childType(zcu);
2479
24452480 const mir_tag: Mir.Inst.Tag = switch (tag) {
2446 .add => .vaddvv,
2447 .sub => .vsubvv,
2481 .add => switch (child_ty.zigTypeTag(zcu)) {
2482 .Int => .vaddvv,
2483 .Float => .vfaddvv,
2484 else => unreachable,
2485 },
2486 .sub => switch (child_ty.zigTypeTag(zcu)) {
2487 .Int => .vsubvv,
2488 .Float => .vfsubvv,
2489 else => unreachable,
2490 },
24482491 else => return func.fail("TODO: genBinOp {s} Vector", .{@tagName(tag)}),
24492492 };
24502493
2451 const num_elem: u5 = math.cast(u5, lhs_ty.vectorLen(zcu)) orelse {
2452 return func.fail("TODO: genBinOp use vsetvli for larger avl sizes", .{});
2453 };
2454 const elem_size = lhs_ty.childType(zcu).bitSize(pt);
2455
24562494 try func.setVl(.zero, num_elem, .{
24572495 .vsew = switch (elem_size) {
24582496 8 => .@"8",
......@@ -2761,78 +2799,55 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void {
27612799 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
27622800
27632801 const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: {
2764 const lhs_ty = func.typeOf(extra.lhs);
2765
2766 const int_info = lhs_ty.intInfo(zcu);
2767
2768 const tuple_ty = func.typeOfIndex(inst);
2769 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
2770 const offset = result_mcv.load_frame;
2802 const ty = func.typeOf(extra.lhs);
2803 switch (ty.zigTypeTag(zcu)) {
2804 .Vector => return func.fail("TODO implement add with overflow for Vector type", .{}),
2805 .Int => {
2806 const int_info = ty.intInfo(zcu);
27712807
2772 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2773 const add_result = try func.binOp(null, .add, extra.lhs, extra.rhs);
2774 const add_result_reg = try func.copyToTmpRegister(lhs_ty, add_result);
2775 const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg);
2776 defer func.register_manager.unlockReg(add_result_reg_lock);
2808 const tuple_ty = func.typeOfIndex(inst);
2809 const result_mcv = try func.allocRegOrMem(tuple_ty, inst, false);
2810 const offset = result_mcv.load_frame;
27772811
2778 const shift_amount: u6 = @intCast(Type.usize.bitSize(pt) - int_info.bits);
2812 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
2813 const add_result = try func.binOp(null, .add, extra.lhs, extra.rhs);
27792814
2780 const shift_reg, const shift_lock = try func.allocReg(.int);
2781 defer func.register_manager.unlockReg(shift_lock);
2815 const add_result_reg = try func.copyToTmpRegister(ty, add_result);
2816 const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg);
2817 defer func.register_manager.unlockReg(add_result_reg_lock);
27822818
2783 _ = try func.addInst(.{
2784 .tag = .slli,
2785 .ops = .rri,
2786 .data = .{
2787 .i_type = .{
2788 .rd = shift_reg,
2789 .rs1 = add_result_reg,
2790 .imm12 = Immediate.u(shift_amount),
2791 },
2792 },
2793 });
2794
2795 _ = try func.addInst(.{
2796 .tag = if (int_info.signedness == .unsigned) .srli else .srai,
2797 .ops = .rri,
2798 .data = .{
2799 .i_type = .{
2800 .rd = shift_reg,
2801 .rs1 = shift_reg,
2802 .imm12 = Immediate.u(shift_amount),
2803 },
2804 },
2805 });
2806
2807 try func.genSetMem(
2808 .{ .frame = offset.index },
2809 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, pt))),
2810 lhs_ty,
2811 add_result,
2812 );
2819 try func.genSetMem(
2820 .{ .frame = offset.index },
2821 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, pt))),
2822 ty,
2823 add_result,
2824 );
28132825
2814 const overflow_reg, const overflow_lock = try func.allocReg(.int);
2815 defer func.register_manager.unlockReg(overflow_lock);
2826 const overflow_reg, const overflow_lock = try func.allocReg(.int);
2827 defer func.register_manager.unlockReg(overflow_lock);
28162828
2817 try func.genBinOp(
2818 .cmp_neq,
2819 .{ .register = shift_reg },
2820 lhs_ty,
2821 .{ .register = add_result_reg },
2822 lhs_ty,
2823 overflow_reg,
2824 );
2829 try func.genBinOp(
2830 .cmp_neq,
2831 .{ .register = add_result_reg },
2832 ty,
2833 .{ .register = add_result_reg },
2834 ty,
2835 overflow_reg,
2836 );
28252837
2826 try func.genSetMem(
2827 .{ .frame = offset.index },
2828 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, pt))),
2829 Type.u1,
2830 .{ .register = overflow_reg },
2831 );
2838 try func.genSetMem(
2839 .{ .frame = offset.index },
2840 offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(1, pt))),
2841 Type.u1,
2842 .{ .register = overflow_reg },
2843 );
28322844
2833 break :result result_mcv;
2834 } else {
2835 return func.fail("TODO: less than 8 bit or non-pow 2 addition", .{});
2845 break :result result_mcv;
2846 } else {
2847 return func.fail("TODO: less than 8 bit or non-pow 2 addition", .{});
2848 }
2849 },
2850 else => unreachable,
28362851 }
28372852 };
28382853
......@@ -5519,8 +5534,6 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
55195534 const inputs: []const Air.Inst.Ref = @ptrCast(func.air.extra[extra_i..][0..extra.data.inputs_len]);
55205535 extra_i += inputs.len;
55215536
5522 log.debug("airAsm input: {any}", .{inputs});
5523
55245537 const dead = !is_volatile and func.liveness.isUnused(inst);
55255538 const result: MCValue = if (dead) .unreach else result: {
55265539 if (outputs.len > 1) {
......@@ -5897,7 +5910,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
58975910 const max_size: u32 = switch (reg.class()) {
58985911 .int => 64,
58995912 .float => if (func.hasFeature(.d)) 64 else 32,
5900 .vector => func.vec_len,
5913 .vector => 64, // TODO: calculate it from avl * vsew
59015914 };
59025915 if (abi_size > max_size) return std.debug.panic("tried to set reg with size {}", .{abi_size});
59035916 const dst_reg_class = reg.class();
......@@ -6033,6 +6046,8 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
60336046 .register_pair => return func.fail("genSetReg should we allow reg -> reg_pair?", .{}),
60346047 .load_frame => |frame| {
60356048 if (reg.class() == .vector) {
6049 // vectors don't support an offset memory load so we need to put the true
6050 // address into a register before loading from it.
60366051 const addr_reg, const addr_lock = try func.allocReg(.int);
60376052 defer func.register_manager.unlockReg(addr_lock);
60386053
......@@ -6073,28 +6088,30 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
60736088 _ = try func.addInst(.{
60746089 .tag = .pseudo,
60756090 .ops = .pseudo_lea_rm,
6076 .data = .{ .rm = .{
6077 .r = reg,
6078 .m = switch (src_mcv) {
6079 .register_offset => |reg_off| .{
6080 .base = .{ .reg = reg_off.reg },
6081 .mod = .{
6082 .size = func.memSize(ty),
6083 .disp = reg_off.off,
6084 .unsigned = false,
6091 .data = .{
6092 .rm = .{
6093 .r = reg,
6094 .m = switch (src_mcv) {
6095 .register_offset => |reg_off| .{
6096 .base = .{ .reg = reg_off.reg },
6097 .mod = .{
6098 .size = .byte, // the size doesn't matter
6099 .disp = reg_off.off,
6100 .unsigned = false,
6101 },
60856102 },
6086 },
6087 .lea_frame => |frame| .{
6088 .base = .{ .frame = frame.index },
6089 .mod = .{
6090 .size = func.memSize(ty),
6091 .disp = frame.off,
6092 .unsigned = false,
6103 .lea_frame => |frame| .{
6104 .base = .{ .frame = frame.index },
6105 .mod = .{
6106 .size = .byte, // the size doesn't matter
6107 .disp = frame.off,
6108 .unsigned = false,
6109 },
60936110 },
6111 else => unreachable,
60946112 },
6095 else => unreachable,
60966113 },
6097 } },
6114 },
60986115 });
60996116 },
61006117 .indirect => |reg_off| {
......@@ -6119,9 +6136,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError!
61196136 // There is no vector instruction for loading with an offset to a base register,
61206137 // so we need to get an offset register containing the address of the vector first
61216138 // and load from it.
6122 const len: u5 = math.cast(u5, ty.vectorLen(zcu)) orelse {
6123 return func.fail("TODO: genSetReg load_frame -> vec reg, vector length doesn't fit into imm avl", .{});
6124 };
6139 const len = ty.vectorLen(zcu);
61256140 const elem_ty = ty.childType(zcu);
61266141 const elem_size = elem_ty.abiSize(pt);
61276142
......@@ -6202,6 +6217,8 @@ fn genSetMem(
62026217 src_mcv: MCValue,
62036218) InnerError!void {
62046219 const pt = func.pt;
6220 const zcu = pt.zcu;
6221
62056222 const abi_size: u32 = @intCast(ty.abiSize(pt));
62066223 const dst_ptr_mcv: MCValue = switch (base) {
62076224 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
......@@ -6252,10 +6269,8 @@ fn genSetMem(
62526269 if (reg.class() == .vector) {
62536270 const addr_reg = try func.copyToTmpRegister(Type.usize, dst_ptr_mcv);
62546271
6255 const num_elem: u5 = math.cast(u5, ty.vectorLen(pt.zcu)) orelse {
6256 return func.fail("TODO: genBinOp use vsetvli for larger avl sizes", .{});
6257 };
6258 const elem_size = ty.childType(pt.zcu).bitSize(pt);
6272 const num_elem = ty.vectorLen(zcu);
6273 const elem_size = ty.childType(zcu).bitSize(pt);
62596274
62606275 try func.setVl(.zero, num_elem, .{
62616276 .vsew = switch (elem_size) {
......@@ -6279,7 +6294,7 @@ fn genSetMem(
62796294 .base = .{ .reg = addr_reg },
62806295 .mod = .{
62816296 .disp = 0,
6282 .size = func.memSize(ty.childType(pt.zcu)),
6297 .size = func.memSize(ty.childType(zcu)),
62836298 .unsigned = false,
62846299 },
62856300 },
src/arch/riscv64/Encoding.zig+10
......@@ -285,6 +285,9 @@ pub const Mnemonic = enum {
285285 vaddvv,
286286 vsubvv,
287287
288 vfaddvv,
289 vfsubvv,
290
288291 vadcvv,
289292
290293 vmvvx,
......@@ -316,6 +319,8 @@ pub const Mnemonic = enum {
316319 amomaxud,
317320 amominud,
318321
322 // TODO: Q extension
323
319324 pub fn encoding(mnem: Mnemonic) Enc {
320325 return switch (mnem) {
321326 // zig fmt: off
......@@ -542,6 +547,9 @@ pub const Mnemonic = enum {
542547 .vaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } },
543548 .vsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } },
544549
550 .vfaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPFVV } } },
551 .vfsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPFVV } } },
552
545553 .vadcvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } },
546554 .vmvvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010111, .funct3 = .OPIVX } } },
547555
......@@ -702,6 +710,8 @@ pub const InstEnc = enum {
702710
703711 .vaddvv,
704712 .vsubvv,
713 .vfaddvv,
714 .vfsubvv,
705715 .vadcvv,
706716 .vmvvx,
707717 .vslidedownvx,
src/arch/riscv64/Mir.zig+2-3
......@@ -142,12 +142,11 @@ pub const Inst = struct {
142142 vsetivli,
143143 vsetvl,
144144 vaddvv,
145 vfaddvv,
145146 vsubvv,
147 vfsubvv,
146148 vslidedownvx,
147149
148 // A Extension Instructions
149 amo,
150
151150 /// A pseudo-instruction. Used for anything that isn't 1:1 with an
152151 /// assembly instruction.
153152 pseudo,
src/arch/riscv64/bits.zig+2-2
......@@ -41,7 +41,7 @@ pub const Memory = struct {
4141 2...2 => .hword,
4242 3...4 => .word,
4343 5...8 => .dword,
44 else => unreachable,
44 else => std.debug.panic("fromByteSize {}", .{size}),
4545 };
4646 }
4747
......@@ -221,7 +221,7 @@ pub const Register = enum(u8) {
221221 // zig fmt: off
222222 @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => 64,
223223 @intFromEnum(Register.ft0) ... @intFromEnum(Register.f31) => if (Target.riscv.featureSetHas(features, .d)) 64 else 32,
224 @intFromEnum(Register.v0) ... @intFromEnum(Register.v31) => 1024, // TODO: look at suggestVectorSize
224 @intFromEnum(Register.v0) ... @intFromEnum(Register.v31) => 256, // TODO: look at suggestVectorSize
225225 else => unreachable,
226226 // zig fmt: on
227227 };
test/behavior/byteswap.zig-1
......@@ -100,7 +100,6 @@ test "@byteSwap vectors u8" {
100100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
101101 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
102102 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
103 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
104103
105104 try comptime vector8();
106105 try vector8();
test/behavior/cast.zig-1
......@@ -1985,7 +1985,6 @@ test "peer type resolution: vector and array and tuple" {
19851985 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
19861986 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
19871987 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1988 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
19891988
19901989 var vec: @Vector(2, i8) = .{ 10, 20 };
19911990 var arr: [2]i8 = .{ 30, 40 };
test/behavior/globals.zig-1
......@@ -18,7 +18,6 @@ test "store to global vector" {
1818 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
1919 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2020 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
2221
2322 try expect(vpos[1] == 0.0);
2423 vpos = @Vector(2, f32){ 0.0, 1.0 };
test/behavior/sizeof_and_typeof.zig-2
......@@ -19,8 +19,6 @@ test "@sizeOf on compile-time types" {
1919}
2020
2121test "@TypeOf() with multiple arguments" {
22 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
23
2422 {
2523 var var_1: u32 = undefined;
2624 var var_2: u8 = undefined;
test/behavior/vector.zig+28-21
......@@ -97,7 +97,6 @@ test "vector int operators" {
9797
9898test "vector float operators" {
9999 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
101100 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
102101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103102 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -105,21 +104,34 @@ test "vector float operators" {
105104 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
106105 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
107106
108 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
109 const S = struct {
110 fn doTheTest() !void {
111 var v: @Vector(4, T) = [4]T{ 10, 20, 30, 40 };
112 var x: @Vector(4, T) = [4]T{ 1, 2, 3, 4 };
113 _ = .{ &v, &x };
114 try expect(mem.eql(T, &@as([4]T, v + x), &[4]T{ 11, 22, 33, 44 }));
115 try expect(mem.eql(T, &@as([4]T, v - x), &[4]T{ 9, 18, 27, 36 }));
116 try expect(mem.eql(T, &@as([4]T, v * x), &[4]T{ 10, 40, 90, 160 }));
117 try expect(mem.eql(T, &@as([4]T, -x), &[4]T{ -1, -2, -3, -4 }));
118 }
119 };
120 try S.doTheTest();
121 try comptime S.doTheTest();
122 }
107 const S = struct {
108 fn doTheTest(T: type) !void {
109 var v: @Vector(4, T) = .{ 10, 20, 30, 40 };
110 var x: @Vector(4, T) = .{ 1, 2, 3, 4 };
111 _ = .{ &v, &x };
112 try expectEqual(v + x, .{ 11, 22, 33, 44 });
113 try expectEqual(v - x, .{ 9, 18, 27, 36 });
114 try expectEqual(v * x, .{ 10, 40, 90, 160 });
115 try expectEqual(-x, .{ -1, -2, -3, -4 });
116 }
117 };
118
119 try S.doTheTest(f32);
120 try comptime S.doTheTest(f32);
121
122 try S.doTheTest(f64);
123 try comptime S.doTheTest(f64);
124
125 try S.doTheTest(f16);
126 try comptime S.doTheTest(f16);
127
128 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
129
130 try S.doTheTest(f80);
131 try comptime S.doTheTest(f80);
132
133 try S.doTheTest(f128);
134 try comptime S.doTheTest(f128);
123135}
124136
125137test "vector bit operators" {
......@@ -1228,7 +1240,6 @@ test "loading the second vector from a slice of vectors" {
12281240 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12291241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12301242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1231 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12321243
12331244 @setRuntimeSafety(false);
12341245 var small_bases = [2]@Vector(2, u8){
......@@ -1245,7 +1256,6 @@ test "array of vectors is copied" {
12451256 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12461257 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12471258 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1248 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
12491259
12501260 const Vec3 = @Vector(3, i32);
12511261 var points = [_]Vec3{
......@@ -1316,7 +1326,6 @@ test "zero multiplicand" {
13161326 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13171327 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13181328 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1319 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
13201329
13211330 const zeros = @Vector(2, u32){ 0.0, 0.0 };
13221331 var ones = @Vector(2, u32){ 1.0, 1.0 };
......@@ -1411,7 +1420,6 @@ test "store to vector in slice" {
14111420 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14121421 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14131422 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
1414 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14151423
14161424 var v = [_]@Vector(3, f32){
14171425 .{ 1, 1, 1 },
......@@ -1478,7 +1486,6 @@ test "store vector with memset" {
14781486test "addition of vectors represented as strings" {
14791487 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14801488 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1481 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
14821489
14831490 const V = @Vector(3, u8);
14841491 const foo: V = "foo".*;