talking-pixel / kernel /matvec.wat
cfahlgren1's picture
cfahlgren1 HF Staff
convert talking pixel to a sveltekit app that runs pivo-1.4m tts in the browser
3ec6b9e
Raw History Blame Contribute Delete
6.17 kB
;; Generated by tools/gen_matvec_wat.mjs. y[j] = sum_i x[i] * W[i*nout + j]
(module
(import "env" "memory" (memory 1))
(func (export "matvec") (param $w i32) (param $x i32) (param $y i32) (param $nin i32) (param $nout i32)
(local $j i32) (local $i i32) (local $wp i32) (local $xp i32) (local $row i32) (local $row2 i32)
(local $x0 v128) (local $x1 v128)
(local $a0 v128) (local $a1 v128) (local $a2 v128) (local $a3 v128) (local $a4 v128) (local $a5 v128) (local $a6 v128) (local $a7 v128)
(local.set $row (i32.shl (local.get $nout) (i32.const 2)))
(local.set $row2 (i32.shl (local.get $nout) (i32.const 3)))
(local.set $j (i32.const 0))
(block $done
(loop $blocks
(br_if $done (i32.gt_u (i32.add (local.get $j) (i32.const 32)) (local.get $nout)))
(local.set $a0 (v128.const i32x4 0 0 0 0))
(local.set $a1 (v128.const i32x4 0 0 0 0))
(local.set $a2 (v128.const i32x4 0 0 0 0))
(local.set $a3 (v128.const i32x4 0 0 0 0))
(local.set $a4 (v128.const i32x4 0 0 0 0))
(local.set $a5 (v128.const i32x4 0 0 0 0))
(local.set $a6 (v128.const i32x4 0 0 0 0))
(local.set $a7 (v128.const i32x4 0 0 0 0))
(local.set $wp (i32.add (local.get $w) (i32.shl (local.get $j) (i32.const 2))))
(local.set $xp (local.get $x))
(local.set $i (i32.shr_u (local.get $nin) (i32.const 1)))
(loop $rows
(local.set $x0 (v128.load32_splat (local.get $xp)))
(local.set $x1 (v128.load32_splat offset=4 (local.get $xp)))
(local.set $a0 (f32x4.add (local.get $a0) (f32x4.mul (local.get $x0) (v128.load offset=0 (local.get $wp)))))
(local.set $a1 (f32x4.add (local.get $a1) (f32x4.mul (local.get $x0) (v128.load offset=16 (local.get $wp)))))
(local.set $a2 (f32x4.add (local.get $a2) (f32x4.mul (local.get $x0) (v128.load offset=32 (local.get $wp)))))
(local.set $a3 (f32x4.add (local.get $a3) (f32x4.mul (local.get $x0) (v128.load offset=48 (local.get $wp)))))
(local.set $a4 (f32x4.add (local.get $a4) (f32x4.mul (local.get $x0) (v128.load offset=64 (local.get $wp)))))
(local.set $a5 (f32x4.add (local.get $a5) (f32x4.mul (local.get $x0) (v128.load offset=80 (local.get $wp)))))
(local.set $a6 (f32x4.add (local.get $a6) (f32x4.mul (local.get $x0) (v128.load offset=96 (local.get $wp)))))
(local.set $a7 (f32x4.add (local.get $a7) (f32x4.mul (local.get $x0) (v128.load offset=112 (local.get $wp)))))
(local.set $a0 (f32x4.add (local.get $a0) (f32x4.mul (local.get $x1) (v128.load offset=0 (i32.add (local.get $wp) (local.get $row))))))
(local.set $a1 (f32x4.add (local.get $a1) (f32x4.mul (local.get $x1) (v128.load offset=16 (i32.add (local.get $wp) (local.get $row))))))
(local.set $a2 (f32x4.add (local.get $a2) (f32x4.mul (local.get $x1) (v128.load offset=32 (i32.add (local.get $wp) (local.get $row))))))
(local.set $a3 (f32x4.add (local.get $a3) (f32x4.mul (local.get $x1) (v128.load offset=48 (i32.add (local.get $wp) (local.get $row))))))
(local.set $a4 (f32x4.add (local.get $a4) (f32x4.mul (local.get $x1) (v128.load offset=64 (i32.add (local.get $wp) (local.get $row))))))
(local.set $a5 (f32x4.add (local.get $a5) (f32x4.mul (local.get $x1) (v128.load offset=80 (i32.add (local.get $wp) (local.get $row))))))
(local.set $a6 (f32x4.add (local.get $a6) (f32x4.mul (local.get $x1) (v128.load offset=96 (i32.add (local.get $wp) (local.get $row))))))
(local.set $a7 (f32x4.add (local.get $a7) (f32x4.mul (local.get $x1) (v128.load offset=112 (i32.add (local.get $wp) (local.get $row))))))
(local.set $wp (i32.add (local.get $wp) (local.get $row2)))
(local.set $xp (i32.add (local.get $xp) (i32.const 8)))
(local.set $i (i32.sub (local.get $i) (i32.const 1)))
(br_if $rows (local.get $i)))
(local.set $wp (i32.add (local.get $y) (i32.shl (local.get $j) (i32.const 2))))
(v128.store offset=0 (local.get $wp) (local.get $a0))
(v128.store offset=16 (local.get $wp) (local.get $a1))
(v128.store offset=32 (local.get $wp) (local.get $a2))
(v128.store offset=48 (local.get $wp) (local.get $a3))
(v128.store offset=64 (local.get $wp) (local.get $a4))
(v128.store offset=80 (local.get $wp) (local.get $a5))
(v128.store offset=96 (local.get $wp) (local.get $a6))
(v128.store offset=112 (local.get $wp) (local.get $a7))
(local.set $j (i32.add (local.get $j) (i32.const 32)))
(br $blocks)))
(block $done4
(loop $blocks4
(br_if $done4 (i32.ge_u (local.get $j) (local.get $nout)))
(local.set $a0 (v128.const i32x4 0 0 0 0))
(local.set $wp (i32.add (local.get $w) (i32.shl (local.get $j) (i32.const 2))))
(local.set $xp (local.get $x))
(local.set $i (local.get $nin))
(loop $rows4
(local.set $a0 (f32x4.add (local.get $a0)
(f32x4.mul (v128.load32_splat (local.get $xp)) (v128.load (local.get $wp)))))
(local.set $wp (i32.add (local.get $wp) (local.get $row)))
(local.set $xp (i32.add (local.get $xp) (i32.const 4)))
(local.set $i (i32.sub (local.get $i) (i32.const 1)))
(br_if $rows4 (local.get $i)))
(v128.store (i32.add (local.get $y) (i32.shl (local.get $j) (i32.const 2))) (local.get $a0))
(local.set $j (i32.add (local.get $j) (i32.const 4)))
(br $blocks4)))
)
;; Y[m, nout] = X[m, nin] @ W: one matvec per row (weights stay hot in cache).
(func (export "gemm") (param $w i32) (param $x i32) (param $y i32) (param $m i32) (param $nin i32) (param $nout i32)
(block $done
(loop $rows
(br_if $done (i32.eqz (local.get $m)))
(call 0 (local.get $w) (local.get $x) (local.get $y) (local.get $nin) (local.get $nout))
(local.set $x (i32.add (local.get $x) (i32.shl (local.get $nin) (i32.const 2))))
(local.set $y (i32.add (local.get $y) (i32.shl (local.get $nout) (i32.const 2))))
(local.set $m (i32.sub (local.get $m) (i32.const 1)))
(br $rows)))
)
)