Commit 9766b68c47

David Rubin <daviru007@icloud.com>
2024-07-05 02:38:03
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.
1 parent f2bf6c1
Changed files (5)
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)}),
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;
 }
 
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,
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
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);