bone_sse: V4 FMA matmul, enable SSE4.1+FMA+AVX target

This commit is contained in:
MarcelineVQ
2026-03-16 10:54:25 -07:00
parent 08d1992eaf
commit 5d41cd03a3
2 changed files with 25 additions and 14 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ pub fn build(b: *std.Build) void {
.cpu_arch = .x86,
.os_tag = .windows,
.abi = .msvc,
.cpu_features_add = std.Target.x86.featureSet(&.{ .sse, .sse2 }),
.cpu_features_add = std.Target.x86.featureSet(&.{ .sse, .sse2, .sse3, .sse4_1, .fma, .avx }),
});
const bone_sse_obj = b.addObject(.{
.name = "bone_sse",
+24 -13
View File
@@ -396,20 +396,31 @@ inline fn copyMat4(dst: u32, src: u32) void {
}
/// 4x4 matrix multiply: dst = a * b (row-major). Safe for dst==a or dst==b.
/// Uses f64 intermediates for precision. Scalar — no alignment requirements.
/// Uses V4 + @mulAdd (FMA): 1 mul + 3 FMA per row = 16 SIMD ops total.
fn matMul4x4(dst: u32, a: u32, b: u32) void {
var m: [16]f64 = undefined;
inline for (0..4) |row| {
inline for (0..4) |col| {
const i = row * 4 + col;
m[i] = @as(f64, rf32(a + @as(u32, @intCast(row)) * 16)) * @as(f64, rf32(b + @as(u32, @intCast(col)) * 4)) +
@as(f64, rf32(a + @as(u32, @intCast(row)) * 16 + 4)) * @as(f64, rf32(b + @as(u32, @intCast(col)) * 4 + 16)) +
@as(f64, rf32(a + @as(u32, @intCast(row)) * 16 + 8)) * @as(f64, rf32(b + @as(u32, @intCast(col)) * 4 + 32)) +
@as(f64, rf32(a + @as(u32, @intCast(row)) * 16 + 12)) * @as(f64, rf32(b + @as(u32, @intCast(col)) * 4 + 48));
}
}
inline for (0..16) |i| {
wf32(dst + @as(u32, @intCast(i)) * 4, @floatCast(m[i]));
// Pre-load all rows of B
const b0 = V4{ rf32(b), rf32(b + 4), rf32(b + 8), rf32(b + 12) };
const b1 = V4{ rf32(b + 16), rf32(b + 20), rf32(b + 24), rf32(b + 28) };
const b2 = V4{ rf32(b + 32), rf32(b + 36), rf32(b + 40), rf32(b + 44) };
const b3 = V4{ rf32(b + 48), rf32(b + 52), rf32(b + 56), rf32(b + 60) };
// Pre-load all rows of A (in case dst aliases a)
const a0 = V4{ rf32(a), rf32(a + 4), rf32(a + 8), rf32(a + 12) };
const a1 = V4{ rf32(a + 16), rf32(a + 20), rf32(a + 24), rf32(a + 28) };
const a2 = V4{ rf32(a + 32), rf32(a + 36), rf32(a + 40), rf32(a + 44) };
const a3 = V4{ rf32(a + 48), rf32(a + 52), rf32(a + 56), rf32(a + 60) };
const rows = [4]V4{ a0, a1, a2, a3 };
// Compute: each output row = broadcast(a[row][col]) * b_row, accumulated with FMA
inline for (0..4) |i| {
const s0: V4 = @splat(rows[i][0]);
const s1: V4 = @splat(rows[i][1]);
const s2: V4 = @splat(rows[i][2]);
const s3: V4 = @splat(rows[i][3]);
const row = @mulAdd(V4, s3, b3, @mulAdd(V4, s2, b2, @mulAdd(V4, s1, b1, s0 * b0)));
const off: u32 = @intCast(i * 16);
wf32(dst + off, row[0]);
wf32(dst + off + 4, row[1]);
wf32(dst + off + 8, row[2]);
wf32(dst + off + 12, row[3]);
}
}