From 9766b68c475438e24885dd75cf137d51e72ccfa3 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 4 Jul 2024 17:38:03 -0700 Subject: [PATCH] riscv: un-cache the `avl` and `vtype` when returning from a function call the csrs `avl` and `vtype` are considered caller-saved so it could have changed while inside of the function. the easiest way to handle this is to just set the cached `vtype` and `avl` to null, so that the next time something needs to set it, it'll emit an instruction instead of relying on a potentially invalid setting. --- src/arch/riscv64/CodeGen.zig | 11 ++++++++++- src/arch/riscv64/Encoding.zig | 7 +++++++ src/arch/riscv64/Mir.zig | 2 ++ src/arch/riscv64/abi.zig | 2 ++ test/behavior/vector.zig | 5 +++-- 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 6e203161c2e0716106c4bcd70f5d7a793525b3a5..13713ccb84ffd61828a9340b2b6fb835f0a3caa4 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -2481,6 +2481,11 @@ fn genBinOp( .Float => .vfsubvv, else => unreachable, }, + .mul => switch (child_ty.zigTypeTag(zcu)) { + .Int => .vmulvv, + .Float => .vfmulvv, + else => unreachable, + }, else => return func.fail("TODO: genBinOp {s} Vector", .{@tagName(tag)}), }; @@ -2490,7 +2495,7 @@ fn genBinOp( 16 => .@"16", 32 => .@"32", 64 => .@"64", - else => unreachable, + else => return func.fail("TODO: genBinOp > 64 bit elements, found {d}", .{elem_size}), }, .vlmul = .m1, .vma = true, @@ -4638,6 +4643,10 @@ fn genCall( .lib => return func.fail("TODO: lib func calls", .{}), } + // reset the vector settings as they might have changed in the function + func.avl = null; + func.vtype = null; + return call_info.return_value.short; } diff --git a/src/arch/riscv64/Encoding.zig b/src/arch/riscv64/Encoding.zig index f4684fe42b00dbece57c3fea3c0f3092b999cc6c..77cd905e7ff77c21464b9022341be39758c6d264 100644 --- a/src/arch/riscv64/Encoding.zig +++ b/src/arch/riscv64/Encoding.zig @@ -288,6 +288,9 @@ pub const Mnemonic = enum { vfaddvv, vfsubvv, + vmulvv, + vfmulvv, + vadcvv, vmvvx, @@ -546,9 +549,11 @@ pub const Mnemonic = enum { .vsetvli => .{ .opcode = .OP_V, .data = .{ .f = .{ .funct3 = 0b111 } } }, .vaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPIVV } } }, .vsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPIVV } } }, + .vmulvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100101, .funct3 = .OPIVV } } }, .vfaddvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000000, .funct3 = .OPFVV } } }, .vfsubvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b000010, .funct3 = .OPFVV } } }, + .vfmulvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b100100, .funct3 = .OPFVV } } }, .vadcvv => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010000, .funct3 = .OPMVV } } }, .vmvvx => .{ .opcode = .OP_V, .data = .{ .vecmath = .{ .vm = true, .funct6 = 0b010111, .funct3 = .OPIVX } } }, @@ -710,8 +715,10 @@ pub const InstEnc = enum { .vaddvv, .vsubvv, + .vmulvv, .vfaddvv, .vfsubvv, + .vfmulvv, .vadcvv, .vmvvx, .vslidedownvx, diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig index 1478bf5d5bd4857ffe57ed9e6821c558522c8941..78da136706bea52f1799556e62e402fc3129b253 100644 --- a/src/arch/riscv64/Mir.zig +++ b/src/arch/riscv64/Mir.zig @@ -145,6 +145,8 @@ pub const Inst = struct { vfaddvv, vsubvv, vfsubvv, + vmulvv, + vfmulvv, vslidedownvx, /// A pseudo-instruction. Used for anything that isn't 1:1 with an diff --git a/src/arch/riscv64/abi.zig b/src/arch/riscv64/abi.zig index 3f5f7f6744a8a63c95fb9fb9823261c966b47f4b..baed5cc68cd6d14fd6f33f5be1d7a10f502976ba 100644 --- a/src/arch/riscv64/abi.zig +++ b/src/arch/riscv64/abi.zig @@ -200,6 +200,8 @@ pub fn classifySystem(ty: Type, pt: Zcu.PerThread) [8]SystemClass { result[0] = .integer; return result; } + // we should pass vector registers of size <= 128 through 2 integer registers + // but we haven't implemented seperating vector registers into register_pairs return memory_class; }, else => |bad_ty| std.debug.panic("classifySystem {s}", .{@tagName(bad_ty)}), diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 6a1e36e9c45b3de6efa9ca4567718f94d88aa7bd..d4b2acd6afd8985445232015c0dfa432dec187d2 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -102,7 +102,6 @@ test "vector float operators" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { @@ -119,7 +118,7 @@ test "vector float operators" { try expectEqual(v + x, .{ 11, 22, 33, 44 }); try expectEqual(v - x, .{ 9, 18, 27, 36 }); try expectEqual(v * x, .{ 10, 40, 90, 160 }); - try expectEqual(-x, .{ -1, -2, -3, -4 }); + if (builtin.zig_backend != .stage2_riscv64) try expectEqual(-x, .{ -1, -2, -3, -4 }); } }; @@ -129,6 +128,8 @@ test "vector float operators" { try S.doTheTest(f64); try comptime S.doTheTest(f64); + if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; + try S.doTheTest(f16); try comptime S.doTheTest(f16); -- 2.54.0