char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Taimur Ahmadggml-cpu: fix RVV checks in quants and repacking (#20682)054d8b0f2

char/aliceai-t5-moe
95.6 KiB1703 linesraw
1#define GGML_COMMON_IMPL_CPP
2#define GGML_COMMON_DECL_CPP
3#include "ggml-common.h"
4#include "ggml-backend-impl.h"
5
6#include "ggml-impl.h"
7#include "ggml-cpu.h"
8#include "ggml-cpu-impl.h"
9#include "simd-mappings.h"
10#include "traits.h"
11
12#include <cmath>
13#include <cstring>
14#include <cassert>
15#include <cstdlib> // for qsort
16#include <cstdio>  // for GGML_ASSERT
17
18#define GGML_CPU_CLANG_WORKAROUND
19#include "../../repack.h"
20
21#if defined(__GNUC__)
22#pragma GCC diagnostic ignored "-Woverlength-strings"
23#endif
24
25#define UNUSED GGML_UNUSED
26
27void ggml_quantize_mat_q8_0_4x8(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) {
28    assert(QK8_0 == 32);
29    assert(k % QK8_0 == 0);
30    const int nb = k / QK8_0;
31
32#if defined(__riscv_v_intrinsic)
33    block_q8_0x4 * GGML_RESTRICT y = (block_q8_0x4 *) vy;
34    const size_t vl_calc = __riscv_vsetvl_e32m8(QK8_0);
35    const size_t vl_save = __riscv_vsetvl_e64m2(4);
36    vfloat32m1_t v_scalar_zero = __riscv_vfmv_s_f_f32m1(0.0f, __riscv_vsetvl_e32m1(1));
37
38    for (int i = 0; i < nb; i++) {
39        const float *x_block_base = x + i * QK8_0;
40        vint8m2_t q_r0, q_r1, q_r2, q_r3;
41        {
42            vfloat32m8_t v_src = __riscv_vle32_v_f32m8(x_block_base + 0 * k, vl_calc);
43            vfloat32m8_t v_abs = __riscv_vfabs_v_f32m8(v_src, vl_calc);
44            vfloat32m1_t v_max = __riscv_vfredmax_vs_f32m8_f32m1(v_abs, v_scalar_zero, vl_calc);
45            float amax = __riscv_vfmv_f_s_f32m1_f32(v_max);
46
47            float d = amax / 127.0f;
48            y[i].d[0] = GGML_CPU_FP32_TO_FP16(d);
49
50            float id = d ? 1.0f / d : 0.0f;
51            vfloat32m8_t v_scaled = __riscv_vfmul_vf_f32m8(v_src, id, vl_calc);
52            vint16m4_t v_i16 = __riscv_vfncvt_x_f_w_i16m4_rm(v_scaled, 4, vl_calc);
53            q_r0 = __riscv_vncvt_x_x_w_i8m2(v_i16, vl_calc);
54        }
55        asm volatile ("" ::: "memory");
56
57        {
58            vfloat32m8_t v_src = __riscv_vle32_v_f32m8(x_block_base + 1 * k, vl_calc);
59            vfloat32m8_t v_abs = __riscv_vfabs_v_f32m8(v_src, vl_calc);
60            vfloat32m1_t v_max = __riscv_vfredmax_vs_f32m8_f32m1(v_abs, v_scalar_zero, vl_calc);
61            float amax = __riscv_vfmv_f_s_f32m1_f32(v_max);
62
63            float d = amax / 127.0f;
64            y[i].d[1] = GGML_CPU_FP32_TO_FP16(d);
65            float id = d ? 1.0f / d : 0.0f;
66
67            vfloat32m8_t v_scaled = __riscv_vfmul_vf_f32m8(v_src, id, vl_calc);
68            vint16m4_t v_i16 = __riscv_vfncvt_x_f_w_i16m4_rm(v_scaled, 4, vl_calc);
69            q_r1 = __riscv_vncvt_x_x_w_i8m2(v_i16, vl_calc);
70        }
71        asm volatile ("" ::: "memory");
72        {
73            vfloat32m8_t v_src = __riscv_vle32_v_f32m8(x_block_base + 2 * k, vl_calc);
74            vfloat32m8_t v_abs = __riscv_vfabs_v_f32m8(v_src, vl_calc);
75            vfloat32m1_t v_max = __riscv_vfredmax_vs_f32m8_f32m1(v_abs, v_scalar_zero, vl_calc);
76            float amax = __riscv_vfmv_f_s_f32m1_f32(v_max);
77
78            float d = amax / 127.0f;
79            y[i].d[2] = GGML_CPU_FP32_TO_FP16(d);
80            float id = d ? 1.0f / d : 0.0f;
81
82            vfloat32m8_t v_scaled = __riscv_vfmul_vf_f32m8(v_src, id, vl_calc);
83            vint16m4_t v_i16 = __riscv_vfncvt_x_f_w_i16m4_rm(v_scaled, 4, vl_calc);
84            q_r2 = __riscv_vncvt_x_x_w_i8m2(v_i16, vl_calc);
85        }
86        asm volatile ("" ::: "memory");
87        {
88            vfloat32m8_t v_src = __riscv_vle32_v_f32m8(x_block_base + 3 * k, vl_calc);
89            vfloat32m8_t v_abs = __riscv_vfabs_v_f32m8(v_src, vl_calc);
90            vfloat32m1_t v_max = __riscv_vfredmax_vs_f32m8_f32m1(v_abs, v_scalar_zero, vl_calc);
91            float amax = __riscv_vfmv_f_s_f32m1_f32(v_max);
92
93            float d = amax / 127.0f;
94            y[i].d[3] = GGML_CPU_FP32_TO_FP16(d);
95            float id = d ? 1.0f / d : 0.0f;
96
97            vfloat32m8_t v_scaled = __riscv_vfmul_vf_f32m8(v_src, id, vl_calc);
98            vint16m4_t v_i16 = __riscv_vfncvt_x_f_w_i16m4_rm(v_scaled, 4, vl_calc);
99            q_r3 = __riscv_vncvt_x_x_w_i8m2(v_i16, vl_calc);
100        }
101        vint64m2_t v_q64_r0 = __riscv_vreinterpret_v_i8m2_i64m2(q_r0);
102        vint64m2_t v_q64_r1 = __riscv_vreinterpret_v_i8m2_i64m2(q_r1);
103        vint64m2_t v_q64_r2 = __riscv_vreinterpret_v_i8m2_i64m2(q_r2);
104        vint64m2_t v_q64_r3 = __riscv_vreinterpret_v_i8m2_i64m2(q_r3);
105        vint64m2x4_t v_quant_tuple = __riscv_vcreate_v_i64m2x4(v_q64_r0, v_q64_r1, v_q64_r2, v_q64_r3);
106        __riscv_vsseg4e64_v_i64m2x4((int64_t*)y[i].qs, v_quant_tuple, vl_save);
107    }
108#else
109    UNUSED(nb);
110    ggml_quantize_mat_q8_0_4x8_generic(x, vy, k);
111#endif
112}
113
114void ggml_gemv_q4_0_8x8_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
115    const int qk = QK8_0;
116    const int nb = n / qk;
117    const int ncols_interleaved = 8;
118    const int blocklen = 8;
119
120    assert (n % qk == 0);
121    assert (nc % ncols_interleaved == 0);
122
123    UNUSED(s);
124    UNUSED(bs);
125    UNUSED(vx);
126    UNUSED(vy);
127    UNUSED(nr);
128    UNUSED(nc);
129    UNUSED(nb);
130    UNUSED(ncols_interleaved);
131    UNUSED(blocklen);
132
133#if defined __riscv_v
134    if (__riscv_vlenb() >= QK4_0) {
135        const size_t vl = QK4_0;
136
137        const block_q8_0 * a_ptr = (const block_q8_0 *) vy;
138        for (int x = 0; x < nc / ncols_interleaved; x++) {
139            const block_q4_0x8 * b_ptr = (const block_q4_0x8 *) vx + (x * nb);
140
141            vfloat32m1_t sumf = __riscv_vfmv_v_f_f32m1(0.0, vl / 4);
142            for (int l = 0; l < nb; l++) {
143                const int64_t a0 = *(const int64_t *)&a_ptr[l].qs[0];
144                const int64_t a1 = *(const int64_t *)&a_ptr[l].qs[8];
145                const int64_t a2 = *(const int64_t *)&a_ptr[l].qs[16];
146                const int64_t a3 = *(const int64_t *)&a_ptr[l].qs[24];
147                __asm__ __volatile__("" ::: "memory"); // prevent gcc from emitting fused vlse64, violating alignment constraints
148                const vint8m2_t lhs_0_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(a0, vl / 4));
149                const vint8m2_t lhs_1_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(a1, vl / 4));
150                const vint8m2_t lhs_2_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(a2, vl / 4));
151                const vint8m2_t lhs_3_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(a3, vl / 4));
152
153                const vint8m4_t rhs_raw_vec = __riscv_vle8_v_i8m4((const int8_t *)b_ptr[l].qs, vl * 4);
154                const vint8m4_t rhs_vec_lo = __riscv_vsra_vx_i8m4(__riscv_vsll_vx_i8m4(rhs_raw_vec, 4, vl * 4), 4, vl * 4);
155                const vint8m4_t rhs_vec_hi = __riscv_vsra_vx_i8m4(rhs_raw_vec, 4, vl * 4);
156                const vint8m2_t rhs_vec_lo_0 = __riscv_vget_v_i8m4_i8m2(rhs_vec_lo, 0);
157                const vint8m2_t rhs_vec_lo_1 = __riscv_vget_v_i8m4_i8m2(rhs_vec_lo, 1);
158                const vint8m2_t rhs_vec_hi_0 = __riscv_vget_v_i8m4_i8m2(rhs_vec_hi, 0);
159                const vint8m2_t rhs_vec_hi_1 = __riscv_vget_v_i8m4_i8m2(rhs_vec_hi, 1);
160
161                const vint16m4_t sumi_lo_0 = __riscv_vwmul_vv_i16m4(rhs_vec_lo_0, lhs_0_8, vl * 2);
162                const vint16m4_t sumi_lo_1 = __riscv_vwmacc_vv_i16m4(sumi_lo_0, rhs_vec_lo_1, lhs_1_8, vl * 2);
163                const vint16m4_t sumi_hi_0 = __riscv_vwmacc_vv_i16m4(sumi_lo_1, rhs_vec_hi_0, lhs_2_8, vl * 2);
164                const vint16m4_t sumi_hi_m = __riscv_vwmacc_vv_i16m4(sumi_hi_0, rhs_vec_hi_1, lhs_3_8, vl * 2);
165
166                const vuint32m4_t sumi_i32 = __riscv_vreinterpret_v_i32m4_u32m4(__riscv_vreinterpret_v_i16m4_i32m4(sumi_hi_m));
167                const vuint16m2_t sumi_h2_0 = __riscv_vnsrl_wx_u16m2(sumi_i32, 0, vl);
168                const vuint16m2_t sumi_h2_1 = __riscv_vnsrl_wx_u16m2(sumi_i32, 16, vl);
169                const vuint16m2_t sumi_h2 = __riscv_vadd_vv_u16m2(sumi_h2_0, sumi_h2_1, vl);
170                const vuint32m2_t sumi_h2_i32 = __riscv_vreinterpret_v_u16m2_u32m2(sumi_h2);
171                const vuint16m1_t sumi_h4_0 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 0, vl / 2);
172                const vuint16m1_t sumi_h4_1 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 16, vl / 2);
173                const vuint16m1_t sumi_h4 = __riscv_vadd_vv_u16m1(sumi_h4_0, sumi_h4_1, vl / 2);
174                const vuint32m1_t sumi_h4_i32 = __riscv_vreinterpret_v_u16m1_u32m1(sumi_h4);
175                const vint16mf2_t sumi_h8_0 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 0, vl / 4));
176                const vint16mf2_t sumi_h8_1 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 16, vl / 4));
177                const vint32m1_t sumi_h8 = __riscv_vwadd_vv_i32m1(sumi_h8_0, sumi_h8_1, vl / 4);
178                const vfloat32m1_t facc = __riscv_vfcvt_f_x_v_f32m1(sumi_h8, vl / 4);
179
180                // vector version needs Zvfhmin extension
181                const float a_scale = GGML_CPU_FP16_TO_FP32(a_ptr[l].d);
182                const float b_scales[8] = {
183                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[0]),
184                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[1]),
185                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[2]),
186                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[3]),
187                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[4]),
188                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[5]),
189                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[6]),
190                    GGML_CPU_FP16_TO_FP32(b_ptr[l].d[7])
191                };
192                const vfloat32m1_t b_scales_vec = __riscv_vle32_v_f32m1(b_scales, vl / 4);
193                const vfloat32m1_t tmp1 = __riscv_vfmul_vf_f32m1(facc, a_scale, vl / 4);
194                sumf = __riscv_vfmacc_vv_f32m1(sumf, tmp1, b_scales_vec, vl / 4);
195            }
196            __riscv_vse32_v_f32m1(s + x * ncols_interleaved, sumf, vl / 4);
197        }
198        return;
199    }
200
201#endif
202    ggml_gemv_q4_0_8x8_q8_0_generic(n, s, bs, vx, vy, nr, nc);
203}
204
205#if defined __riscv_zvfh
206void ggml_gemv_q4_0_16x1_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
207    const int qk = QK8_0;
208    const int nb = n / qk;
209    const int ncols_interleaved = 16;
210    const int blocklen = 1;
211
212    assert (n % qk == 0);
213    assert (nc % ncols_interleaved == 0);
214
215    UNUSED(s);
216    UNUSED(bs);
217    UNUSED(vx);
218    UNUSED(vy);
219    UNUSED(nr);
220    UNUSED(nc);
221    UNUSED(nb);
222    UNUSED(ncols_interleaved);
223    UNUSED(blocklen);
224
225    const block_q8_0 * a_ptr = (const block_q8_0 *) vy;
226    for (int x = 0; x < nc / ncols_interleaved; x++) {
227        const block_q4_0x16 * b_ptr = (const block_q4_0x16 *) vx + (x * nb);
228
229        // 1x16 Accumulator
230        vfloat32m2_t sumf = __riscv_vfmv_v_f_f32m2(0.0f, 16);
231
232        for (int l = 0; l < nb; l++) {
233            // 1x16 Integer Accumulator
234            vint16m1_t sumi_0_lo_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
235            vint16m1_t sumi_0_hi_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
236
237            // Accumulation loop.
238            for (int i = 0; i < QK4_0 / 2; i++) {
239                // Load `b_ptr`.
240                const vint8mf2_t b_0_packed = __riscv_vle8_v_i8mf2((const int8_t *)&b_ptr[l].qs[i * 16], 16);
241                const vint8mf2_t b_0_lo = __riscv_vsra_vx_i8mf2(__riscv_vsll_vx_i8mf2(b_0_packed, 4, 16), 4, 16);
242                const vint8mf2_t b_0_hi = __riscv_vsra_vx_i8mf2(b_0_packed, 4, 16);
243
244                sumi_0_lo_16 = __riscv_vwmacc_vx_i16m1(sumi_0_lo_16, a_ptr[l].qs[i], b_0_lo, 16);
245                sumi_0_hi_16 = __riscv_vwmacc_vx_i16m1(sumi_0_hi_16, a_ptr[l].qs[16 + i], b_0_hi, 16);
246            }
247
248            const vint32m2_t sumi = __riscv_vwadd_vv_i32m2(sumi_0_lo_16, sumi_0_hi_16, 16);
249
250            const vfloat16m1_t b_d = __riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].d, 16);
251            const vfloat32m2_t d_0 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d, 16);
252
253            sumf = __riscv_vfmacc_vv_f32m2(sumf, __riscv_vfcvt_f_x_v_f32m2(sumi, 16), d_0, 16);
254        }
255
256        __riscv_vse32_v_f32m2(s + x * 16, sumf, 16);
257    }
258}
259
260void ggml_gemv_q4_K_16x1_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
261    const int qk = QK_K;
262    const int nb = n / qk;
263    const int ncols_interleaved = 16;
264    const int blocklen = 1;
265
266    assert (n % qk == 0);
267    assert (nc % ncols_interleaved == 0);
268
269    UNUSED(s);
270    UNUSED(bs);
271    UNUSED(vx);
272    UNUSED(vy);
273    UNUSED(nr);
274    UNUSED(nc);
275    UNUSED(nb);
276    UNUSED(ncols_interleaved);
277    UNUSED(blocklen);
278
279    const block_q8_K * a_ptr = (const block_q8_K *) vy;
280
281    for (int x = 0; x < nc / ncols_interleaved; x++) {
282        const block_q4_Kx16 * b_ptr = (const block_q4_Kx16 *) vx + (x * nb);
283
284        // 1x16 Accumulator
285        vfloat32m2_t sumf = __riscv_vfmv_v_f_f32m2(0.0f, 16);
286
287        for (int l = 0; l < nb; l++) {
288            vint32m2_t sumi = __riscv_vmv_v_x_i32m2(0, 16);
289
290            // Load `dmin`.
291            const vfloat32m2_t dmins_d = __riscv_vfmul_vf_f32m2(
292                __riscv_vfwcvt_f_f_v_f32m2(__riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].dmin, 16), 16), a_ptr[l].d, 16);
293
294            // We process 4 sub-blocks at once.
295            for (int j = 0; j < QK_K / 128; j++) {
296                // Extract the scales and the mins.
297                //
298                // Low bits.
299                vuint8m2_t scales_mins_lo = __riscv_vle8_v_u8m2(&b_ptr[l].scales[j * 64], 64);
300                vuint8m2_t scales_lo = __riscv_vand_vx_u8m2(scales_mins_lo, 0x0F, 64);
301                vuint8m2_t mins_lo = __riscv_vsrl_vx_u8m2(scales_mins_lo, 4, 64);
302
303                // High bits.
304                vuint8m2_t scales_mins_hi = __riscv_vle8_v_u8m2(&b_ptr[l].scales[128], 64);
305                vuint8m2_t scales_hi;
306                vuint8m2_t mins_hi;
307                if (!j) {
308                    scales_hi = __riscv_vsll_vx_u8m2(__riscv_vand_vx_u8m2(scales_mins_hi, 0x03, 64), 4, 64);
309                    mins_hi = __riscv_vsll_vx_u8m2(__riscv_vand_vx_u8m2(scales_mins_hi, 0x0C, 64), 2, 64);
310                } else {
311                    scales_hi = __riscv_vand_vx_u8m2(scales_mins_hi, 0x30, 64);
312                    mins_hi = __riscv_vsrl_vx_u8m2(__riscv_vand_vx_u8m2(scales_mins_hi, 0xC0, 64), 2, 64);
313                }
314                vuint16m4_t scales = __riscv_vzext_vf2_u16m4(__riscv_vor_vv_u8m2(scales_hi, scales_lo, 64), 64);
315                vint16m4_t mins = __riscv_vreinterpret_v_u16m4_i16m4(__riscv_vzext_vf2_u16m4(__riscv_vor_vv_u8m2(mins_hi, mins_lo, 64), 64));
316
317                // Reduce the mins and multiply with `dmin`.
318                //
319                // Correct in `sumf`.
320                vint32m2_t bsums = __riscv_vmv_v_x_i32m2(0, 16);
321                bsums = __riscv_vwmacc_vx_i32m2(bsums, a_ptr[l].bsums[j * 8] + a_ptr[l].bsums[j * 8 + 1], __riscv_vget_v_i16m4_i16m1(mins, 0), 16);
322                bsums = __riscv_vwmacc_vx_i32m2(bsums, a_ptr[l].bsums[j * 8 + 2] + a_ptr[l].bsums[j * 8 + 3], __riscv_vget_v_i16m4_i16m1(mins, 1), 16);
323                bsums = __riscv_vwmacc_vx_i32m2(bsums, a_ptr[l].bsums[j * 8 + 4] + a_ptr[l].bsums[j * 8 + 5], __riscv_vget_v_i16m4_i16m1(mins, 2), 16);
324                bsums = __riscv_vwmacc_vx_i32m2(bsums, a_ptr[l].bsums[j * 8 + 6] + a_ptr[l].bsums[j * 8 + 7], __riscv_vget_v_i16m4_i16m1(mins, 3), 16);
325
326                sumf = __riscv_vfsub_vv_f32m2(sumf, __riscv_vfmul_vv_f32m2(dmins_d, __riscv_vfcvt_f_x_v_f32m2(bsums, 16), 16), 16);
327
328                // Accumulation for 2 sub-blocks.
329                //
330                // This might overflow, so we accumulate in two steps.
331                //
332                // Recheck.
333                for (int k = 0; k < 2; k++) {
334                    vint16m1_t sumi_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
335                    vint16m1_t sumi_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
336
337                    for (int i = k * 16; i < k * 16 + QK4_0 / 2; i++) {
338                        // Load `b_ptr`.
339                        const vuint8mf2_t b_0_packed = __riscv_vle8_v_u8mf2(&b_ptr[l].qs[j * 1024 + i * 16], 16);
340                        const vint8mf2_t b_s_0 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(b_0_packed, 0xF, 16));
341                        const vint8mf2_t b_s_1 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vsrl_vx_u8mf2(b_0_packed, 4, 16));
342
343                        sumi_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_s_0_16, a_ptr[l].qs[j * 128 + i], b_s_0, 16);
344                        sumi_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_s_1_16, a_ptr[l].qs[j * 128 + 32 + i], b_s_1, 16);
345                    }
346
347                    sumi = __riscv_vwmacc_vv_i32m2(sumi,
348                        __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 0)),
349                        sumi_s_0_16, 16);
350                    sumi = __riscv_vwmacc_vv_i32m2(sumi,
351                        __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 1)),
352                        sumi_s_1_16, 16);
353                }
354                // Accumulation for 2 sub-blocks.
355                //
356                // This might overflow, so we accumulate in two steps.
357                //
358                // Recheck.
359                for (int k = 0; k < 2; k++) {
360                    vint16m1_t sumi_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
361                    vint16m1_t sumi_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
362
363                    for (int i = k * 16; i < k * 16 + QK4_0 / 2; i++) {
364                        // Load `b_ptr`.
365                        const vuint8mf2_t b_0_packed = __riscv_vle8_v_u8mf2(&b_ptr[l].qs[j * 1024 + 512 + i * 16], 16);
366                        const vint8mf2_t b_s_0 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(b_0_packed, 0xF, 16));
367                        const vint8mf2_t b_s_1 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vsrl_vx_u8mf2(b_0_packed, 4, 16));
368
369                        sumi_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_s_0_16, a_ptr[l].qs[j * 128 + 64 + i], b_s_0, 16);
370                        sumi_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_s_1_16, a_ptr[l].qs[j * 128 + 96 + i], b_s_1, 16);
371                    }
372
373                    sumi = __riscv_vwmacc_vv_i32m2(sumi,
374                        __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 2)),
375                        sumi_s_0_16, 16);
376                    sumi = __riscv_vwmacc_vv_i32m2(sumi,
377                        __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 3)),
378                        sumi_s_1_16, 16);
379                }
380            }
381
382            const vfloat32m2_t b_d = __riscv_vfwcvt_f_f_v_f32m2(__riscv_vle16_v_f16m1((const _Float16 *)&b_ptr[l].d[0], 16), 16);
383            const vfloat32m2_t d_0 = __riscv_vfmul_vf_f32m2(b_d, a_ptr[l].d, 16);
384
385            sumf = __riscv_vfmacc_vv_f32m2(sumf, __riscv_vfcvt_f_x_v_f32m2(sumi, 16), d_0, 16);
386        }
387
388        __riscv_vse32_v_f32m2(s + x * 16, sumf, 16);
389    }
390}
391
392void ggml_gemv_iq4_nl_16x1_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
393    const int qk = QK8_0;
394    const int nb = n / qk;
395    const int ncols_interleaved = 16;
396    const int blocklen = 1;
397
398    assert (n % qk == 0);
399    assert (nc % ncols_interleaved == 0);
400
401    UNUSED(s);
402    UNUSED(bs);
403    UNUSED(vx);
404    UNUSED(vy);
405    UNUSED(nr);
406    UNUSED(nc);
407    UNUSED(nb);
408    UNUSED(ncols_interleaved);
409    UNUSED(blocklen);
410
411    const vint8mf2_t values = __riscv_vle8_v_i8mf2(kvalues_iq4nl, 16);
412    const block_q8_0 * a_ptr = (const block_q8_0 *) vy;
413    for (int x = 0; x < nc / ncols_interleaved; x++) {
414        const block_iq4_nlx16 * b_ptr = (const block_iq4_nlx16 *) vx + (x * nb);
415
416        // 1x16 Accumulator1
417        vfloat32m2_t sumf = __riscv_vfmv_v_f_f32m2(0.0f, 16);
418
419        for (int l = 0; l < nb; l++) {
420            // 1x16 integer accumulator
421            vint32m2_t sumi = __riscv_vmv_v_x_i32m2(0.0f, 16);
422
423            // Accumulation loop.
424            for (int i = 0; i < QK4_NL / 2; i++) {
425                // Load `b_ptr`.
426                const vuint8mf2_t b_0_packed = __riscv_vle8_v_u8mf2((const uint8_t *)&b_ptr[l].qs[i * 16], 16);
427                const vint8mf2_t b_0_lo = __riscv_vrgather_vv_i8mf2(values, __riscv_vand_vx_u8mf2(b_0_packed, 0xf, 16), 16);
428                const vint8mf2_t b_0_hi = __riscv_vrgather_vv_i8mf2(values, __riscv_vsrl_vx_u8mf2(b_0_packed, 4, 16), 16);
429                // const vint16m1_t b_0_lo_16 = __riscv_vwcvt_x_x_v_i16m1(b_0_lo, 16);
430                // const vint16m1_t b_0_hi_16 = __riscv_vwcvt_x_x_v_i16m1(b_0_hi, 16);
431
432                const vint16m1_t sumi_lo = __riscv_vwmul_vx_i16m1(b_0_lo, a_ptr[l].qs[i], 16);
433                const vint16m1_t sumi_hi = __riscv_vwmul_vx_i16m1(b_0_hi, a_ptr[l].qs[16 + i], 16);
434                sumi = __riscv_vadd_vv_i32m2(sumi, __riscv_vwadd_vv_i32m2(sumi_lo, sumi_hi, 16), 16);
435            }
436
437            const vfloat16m1_t b_d = __riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].d, 16);
438            const vfloat32m2_t d_0 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d, 16);
439
440            sumf = __riscv_vfmacc_vv_f32m2(sumf, __riscv_vfcvt_f_x_v_f32m2(sumi, 16), d_0, 16);
441        }
442
443        __riscv_vse32_v_f32m2(s + x * 16, sumf, 16);
444    }
445}
446
447void ggml_gemv_q8_0_16x1_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
448    const int qk = QK8_0;
449    const int nb = n / qk;
450    const int ncols_interleaved = 16;
451    const int blocklen = 1;
452
453    assert (n % qk == 0);
454    assert (nc % ncols_interleaved == 0);
455
456    UNUSED(s);
457    UNUSED(bs);
458    UNUSED(vx);
459    UNUSED(vy);
460    UNUSED(nr);
461    UNUSED(nc);
462    UNUSED(nb);
463    UNUSED(ncols_interleaved);
464    UNUSED(blocklen);
465    UNUSED(bs);
466
467    const block_q8_0 * a_ptr = (const block_q8_0 *) vy;
468    for (int x = 0; x < nc / ncols_interleaved; x++) {
469        const block_q8_0x16 * b_ptr = (const block_q8_0x16 *) vx + (x * nb);
470
471        // 1x16 Accumulator
472        vfloat32m2_t sumf = __riscv_vfmv_v_f_f32m2(0.0f, 16);
473
474        for (int l = 0; l < nb; l++) {
475            // 1x16 Integer Accumulator
476            vint32m2_t sumi = __riscv_vmv_v_x_i32m2(0.0f, 16);
477
478            // Accumulation loop.
479            for (int i = 0; i < QK8_0; i++) {
480                // Load `b_ptr`.
481                const vint8mf2_t b_0 = __riscv_vle8_v_i8mf2((const int8_t *)&b_ptr[l].qs[i * 16], 16);
482                // const vint16m1_t b_0_16 = __riscv_vwcvt_x_x_v_i16m1(b_0, 16);
483
484                sumi = __riscv_vwadd_wv_i32m2(sumi, __riscv_vwmul_vx_i16m1(b_0, a_ptr[l].qs[i], 16), 16);
485            }
486
487            const vfloat16m1_t b_d = __riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].d, 16);
488            const vfloat32m2_t d_0 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d, 16);
489
490            sumf = __riscv_vfmacc_vv_f32m2(sumf, __riscv_vfcvt_f_x_v_f32m2(sumi, 16), d_0, 16);
491        }
492
493        __riscv_vse32_v_f32m2(s + x * 16, sumf, 16);
494    }
495}
496
497void ggml_gemv_q2_K_16x1_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
498    assert(n % QK_K == 0);
499    assert(nr == 1);
500    assert(nc % 16 == 0);
501
502    UNUSED(bs);
503
504    const int N_COLS_TILE = 16;
505    const int num_k_blocks = n / QK_K;
506
507    const size_t vl = __riscv_vsetvl_e32m2(N_COLS_TILE);
508    for (int col_tile = 0; col_tile < nc; col_tile += N_COLS_TILE) {
509
510        const block_q8_K* lhs_base_ptr = (const block_q8_K*)vy;
511        const block_q2_Kx16* rhs_base_ptr = (const block_q2_Kx16*)vx + (col_tile / N_COLS_TILE) * num_k_blocks;
512
513        vfloat32m2_t v_sumf = __riscv_vfmv_v_f_f32m2(0.0f, vl);
514
515        for (int k_block = 0; k_block < num_k_blocks; ++k_block) {
516            const block_q8_K* lhs_current = &lhs_base_ptr[k_block];
517            const block_q2_Kx16* rhs_current = &rhs_base_ptr[k_block];
518
519            // 1. Prepare Global Min Scales
520            vfloat16m1_t v_g_min_f16 = __riscv_vle16_v_f16m1((const _Float16*)rhs_current->dmin, vl);
521            vfloat32m2_t v_g_min_base = __riscv_vfwcvt_f_f_v_f32m2(v_g_min_f16, vl);
522
523            vfloat32m2_t v_g_min_final = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d, vl);
524
525            vint32m2_t v_isum = __riscv_vmv_v_x_i32m2(0, vl);
526
527            const uint8_t* rhs_qs_ptr = rhs_current->qs;
528            const uint8_t* rhs_sc_ptr = rhs_current->scales;
529            const int8_t*  lhs_qs_ptr = lhs_current->qs;
530
531            // --- Phase Loop (4 phases x 64 elements) ---
532            for (int phase = 0; phase < 4; ++phase) {
533
534                // A. Load Scales/Mins
535                vuint16m1_t v_d_sb_0, v_d_sb_1, v_d_sb_2, v_d_sb_3;
536                vuint16m1_t v_m_sb_0, v_m_sb_1, v_m_sb_2, v_m_sb_3;
537
538                {
539                    vuint8mf2_t v_raw;
540                    // Sub-block 0
541                    v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 0, vl);
542                    v_d_sb_0 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
543                    v_m_sb_0 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
544
545                    // Sub-block 1
546                    v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 16, vl);
547                    v_d_sb_1 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
548                    v_m_sb_1 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
549
550                    // Sub-block 2
551                    v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 32, vl);
552                    v_d_sb_2 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
553                    v_m_sb_2 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
554
555                    // Sub-block 3
556                    v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 48, vl);
557                    v_d_sb_3 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
558                    v_m_sb_3 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
559
560                    rhs_sc_ptr += 64;
561                }
562
563                int base_k_phase = (phase < 2) ? (phase * 16) : (128 + (phase-2)*16);
564                int k_offsets[4] = {0, 32, 64, 96};
565
566                // B. Inner Dot Product Loop
567                for (int l = 0; l < 16; ++l) {
568                    vuint8mf2_t v_rhs_data = __riscv_vle8_v_u8mf2(rhs_qs_ptr, vl);
569                    rhs_qs_ptr += 16;
570
571                    // Sub-block 0
572                    {
573                        vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(v_rhs_data, 3, vl);
574                        vint16m1_t v_w = __riscv_vmul_vv_i16m1(
575                            __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
576                            __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_0), vl);
577
578                        int8_t q8 = lhs_qs_ptr[base_k_phase + k_offsets[0] + l];
579                        v_isum = __riscv_vwmacc_vx_i32m2(v_isum, (int16_t)q8, v_w, vl);
580                    }
581                    // Sub-block 1
582                    {
583                        vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(v_rhs_data, 2, vl), 3, vl);
584                        vint16m1_t v_w = __riscv_vmul_vv_i16m1(
585                            __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
586                            __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_1), vl);
587
588                        int8_t q8 = lhs_qs_ptr[base_k_phase + k_offsets[1] + l];
589                        v_isum = __riscv_vwmacc_vx_i32m2(v_isum, (int16_t)q8, v_w, vl);
590                    }
591                    // Sub-block 2
592                    {
593                        vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(v_rhs_data, 4, vl), 3, vl);
594                        vint16m1_t v_w = __riscv_vmul_vv_i16m1(
595                            __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
596                            __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_2), vl);
597
598                        int8_t q8 = lhs_qs_ptr[base_k_phase + k_offsets[2] + l];
599                        v_isum = __riscv_vwmacc_vx_i32m2(v_isum, (int16_t)q8, v_w, vl);
600                    }
601                    // Sub-block 3
602                    {
603                        vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(v_rhs_data, 6, vl), 3, vl);
604                        vint16m1_t v_w = __riscv_vmul_vv_i16m1(
605                            __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
606                            __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_3), vl);
607
608                        int8_t q8 = lhs_qs_ptr[base_k_phase + k_offsets[3] + l];
609                        v_isum = __riscv_vwmacc_vx_i32m2(v_isum, (int16_t)q8, v_w, vl);
610                    }
611                }
612
613                // correction
614                int sb_base_abs = base_k_phase / 16;
615
616                // Sub-block 0
617                {
618                    int sb_idx = sb_base_abs + (k_offsets[0] / 16);
619                    int16_t bsum = lhs_current->bsums[sb_idx];
620                    vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_0);
621                    vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, bsum, vl);
622                    vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min_final, vl);
623                    v_sumf = __riscv_vfsub_vv_f32m2(v_sumf, vf_c, vl);
624                }
625                // Sub-block 1
626                {
627                    int sb_idx = sb_base_abs + (k_offsets[1] / 16);
628                    int16_t bsum = lhs_current->bsums[sb_idx];
629                    vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_1);
630                    vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, bsum, vl);
631                    vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min_final, vl);
632                    v_sumf = __riscv_vfsub_vv_f32m2(v_sumf, vf_c, vl);
633                }
634                // Sub-block 2
635                {
636                    int sb_idx = sb_base_abs + (k_offsets[2] / 16);
637                    int16_t bsum = lhs_current->bsums[sb_idx];
638                    vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_2);
639                    vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, bsum, vl);
640                    vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min_final, vl);
641                    v_sumf = __riscv_vfsub_vv_f32m2(v_sumf, vf_c, vl);
642                }
643                // Sub-block 3
644                {
645                    int sb_idx = sb_base_abs + (k_offsets[3] / 16);
646                    int16_t bsum = lhs_current->bsums[sb_idx];
647                    vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_3);
648                    vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, bsum, vl);
649                    vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min_final, vl);
650                    v_sumf = __riscv_vfsub_vv_f32m2(v_sumf, vf_c, vl);
651                }
652
653            } // End Phase Loop
654
655            // Apply global Scales
656            vfloat16m1_t v_g_all_f16 = __riscv_vle16_v_f16m1((const _Float16*)rhs_current->d, vl);
657            vfloat32m2_t v_g_all_base = __riscv_vfwcvt_f_f_v_f32m2(v_g_all_f16, vl);
658
659            vfloat32m2_t v_g_all_final = __riscv_vfmul_vf_f32m2(v_g_all_base, lhs_current->d, vl);
660            vfloat32m2_t v_sum = __riscv_vfcvt_f_x_v_f32m2(v_isum, vl);
661            v_sum = __riscv_vfmul_vv_f32m2(v_sum, v_g_all_final, vl);
662            v_sumf = __riscv_vfadd_vv_f32m2(v_sumf, v_sum, vl);
663
664        } // End K-Block
665        __riscv_vse32_v_f32m2(s + col_tile, v_sumf, vl);
666    }
667}
668#endif
669
670void ggml_gemm_q4_0_8x8_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
671    const int qk = QK8_0;
672    const int nb = n / qk;
673    const int ncols_interleaved = 8;
674    const int blocklen = 8;
675
676    assert (n % qk == 0);
677    assert (nr % 4 == 0);
678    assert (nc % ncols_interleaved == 0);
679
680    UNUSED(s);
681    UNUSED(bs);
682    UNUSED(vx);
683    UNUSED(vy);
684    UNUSED(nr);
685    UNUSED(nc);
686    UNUSED(nb);
687    UNUSED(ncols_interleaved);
688    UNUSED(blocklen);
689
690#if defined __riscv_v
691    if (__riscv_vlenb() >= QK4_0) {
692        const size_t vl = QK4_0;
693
694        for (int y = 0; y < nr / 4; y++) {
695            const block_q8_0x4 * a_ptr = (const block_q8_0x4 *) vy + (y * nb);
696            for (int x = 0; x < nc / ncols_interleaved; x++) {
697                const block_q4_0x8 * b_ptr = (const block_q4_0x8 *) vx + (x * nb);
698                vfloat32m1_t sumf0 = __riscv_vfmv_v_f_f32m1(0.0, vl / 4);
699                vfloat32m1_t sumf1 = __riscv_vfmv_v_f_f32m1(0.0, vl / 4);
700                vfloat32m1_t sumf2 = __riscv_vfmv_v_f_f32m1(0.0, vl / 4);
701                vfloat32m1_t sumf3 = __riscv_vfmv_v_f_f32m1(0.0, vl / 4);
702                for (int l = 0; l < nb; l++) {
703                    const vint8m4_t rhs_raw_vec = __riscv_vle8_v_i8m4((const int8_t *)b_ptr[l].qs, vl * 4);
704                    const vint8m4_t rhs_vec_lo = __riscv_vsra_vx_i8m4(__riscv_vsll_vx_i8m4(rhs_raw_vec, 4, vl * 4), 4, vl * 4);
705                    const vint8m4_t rhs_vec_hi = __riscv_vsra_vx_i8m4(rhs_raw_vec, 4, vl * 4);
706                    const vint8m2_t rhs_vec_lo_0 = __riscv_vget_v_i8m4_i8m2(rhs_vec_lo, 0);
707                    const vint8m2_t rhs_vec_lo_1 = __riscv_vget_v_i8m4_i8m2(rhs_vec_lo, 1);
708                    const vint8m2_t rhs_vec_hi_0 = __riscv_vget_v_i8m4_i8m2(rhs_vec_hi, 0);
709                    const vint8m2_t rhs_vec_hi_1 = __riscv_vget_v_i8m4_i8m2(rhs_vec_hi, 1);
710
711                    // vector version needs Zvfhmin extension
712                    const float a_scales[4] = {
713                        GGML_CPU_FP16_TO_FP32(a_ptr[l].d[0]),
714                        GGML_CPU_FP16_TO_FP32(a_ptr[l].d[1]),
715                        GGML_CPU_FP16_TO_FP32(a_ptr[l].d[2]),
716                        GGML_CPU_FP16_TO_FP32(a_ptr[l].d[3])
717                    };
718                    const float b_scales[8] = {
719                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[0]),
720                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[1]),
721                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[2]),
722                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[3]),
723                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[4]),
724                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[5]),
725                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[6]),
726                        GGML_CPU_FP16_TO_FP32(b_ptr[l].d[7])
727                    };
728                    const vfloat32m1_t b_scales_vec = __riscv_vle32_v_f32m1(b_scales, vl / 4);
729
730                    const int64_t A0 = *(const int64_t *)&a_ptr[l].qs[0];
731                    const int64_t A4 = *(const int64_t *)&a_ptr[l].qs[32];
732                    const int64_t A8 = *(const int64_t *)&a_ptr[l].qs[64];
733                    const int64_t Ac = *(const int64_t *)&a_ptr[l].qs[96];
734                    __asm__ __volatile__("" ::: "memory"); // prevent gcc from emitting fused vlse64, violating alignment
735                    vint16m4_t sumi_l0;
736                    {
737                        const vint8m2_t lhs_0_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A0, vl / 4));
738                        const vint8m2_t lhs_1_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A4, vl / 4));
739                        const vint8m2_t lhs_2_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A8, vl / 4));
740                        const vint8m2_t lhs_3_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(Ac, vl / 4));
741                        const vint16m4_t sumi_lo_0 = __riscv_vwmul_vv_i16m4(rhs_vec_lo_0, lhs_0_8, vl * 2);
742                        const vint16m4_t sumi_lo_1 = __riscv_vwmacc_vv_i16m4(sumi_lo_0, rhs_vec_lo_1, lhs_1_8, vl * 2);
743                        const vint16m4_t sumi_hi_0 = __riscv_vwmacc_vv_i16m4(sumi_lo_1, rhs_vec_hi_0, lhs_2_8, vl * 2);
744                        const vint16m4_t sumi_hi_m = __riscv_vwmacc_vv_i16m4(sumi_hi_0, rhs_vec_hi_1, lhs_3_8, vl * 2);
745
746                        sumi_l0 = sumi_hi_m;
747                    }
748
749                    {
750                        const vuint32m4_t sumi_i32 = __riscv_vreinterpret_v_i32m4_u32m4(__riscv_vreinterpret_v_i16m4_i32m4(sumi_l0));
751                        const vuint16m2_t sumi_h2_0 = __riscv_vnsrl_wx_u16m2(sumi_i32, 0, vl);
752                        const vuint16m2_t sumi_h2_1 = __riscv_vnsrl_wx_u16m2(sumi_i32, 16, vl);
753                        const vuint16m2_t sumi_h2 = __riscv_vadd_vv_u16m2(sumi_h2_0, sumi_h2_1, vl);
754                        const vuint32m2_t sumi_h2_i32 = __riscv_vreinterpret_v_u16m2_u32m2(sumi_h2);
755                        const vuint16m1_t sumi_h4_0 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 0, vl / 2);
756                        const vuint16m1_t sumi_h4_1 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 16, vl / 2);
757                        const vuint16m1_t sumi_h4 = __riscv_vadd_vv_u16m1(sumi_h4_0, sumi_h4_1, vl / 2);
758                        const vuint32m1_t sumi_h4_i32 = __riscv_vreinterpret_v_u16m1_u32m1(sumi_h4);
759                        const vint16mf2_t sumi_h8_0 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 0, vl / 4));
760                        const vint16mf2_t sumi_h8_1 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 16, vl / 4));
761                        const vint32m1_t sumi_h8 = __riscv_vwadd_vv_i32m1(sumi_h8_0, sumi_h8_1, vl / 4);
762                        const vfloat32m1_t facc = __riscv_vfcvt_f_x_v_f32m1(sumi_h8, vl / 4);
763
764                        const vfloat32m1_t tmp1 = __riscv_vfmul_vf_f32m1(facc, a_scales[0], vl / 4);
765                        sumf0 = __riscv_vfmacc_vv_f32m1(sumf0, tmp1, b_scales_vec, vl / 4);
766                    }
767
768                    const int64_t A1 = *(const int64_t *)&a_ptr[l].qs[8];
769                    const int64_t A5 = *(const int64_t *)&a_ptr[l].qs[40];
770                    const int64_t A9 = *(const int64_t *)&a_ptr[l].qs[72];
771                    const int64_t Ad = *(const int64_t *)&a_ptr[l].qs[104];
772                    __asm__ __volatile__("" ::: "memory"); // prevent gcc from emitting fused vlse64, violating alignment
773                    vint16m4_t sumi_l1;
774                    {
775                        const vint8m2_t lhs_0_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A1, vl / 4));
776                        const vint8m2_t lhs_1_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A5, vl / 4));
777                        const vint8m2_t lhs_2_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A9, vl / 4));
778                        const vint8m2_t lhs_3_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(Ad, vl / 4));
779                        const vint16m4_t sumi_lo_0 = __riscv_vwmul_vv_i16m4(rhs_vec_lo_0, lhs_0_8, vl * 2);
780                        const vint16m4_t sumi_lo_1 = __riscv_vwmacc_vv_i16m4(sumi_lo_0, rhs_vec_lo_1, lhs_1_8, vl * 2);
781                        const vint16m4_t sumi_hi_0 = __riscv_vwmacc_vv_i16m4(sumi_lo_1, rhs_vec_hi_0, lhs_2_8, vl * 2);
782                        const vint16m4_t sumi_hi_m = __riscv_vwmacc_vv_i16m4(sumi_hi_0, rhs_vec_hi_1, lhs_3_8, vl * 2);
783
784                        sumi_l1 = sumi_hi_m;
785                    }
786
787                    {
788                        const vuint32m4_t sumi_i32 = __riscv_vreinterpret_v_i32m4_u32m4(__riscv_vreinterpret_v_i16m4_i32m4(sumi_l1));
789                        const vuint16m2_t sumi_h2_0 = __riscv_vnsrl_wx_u16m2(sumi_i32, 0, vl);
790                        const vuint16m2_t sumi_h2_1 = __riscv_vnsrl_wx_u16m2(sumi_i32, 16, vl);
791                        const vuint16m2_t sumi_h2 = __riscv_vadd_vv_u16m2(sumi_h2_0, sumi_h2_1, vl);
792                        const vuint32m2_t sumi_h2_i32 = __riscv_vreinterpret_v_u16m2_u32m2(sumi_h2);
793                        const vuint16m1_t sumi_h4_0 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 0, vl / 2);
794                        const vuint16m1_t sumi_h4_1 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 16, vl / 2);
795                        const vuint16m1_t sumi_h4 = __riscv_vadd_vv_u16m1(sumi_h4_0, sumi_h4_1, vl / 2);
796                        const vuint32m1_t sumi_h4_i32 = __riscv_vreinterpret_v_u16m1_u32m1(sumi_h4);
797                        const vint16mf2_t sumi_h8_0 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 0, vl / 4));
798                        const vint16mf2_t sumi_h8_1 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 16, vl / 4));
799                        const vint32m1_t sumi_h8 = __riscv_vwadd_vv_i32m1(sumi_h8_0, sumi_h8_1, vl / 4);
800                        const vfloat32m1_t facc = __riscv_vfcvt_f_x_v_f32m1(sumi_h8, vl / 4);
801
802                        const vfloat32m1_t tmp1 = __riscv_vfmul_vf_f32m1(facc, a_scales[1], vl / 4);
803                        sumf1 = __riscv_vfmacc_vv_f32m1(sumf1, tmp1, b_scales_vec, vl / 4);
804                    }
805
806                    const int64_t A2 = *(const int64_t *)&a_ptr[l].qs[16];
807                    const int64_t A6 = *(const int64_t *)&a_ptr[l].qs[48];
808                    const int64_t Aa = *(const int64_t *)&a_ptr[l].qs[80];
809                    const int64_t Ae = *(const int64_t *)&a_ptr[l].qs[112];
810                    __asm__ __volatile__("" ::: "memory"); // prevent gcc from emitting fused vlse64, violating alignment
811                    vint16m4_t sumi_l2;
812                    {
813                        const vint8m2_t lhs_0_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A2, vl / 4));
814                        const vint8m2_t lhs_1_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A6, vl / 4));
815                        const vint8m2_t lhs_2_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(Aa, vl / 4));
816                        const vint8m2_t lhs_3_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(Ae, vl / 4));
817                        const vint16m4_t sumi_lo_0 = __riscv_vwmul_vv_i16m4(rhs_vec_lo_0, lhs_0_8, vl * 2);
818                        const vint16m4_t sumi_lo_1 = __riscv_vwmacc_vv_i16m4(sumi_lo_0, rhs_vec_lo_1, lhs_1_8, vl * 2);
819                        const vint16m4_t sumi_hi_0 = __riscv_vwmacc_vv_i16m4(sumi_lo_1, rhs_vec_hi_0, lhs_2_8, vl * 2);
820                        const vint16m4_t sumi_hi_m = __riscv_vwmacc_vv_i16m4(sumi_hi_0, rhs_vec_hi_1, lhs_3_8, vl * 2);
821
822                        sumi_l2 = sumi_hi_m;
823                    }
824
825                    {
826                        const vuint32m4_t sumi_i32 = __riscv_vreinterpret_v_i32m4_u32m4(__riscv_vreinterpret_v_i16m4_i32m4(sumi_l2));
827                        const vuint16m2_t sumi_h2_0 = __riscv_vnsrl_wx_u16m2(sumi_i32, 0, vl);
828                        const vuint16m2_t sumi_h2_1 = __riscv_vnsrl_wx_u16m2(sumi_i32, 16, vl);
829                        const vuint16m2_t sumi_h2 = __riscv_vadd_vv_u16m2(sumi_h2_0, sumi_h2_1, vl);
830                        const vuint32m2_t sumi_h2_i32 = __riscv_vreinterpret_v_u16m2_u32m2(sumi_h2);
831                        const vuint16m1_t sumi_h4_0 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 0, vl / 2);
832                        const vuint16m1_t sumi_h4_1 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 16, vl / 2);
833                        const vuint16m1_t sumi_h4 = __riscv_vadd_vv_u16m1(sumi_h4_0, sumi_h4_1, vl / 2);
834                        const vuint32m1_t sumi_h4_i32 = __riscv_vreinterpret_v_u16m1_u32m1(sumi_h4);
835                        const vint16mf2_t sumi_h8_0 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 0, vl / 4));
836                        const vint16mf2_t sumi_h8_1 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 16, vl / 4));
837                        const vint32m1_t sumi_h8 = __riscv_vwadd_vv_i32m1(sumi_h8_0, sumi_h8_1, vl / 4);
838                        const vfloat32m1_t facc = __riscv_vfcvt_f_x_v_f32m1(sumi_h8, vl / 4);
839
840                        const vfloat32m1_t tmp1 = __riscv_vfmul_vf_f32m1(facc, a_scales[2], vl / 4);
841                        sumf2 = __riscv_vfmacc_vv_f32m1(sumf2, tmp1, b_scales_vec, vl / 4);
842                    }
843
844                    const int64_t A3 = *(const int64_t *)&a_ptr[l].qs[24];
845                    const int64_t A7 = *(const int64_t *)&a_ptr[l].qs[56];
846                    const int64_t Ab = *(const int64_t *)&a_ptr[l].qs[88];
847                    const int64_t Af = *(const int64_t *)&a_ptr[l].qs[120];
848                    __asm__ __volatile__("" ::: "memory"); // prevent gcc from emitting fused vlse64, violating alignment
849                    vint16m4_t sumi_l3;
850                    {
851                        const vint8m2_t lhs_0_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A3, vl / 4));
852                        const vint8m2_t lhs_1_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(A7, vl / 4));
853                        const vint8m2_t lhs_2_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(Ab, vl / 4));
854                        const vint8m2_t lhs_3_8 =__riscv_vreinterpret_v_i64m2_i8m2(__riscv_vmv_v_x_i64m2(Af, vl / 4));
855                        const vint16m4_t sumi_lo_0 = __riscv_vwmul_vv_i16m4(rhs_vec_lo_0, lhs_0_8, vl * 2);
856                        const vint16m4_t sumi_lo_1 = __riscv_vwmacc_vv_i16m4(sumi_lo_0, rhs_vec_lo_1, lhs_1_8, vl * 2);
857                        const vint16m4_t sumi_hi_0 = __riscv_vwmacc_vv_i16m4(sumi_lo_1, rhs_vec_hi_0, lhs_2_8, vl * 2);
858                        const vint16m4_t sumi_hi_m = __riscv_vwmacc_vv_i16m4(sumi_hi_0, rhs_vec_hi_1, lhs_3_8, vl * 2);
859
860                        sumi_l3 = sumi_hi_m;
861                    }
862
863                    {
864                        const vuint32m4_t sumi_i32 = __riscv_vreinterpret_v_i32m4_u32m4(__riscv_vreinterpret_v_i16m4_i32m4(sumi_l3));
865                        const vuint16m2_t sumi_h2_0 = __riscv_vnsrl_wx_u16m2(sumi_i32, 0, vl);
866                        const vuint16m2_t sumi_h2_1 = __riscv_vnsrl_wx_u16m2(sumi_i32, 16, vl);
867                        const vuint16m2_t sumi_h2 = __riscv_vadd_vv_u16m2(sumi_h2_0, sumi_h2_1, vl);
868                        const vuint32m2_t sumi_h2_i32 = __riscv_vreinterpret_v_u16m2_u32m2(sumi_h2);
869                        const vuint16m1_t sumi_h4_0 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 0, vl / 2);
870                        const vuint16m1_t sumi_h4_1 = __riscv_vnsrl_wx_u16m1(sumi_h2_i32, 16, vl / 2);
871                        const vuint16m1_t sumi_h4 = __riscv_vadd_vv_u16m1(sumi_h4_0, sumi_h4_1, vl / 2);
872                        const vuint32m1_t sumi_h4_i32 = __riscv_vreinterpret_v_u16m1_u32m1(sumi_h4);
873                        const vint16mf2_t sumi_h8_0 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 0, vl / 4));
874                        const vint16mf2_t sumi_h8_1 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(sumi_h4_i32, 16, vl / 4));
875                        const vint32m1_t sumi_h8 = __riscv_vwadd_vv_i32m1(sumi_h8_0, sumi_h8_1, vl / 4);
876                        const vfloat32m1_t facc = __riscv_vfcvt_f_x_v_f32m1(sumi_h8, vl / 4);
877
878                        const vfloat32m1_t tmp1 = __riscv_vfmul_vf_f32m1(facc, a_scales[3], vl / 4);
879                        sumf3 = __riscv_vfmacc_vv_f32m1(sumf3, tmp1, b_scales_vec, vl / 4);
880                    }
881                }
882                __riscv_vse32_v_f32m1(&s[(y * 4 + 0) * bs + x * ncols_interleaved], sumf0, vl / 4);
883                __riscv_vse32_v_f32m1(&s[(y * 4 + 1) * bs + x * ncols_interleaved], sumf1, vl / 4);
884                __riscv_vse32_v_f32m1(&s[(y * 4 + 2) * bs + x * ncols_interleaved], sumf2, vl / 4);
885                __riscv_vse32_v_f32m1(&s[(y * 4 + 3) * bs + x * ncols_interleaved], sumf3, vl / 4);
886            }
887        }
888
889        return;
890    }
891
892#endif
893    ggml_gemm_q4_0_8x8_q8_0_generic(n, s, bs, vx, vy, nr, nc);
894}
895
896#if defined __riscv_zvfh
897void ggml_gemm_q4_0_16x1_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
898    const int qk = QK8_0;
899    const int nb = n / qk;
900    const int ncols_interleaved = 16;
901    const int blocklen = 1;
902
903    assert (n % qk == 0);
904    assert (nr % 4 == 0);
905    assert (nc % ncols_interleaved == 0);
906
907    UNUSED(s);
908    UNUSED(bs);
909    UNUSED(vx);
910    UNUSED(vy);
911    UNUSED(nr);
912    UNUSED(nc);
913    UNUSED(nb);
914    UNUSED(ncols_interleaved);
915    UNUSED(blocklen);
916
917    for (int y = 0; y < nr / 4; y++) {
918        const block_q8_0x4 * a_ptr = (const block_q8_0x4 *) vy + (y * nb);
919        for (int x = 0; x < nc / ncols_interleaved; x++) {
920            const block_q4_0x16 * b_ptr = (const block_q4_0x16 *) vx + (x * nb);
921
922            // 4x16 Accumulators
923            vfloat32m2_t sumf_0 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
924            vfloat32m2_t sumf_1 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
925            vfloat32m2_t sumf_2 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
926            vfloat32m2_t sumf_3 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
927
928            for (int l = 0; l < nb; l++) {
929                // 4x16 integer accumulators
930                vint16m1_t sumi_0_lo_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
931                vint16m1_t sumi_1_lo_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
932                vint16m1_t sumi_2_lo_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
933                vint16m1_t sumi_3_lo_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
934                vint16m1_t sumi_0_hi_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
935                vint16m1_t sumi_1_hi_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
936                vint16m1_t sumi_2_hi_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
937                vint16m1_t sumi_3_hi_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
938
939                // Accumulation loop.
940                for (int i = 0; i < QK4_0 / 2; i++) {
941                    // Load `b_ptr`.
942                    const vint8mf2_t b_0_packed = __riscv_vle8_v_i8mf2((const int8_t *)&b_ptr[l].qs[i * 16], 16);
943                    const vint8mf2_t b_0_lo = __riscv_vsra_vx_i8mf2(__riscv_vsll_vx_i8mf2(b_0_packed, 4, 16), 4, 16);
944                    const vint8mf2_t b_0_hi = __riscv_vsra_vx_i8mf2(b_0_packed, 4, 16);
945
946                    sumi_0_lo_16 = __riscv_vwmacc_vx_i16m1(sumi_0_lo_16, a_ptr[l].qs[i * 4], b_0_lo, 16);
947                    sumi_1_lo_16 = __riscv_vwmacc_vx_i16m1(sumi_1_lo_16, a_ptr[l].qs[i * 4 + 1], b_0_lo, 16);
948                    sumi_2_lo_16 = __riscv_vwmacc_vx_i16m1(sumi_2_lo_16, a_ptr[l].qs[i * 4 + 2], b_0_lo, 16);
949                    sumi_3_lo_16 = __riscv_vwmacc_vx_i16m1(sumi_3_lo_16, a_ptr[l].qs[i * 4 + 3], b_0_lo, 16);
950
951                    sumi_0_hi_16 = __riscv_vwmacc_vx_i16m1(sumi_0_hi_16, a_ptr[l].qs[64 + i * 4], b_0_hi, 16);
952                    sumi_1_hi_16 = __riscv_vwmacc_vx_i16m1(sumi_1_hi_16, a_ptr[l].qs[64 + i * 4 + 1], b_0_hi, 16);
953                    sumi_2_hi_16 = __riscv_vwmacc_vx_i16m1(sumi_2_hi_16, a_ptr[l].qs[64 + i * 4 + 2], b_0_hi, 16);
954                    sumi_3_hi_16 = __riscv_vwmacc_vx_i16m1(sumi_3_hi_16, a_ptr[l].qs[64 + i * 4 + 3], b_0_hi, 16);
955                }
956
957                // Do the final accumulation in i32 to prevent overflow.
958                const vint32m2_t sumi_0 = __riscv_vwadd_vv_i32m2(sumi_0_lo_16, sumi_0_hi_16, 16);
959                const vint32m2_t sumi_1 = __riscv_vwadd_vv_i32m2(sumi_1_lo_16, sumi_1_hi_16, 16);
960                const vint32m2_t sumi_2 = __riscv_vwadd_vv_i32m2(sumi_2_lo_16, sumi_2_hi_16, 16);
961                const vint32m2_t sumi_3 = __riscv_vwadd_vv_i32m2(sumi_3_lo_16, sumi_3_hi_16, 16);
962
963                const vfloat16m1_t b_d = __riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].d, 16);
964                const vfloat32m2_t d_0 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[0], 16);
965                const vfloat32m2_t d_1 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[1], 16);
966                const vfloat32m2_t d_2 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[2], 16);
967                const vfloat32m2_t d_3 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[3], 16);
968
969                sumf_0 = __riscv_vfmacc_vv_f32m2(sumf_0, __riscv_vfcvt_f_x_v_f32m2(sumi_0, 16), d_0, 16);
970                sumf_1 = __riscv_vfmacc_vv_f32m2(sumf_1, __riscv_vfcvt_f_x_v_f32m2(sumi_1, 16), d_1, 16);
971                sumf_2 = __riscv_vfmacc_vv_f32m2(sumf_2, __riscv_vfcvt_f_x_v_f32m2(sumi_2, 16), d_2, 16);
972                sumf_3 = __riscv_vfmacc_vv_f32m2(sumf_3, __riscv_vfcvt_f_x_v_f32m2(sumi_3, 16), d_3, 16);
973            }
974
975            __riscv_vse32_v_f32m2(s + (y * 4 + 0) * bs + x * 16, sumf_0, 16);
976            __riscv_vse32_v_f32m2(s + (y * 4 + 1) * bs + x * 16, sumf_1, 16);
977            __riscv_vse32_v_f32m2(s + (y * 4 + 2) * bs + x * 16, sumf_2, 16);
978            __riscv_vse32_v_f32m2(s + (y * 4 + 3) * bs + x * 16, sumf_3, 16);
979        }
980    }
981}
982
983void ggml_gemm_q4_K_16x1_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
984    const int qk = QK_K;
985    const int nb = n / qk;
986    const int ncols_interleaved = 16;
987    const int blocklen = 1;
988
989    assert (n % qk == 0);
990    assert (nr % 4 == 0);
991    assert (nc % ncols_interleaved == 0);
992
993    UNUSED(s);
994    UNUSED(bs);
995    UNUSED(vx);
996    UNUSED(vy);
997    UNUSED(nr);
998    UNUSED(nc);
999    UNUSED(nb);
1000    UNUSED(ncols_interleaved);
1001    UNUSED(blocklen);
1002
1003    for (int y = 0; y < nr / 4; y++) {
1004        const block_q8_Kx4 * a_ptr = (const block_q8_Kx4 *) vy + (y * nb);
1005        for (int x = 0; x < nc / ncols_interleaved; x++) {
1006            const block_q4_Kx16 * b_ptr = (const block_q4_Kx16 *) vx + (x * nb);
1007
1008            // 4x16 Accumulators
1009            vfloat32m2_t sumf_0 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1010            vfloat32m2_t sumf_1 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1011            vfloat32m2_t sumf_2 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1012            vfloat32m2_t sumf_3 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1013
1014            for (int l = 0; l < nb; l++) {
1015                vint32m2_t sumi_0 = __riscv_vmv_v_x_i32m2(0, 16);
1016                vint32m2_t sumi_1 = __riscv_vmv_v_x_i32m2(0, 16);
1017                vint32m2_t sumi_2 = __riscv_vmv_v_x_i32m2(0, 16);
1018                vint32m2_t sumi_3 = __riscv_vmv_v_x_i32m2(0, 16);
1019
1020                // Load `dmin`.
1021                const vfloat32m2_t dmins = __riscv_vfwcvt_f_f_v_f32m2(__riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].dmin, 16), 16);
1022
1023                // We process 4 sub-blocks at once.
1024                for (int j = 0; j < QK_K / 128; j++) {
1025                    // Extract the scales and the mins.
1026                    //
1027                    // Low bits.
1028                    vuint8m2_t scales_mins_lo = __riscv_vle8_v_u8m2(&b_ptr[l].scales[j * 64], 64);
1029                    vuint8m2_t scales_lo = __riscv_vand_vx_u8m2(scales_mins_lo, 0x0F, 64);
1030                    vuint8m2_t mins_lo = __riscv_vsrl_vx_u8m2(scales_mins_lo, 4, 64);
1031
1032                    // High bits.
1033                    vuint8m2_t scales_mins_hi = __riscv_vle8_v_u8m2(&b_ptr[l].scales[128], 64);
1034                    vuint8m2_t scales_hi;
1035                    vuint8m2_t mins_hi;
1036                    if (!j) {
1037                        scales_hi = __riscv_vsll_vx_u8m2(__riscv_vand_vx_u8m2(scales_mins_hi, 0x03, 64), 4, 64);
1038                        mins_hi = __riscv_vsll_vx_u8m2(__riscv_vand_vx_u8m2(scales_mins_hi, 0x0C, 64), 2, 64);
1039                    } else {
1040                        scales_hi = __riscv_vand_vx_u8m2(scales_mins_hi, 0x30, 64);
1041                        mins_hi = __riscv_vsrl_vx_u8m2(__riscv_vand_vx_u8m2(scales_mins_hi, 0xC0, 64), 2, 64);
1042                    }
1043                    vuint16m4_t scales = __riscv_vzext_vf2_u16m4(__riscv_vor_vv_u8m2(scales_hi, scales_lo, 64), 64);
1044                    vint16m4_t mins = __riscv_vreinterpret_v_u16m4_i16m4(__riscv_vzext_vf2_u16m4(__riscv_vor_vv_u8m2(mins_hi, mins_lo, 64), 64));
1045
1046                    // Reduce the mins and multiply with `dmin`.
1047                    //
1048                    // Correct in `sumf`.
1049                    vint32m2_t bsums_0 = __riscv_vmv_v_x_i32m2(0, 16);
1050                    vint32m2_t bsums_1 = __riscv_vmv_v_x_i32m2(0, 16);
1051                    vint32m2_t bsums_2 = __riscv_vmv_v_x_i32m2(0, 16);
1052                    vint32m2_t bsums_3 = __riscv_vmv_v_x_i32m2(0, 16);
1053
1054                    bsums_0 = __riscv_vwmacc_vx_i32m2(bsums_0,
1055                                a_ptr[l].bsums[j * 32] + a_ptr[l].bsums[j * 32 + 4],
1056                                __riscv_vget_v_i16m4_i16m1(mins, 0), 16);
1057                    bsums_1 = __riscv_vwmacc_vx_i32m2(bsums_1,
1058                                a_ptr[l].bsums[j * 32 + 1] + a_ptr[l].bsums[j * 32 + 5],
1059                                __riscv_vget_v_i16m4_i16m1(mins, 0), 16);
1060                    bsums_2 = __riscv_vwmacc_vx_i32m2(bsums_2,
1061                                a_ptr[l].bsums[j * 32 + 2] + a_ptr[l].bsums[j * 32 + 6],
1062                                __riscv_vget_v_i16m4_i16m1(mins, 0), 16);
1063                    bsums_3 = __riscv_vwmacc_vx_i32m2(bsums_3,
1064                                a_ptr[l].bsums[j * 32 + 3] + a_ptr[l].bsums[j * 32 + 7],
1065                                __riscv_vget_v_i16m4_i16m1(mins, 0), 16);
1066                    bsums_0 = __riscv_vwmacc_vx_i32m2(bsums_0,
1067                                a_ptr[l].bsums[j * 32 + 8] + a_ptr[l].bsums[j * 32 + 8 + 4],
1068                                __riscv_vget_v_i16m4_i16m1(mins, 1), 16);
1069                    bsums_1 = __riscv_vwmacc_vx_i32m2(bsums_1,
1070                                a_ptr[l].bsums[j * 32 + 8 + 1] + a_ptr[l].bsums[j * 32 + 8 + 5],
1071                                __riscv_vget_v_i16m4_i16m1(mins, 1), 16);
1072                    bsums_2 = __riscv_vwmacc_vx_i32m2(bsums_2,
1073                                a_ptr[l].bsums[j * 32 + 8 + 2] + a_ptr[l].bsums[j * 32 + 8 + 6],
1074                                __riscv_vget_v_i16m4_i16m1(mins, 1), 16);
1075                    bsums_3 = __riscv_vwmacc_vx_i32m2(bsums_3,
1076                                a_ptr[l].bsums[j * 32 + 8 + 3] + a_ptr[l].bsums[j * 32 + 8 + 7],
1077                                __riscv_vget_v_i16m4_i16m1(mins, 1), 16);
1078                    bsums_0 = __riscv_vwmacc_vx_i32m2(bsums_0,
1079                                a_ptr[l].bsums[j * 32 + 16] + a_ptr[l].bsums[j * 32 + 16 + 4],
1080                                __riscv_vget_v_i16m4_i16m1(mins, 2), 16);
1081                    bsums_1 = __riscv_vwmacc_vx_i32m2(bsums_1,
1082                                a_ptr[l].bsums[j * 32 + 16 + 1] + a_ptr[l].bsums[j * 32 + 16 + 5],
1083                                __riscv_vget_v_i16m4_i16m1(mins, 2), 16);
1084                    bsums_2 = __riscv_vwmacc_vx_i32m2(bsums_2,
1085                                a_ptr[l].bsums[j * 32 + 16 + 2] + a_ptr[l].bsums[j * 32 + 16 + 6],
1086                                __riscv_vget_v_i16m4_i16m1(mins, 2), 16);
1087                    bsums_3 = __riscv_vwmacc_vx_i32m2(bsums_3,
1088                                a_ptr[l].bsums[j * 32 + 16 + 3] + a_ptr[l].bsums[j * 32 + 16 + 7],
1089                                __riscv_vget_v_i16m4_i16m1(mins, 2), 16);
1090                    bsums_0 = __riscv_vwmacc_vx_i32m2(bsums_0,
1091                                a_ptr[l].bsums[j * 32 + 24 + 0] + a_ptr[l].bsums[j * 32 + 24 + 4],
1092                                __riscv_vget_v_i16m4_i16m1(mins, 3), 16);
1093                    bsums_1 = __riscv_vwmacc_vx_i32m2(bsums_1,
1094                                a_ptr[l].bsums[j * 32 + 24 + 1] + a_ptr[l].bsums[j * 32 + 24 + 5],
1095                                __riscv_vget_v_i16m4_i16m1(mins, 3), 16);
1096                    bsums_2 = __riscv_vwmacc_vx_i32m2(bsums_2,
1097                                a_ptr[l].bsums[j * 32 + 24 + 2] + a_ptr[l].bsums[j * 32 + 24 + 6],
1098                                __riscv_vget_v_i16m4_i16m1(mins, 3), 16);
1099                    bsums_3 = __riscv_vwmacc_vx_i32m2(bsums_3,
1100                                a_ptr[l].bsums[j * 32 + 24 + 3] + a_ptr[l].bsums[j * 32 + 24 + 7],
1101                                __riscv_vget_v_i16m4_i16m1(mins, 3), 16);
1102
1103                    const vfloat32m2_t dmins_d_0 = __riscv_vfmul_vf_f32m2(dmins, a_ptr[l].d[0], 16);
1104                    const vfloat32m2_t dmins_d_1 = __riscv_vfmul_vf_f32m2(dmins, a_ptr[l].d[1], 16);
1105                    const vfloat32m2_t dmins_d_2 = __riscv_vfmul_vf_f32m2(dmins, a_ptr[l].d[2], 16);
1106                    const vfloat32m2_t dmins_d_3 = __riscv_vfmul_vf_f32m2(dmins, a_ptr[l].d[3], 16);
1107
1108                    sumf_0 = __riscv_vfsub_vv_f32m2(sumf_0, __riscv_vfmul_vv_f32m2(dmins_d_0, __riscv_vfcvt_f_x_v_f32m2(bsums_0, 16), 16), 16);
1109                    sumf_1 = __riscv_vfsub_vv_f32m2(sumf_1, __riscv_vfmul_vv_f32m2(dmins_d_1, __riscv_vfcvt_f_x_v_f32m2(bsums_1, 16), 16), 16);
1110                    sumf_2 = __riscv_vfsub_vv_f32m2(sumf_2, __riscv_vfmul_vv_f32m2(dmins_d_2, __riscv_vfcvt_f_x_v_f32m2(bsums_2, 16), 16), 16);
1111                    sumf_3 = __riscv_vfsub_vv_f32m2(sumf_3, __riscv_vfmul_vv_f32m2(dmins_d_3, __riscv_vfcvt_f_x_v_f32m2(bsums_3, 16), 16), 16);
1112
1113
1114                    // Accumulation for 2 sub-blocks.
1115                    //
1116                    // This might overflow, so we accumulate in two steps.
1117                    //
1118                    // Recheck.
1119                    for (int k = 0; k < 2; k++) {
1120                        // 4x16 integer accumulators
1121                        vint16m1_t sumi_0_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1122                        vint16m1_t sumi_1_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1123                        vint16m1_t sumi_2_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1124                        vint16m1_t sumi_3_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1125                        vint16m1_t sumi_0_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1126                        vint16m1_t sumi_1_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1127                        vint16m1_t sumi_2_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1128                        vint16m1_t sumi_3_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1129
1130                        for (int i = k * 16; i < k * 16 + QK4_0 / 2; i++) {
1131                            // Load `b_ptr`.
1132                            const vuint8mf2_t b_0_packed = __riscv_vle8_v_u8mf2(&b_ptr[l].qs[j * 1024 + i * 16], 16);
1133                            const vint8mf2_t b_s_0 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(b_0_packed, 0xF, 16));
1134                            const vint8mf2_t b_s_1 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vsrl_vx_u8mf2(b_0_packed, 4, 16));
1135
1136                            sumi_0_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_0_s_0_16, a_ptr[l].qs[j * 512 + i * 4], b_s_0, 16);
1137                            sumi_1_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_1_s_0_16, a_ptr[l].qs[j * 512 + i * 4 + 1], b_s_0, 16);
1138                            sumi_2_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_2_s_0_16, a_ptr[l].qs[j * 512 + i * 4 + 2], b_s_0, 16);
1139                            sumi_3_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_3_s_0_16, a_ptr[l].qs[j * 512 + i * 4 + 3], b_s_0, 16);
1140
1141                            sumi_0_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_0_s_1_16, a_ptr[l].qs[j * 512 + 128 + i * 4], b_s_1, 16);
1142                            sumi_1_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_1_s_1_16, a_ptr[l].qs[j * 512 + 128 + i * 4 + 1], b_s_1, 16);
1143                            sumi_2_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_2_s_1_16, a_ptr[l].qs[j * 512 + 128 + i * 4 + 2], b_s_1, 16);
1144                            sumi_3_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_3_s_1_16, a_ptr[l].qs[j * 512 + 128 + i * 4 + 3], b_s_1, 16);
1145                        }
1146
1147                        sumi_0 = __riscv_vwmacc_vv_i32m2(sumi_0,
1148                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 0)),
1149                                    sumi_0_s_0_16, 16);
1150                        sumi_0 = __riscv_vwmacc_vv_i32m2(sumi_0,
1151                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 1)),
1152                                    sumi_0_s_1_16, 16);
1153                        sumi_1 = __riscv_vwmacc_vv_i32m2(sumi_1,
1154                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 0)),
1155                                    sumi_1_s_0_16, 16);
1156                        sumi_1 = __riscv_vwmacc_vv_i32m2(sumi_1,
1157                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 1)),
1158                                    sumi_1_s_1_16, 16);
1159                        sumi_2 = __riscv_vwmacc_vv_i32m2(sumi_2,
1160                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 0)),
1161                                    sumi_2_s_0_16, 16);
1162                        sumi_2 = __riscv_vwmacc_vv_i32m2(sumi_2,
1163                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 1)),
1164                                    sumi_2_s_1_16, 16);
1165                        sumi_3 = __riscv_vwmacc_vv_i32m2(sumi_3,
1166                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 0)),
1167                                    sumi_3_s_0_16, 16);
1168                        sumi_3 = __riscv_vwmacc_vv_i32m2(sumi_3,
1169                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 1)),
1170                                    sumi_3_s_1_16, 16);
1171                    }
1172                    // Accumulation for 2 sub-blocks.
1173                    //
1174                    // This might overflow, so we accumulate in two steps.
1175                    //
1176                    // Recheck.
1177                    for (int k = 0; k < 2; k++) {
1178                        // 4x16 integer accumulators
1179                        vint16m1_t sumi_0_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1180                        vint16m1_t sumi_1_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1181                        vint16m1_t sumi_2_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1182                        vint16m1_t sumi_3_s_0_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1183                        vint16m1_t sumi_0_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1184                        vint16m1_t sumi_1_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1185                        vint16m1_t sumi_2_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1186                        vint16m1_t sumi_3_s_1_16 = __riscv_vmv_v_x_i16m1(0.0f, 16);
1187
1188                        for (int i = k * 16; i < k * 16 + QK4_0 / 2; i++) {
1189                            // Load `b_ptr`.
1190                            const vuint8mf2_t b_0_packed = __riscv_vle8_v_u8mf2(&b_ptr[l].qs[j * 1024 + 512 + i * 16], 16);
1191                            const vint8mf2_t b_s_0 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(b_0_packed, 0xF, 16));
1192                            const vint8mf2_t b_s_1 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vsrl_vx_u8mf2(b_0_packed, 4, 16));
1193
1194                            sumi_0_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_0_s_0_16, a_ptr[l].qs[j * 512 + 256 + i * 4], b_s_0, 16);
1195                            sumi_1_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_1_s_0_16, a_ptr[l].qs[j * 512 + 256 + i * 4 + 1], b_s_0, 16);
1196                            sumi_2_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_2_s_0_16, a_ptr[l].qs[j * 512 + 256 + i * 4 + 2], b_s_0, 16);
1197                            sumi_3_s_0_16 = __riscv_vwmacc_vx_i16m1(sumi_3_s_0_16, a_ptr[l].qs[j * 512 + 256 + i * 4 + 3], b_s_0, 16);
1198
1199                            sumi_0_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_0_s_1_16, a_ptr[l].qs[j * 512 + 384 + i * 4], b_s_1, 16);
1200                            sumi_1_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_1_s_1_16, a_ptr[l].qs[j * 512 + 384 + i * 4 + 1], b_s_1, 16);
1201                            sumi_2_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_2_s_1_16, a_ptr[l].qs[j * 512 + 384 + i * 4 + 2], b_s_1, 16);
1202                            sumi_3_s_1_16 = __riscv_vwmacc_vx_i16m1(sumi_3_s_1_16, a_ptr[l].qs[j * 512 + 384 + i * 4 + 3], b_s_1, 16);
1203                        }
1204
1205                        sumi_0 = __riscv_vwmacc_vv_i32m2(sumi_0,
1206                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 2)),
1207                                    sumi_0_s_0_16, 16);
1208                        sumi_0 = __riscv_vwmacc_vv_i32m2(sumi_0,
1209                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 3)),
1210                                    sumi_0_s_1_16, 16);
1211                        sumi_1 = __riscv_vwmacc_vv_i32m2(sumi_1,
1212                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 2)),
1213                                    sumi_1_s_0_16, 16);
1214                        sumi_1 = __riscv_vwmacc_vv_i32m2(sumi_1,
1215                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 3)),
1216                                    sumi_1_s_1_16, 16);
1217                        sumi_2 = __riscv_vwmacc_vv_i32m2(sumi_2,
1218                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 2)),
1219                                    sumi_2_s_0_16, 16);
1220                        sumi_2 = __riscv_vwmacc_vv_i32m2(sumi_2,
1221                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 3)),
1222                                    sumi_2_s_1_16, 16);
1223                        sumi_3 = __riscv_vwmacc_vv_i32m2(sumi_3,
1224                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 2)),
1225                                    sumi_3_s_0_16, 16);
1226                        sumi_3 = __riscv_vwmacc_vv_i32m2(sumi_3,
1227                                    __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vget_v_u16m4_u16m1(scales, 3)),
1228                                    sumi_3_s_1_16, 16);
1229                    }
1230                }
1231
1232                const vfloat32m2_t b_d = __riscv_vfwcvt_f_f_v_f32m2(__riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].d, 16), 16);
1233                const vfloat32m2_t d_0 = __riscv_vfmul_vf_f32m2(b_d, a_ptr[l].d[0], 16);
1234                const vfloat32m2_t d_1 = __riscv_vfmul_vf_f32m2(b_d, a_ptr[l].d[1], 16);
1235                const vfloat32m2_t d_2 = __riscv_vfmul_vf_f32m2(b_d, a_ptr[l].d[2], 16);
1236                const vfloat32m2_t d_3 = __riscv_vfmul_vf_f32m2(b_d, a_ptr[l].d[3], 16);
1237
1238                sumf_0 = __riscv_vfmacc_vv_f32m2(sumf_0, __riscv_vfcvt_f_x_v_f32m2(sumi_0, 16), d_0, 16);
1239                sumf_1 = __riscv_vfmacc_vv_f32m2(sumf_1, __riscv_vfcvt_f_x_v_f32m2(sumi_1, 16), d_1, 16);
1240                sumf_2 = __riscv_vfmacc_vv_f32m2(sumf_2, __riscv_vfcvt_f_x_v_f32m2(sumi_2, 16), d_2, 16);
1241                sumf_3 = __riscv_vfmacc_vv_f32m2(sumf_3, __riscv_vfcvt_f_x_v_f32m2(sumi_3, 16), d_3, 16);
1242            }
1243
1244            __riscv_vse32_v_f32m2(s + (y * 4 + 0) * bs + x * 16, sumf_0, 16);
1245            __riscv_vse32_v_f32m2(s + (y * 4 + 1) * bs + x * 16, sumf_1, 16);
1246            __riscv_vse32_v_f32m2(s + (y * 4 + 2) * bs + x * 16, sumf_2, 16);
1247            __riscv_vse32_v_f32m2(s + (y * 4 + 3) * bs + x * 16, sumf_3, 16);
1248        }
1249    }
1250}
1251
1252void ggml_gemm_iq4_nl_16x1_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
1253    const int qk = QK8_0;
1254    const int nb = n / qk;
1255    const int ncols_interleaved = 16;
1256    const int blocklen = 1;
1257
1258    assert (n % qk == 0);
1259    assert (nr % 4 == 0);
1260    assert (nc % ncols_interleaved == 0);
1261
1262    UNUSED(s);
1263    UNUSED(bs);
1264    UNUSED(vx);
1265    UNUSED(vy);
1266    UNUSED(nr);
1267    UNUSED(nc);
1268    UNUSED(nb);
1269    UNUSED(ncols_interleaved);
1270    UNUSED(blocklen);
1271
1272    const vint8mf2_t values = __riscv_vle8_v_i8mf2(kvalues_iq4nl, 16);
1273    for (int y = 0; y < nr / 4; y++) {
1274        const block_q8_0x4 * a_ptr = (const block_q8_0x4 *) vy + (y * nb);
1275        for (int x = 0; x < nc / ncols_interleaved; x++) {
1276            const block_iq4_nlx16 * b_ptr = (const block_iq4_nlx16 *) vx + (x * nb);
1277
1278            // 4x16 Accumulators
1279            vfloat32m2_t sumf_0 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1280            vfloat32m2_t sumf_1 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1281            vfloat32m2_t sumf_2 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1282            vfloat32m2_t sumf_3 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1283
1284            for (int l = 0; l < nb; l++) {
1285                // 4x16 integer accumulators
1286                vint32m2_t sumi_0 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1287                vint32m2_t sumi_1 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1288                vint32m2_t sumi_2 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1289                vint32m2_t sumi_3 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1290
1291                // Accumulation loop.
1292                for (int i = 0; i < QK4_NL / 2; i++) {
1293                    // Load `b_ptr`.
1294                    const vuint8mf2_t b_0_packed = __riscv_vle8_v_u8mf2((const uint8_t *)&b_ptr[l].qs[i * 16], 16);
1295                    const vint8mf2_t b_0_lo = __riscv_vrgather_vv_i8mf2(values, __riscv_vand_vx_u8mf2(b_0_packed, 0xf, 16), 16);
1296                    const vint8mf2_t b_0_hi = __riscv_vrgather_vv_i8mf2(values, __riscv_vsrl_vx_u8mf2(b_0_packed, 4, 16), 16);
1297                    // const vint16m1_t b_0_lo_16 = __riscv_vwcvt_x_x_v_i16m1(b_0_lo, 16);
1298                    // const vint16m1_t b_0_hi_16 = __riscv_vwcvt_x_x_v_i16m1(b_0_hi, 16);
1299
1300                    const vint16m1_t sumi_0_lo = __riscv_vwmul_vx_i16m1(b_0_lo, a_ptr[l].qs[i * 4], 16);
1301                    const vint16m1_t sumi_1_lo = __riscv_vwmul_vx_i16m1(b_0_lo, a_ptr[l].qs[i * 4 + 1], 16);
1302                    const vint16m1_t sumi_2_lo = __riscv_vwmul_vx_i16m1(b_0_lo, a_ptr[l].qs[i * 4 + 2], 16);
1303                    const vint16m1_t sumi_3_lo = __riscv_vwmul_vx_i16m1(b_0_lo, a_ptr[l].qs[i * 4 + 3], 16);
1304
1305                    const vint16m1_t sumi_0_hi = __riscv_vwmul_vx_i16m1(b_0_hi, a_ptr[l].qs[64 + i * 4], 16);
1306                    const vint16m1_t sumi_1_hi = __riscv_vwmul_vx_i16m1(b_0_hi, a_ptr[l].qs[64 + i * 4 + 1], 16);
1307                    const vint16m1_t sumi_2_hi = __riscv_vwmul_vx_i16m1(b_0_hi, a_ptr[l].qs[64 + i * 4 + 2], 16);
1308                    const vint16m1_t sumi_3_hi = __riscv_vwmul_vx_i16m1(b_0_hi, a_ptr[l].qs[64 + i * 4 + 3], 16);
1309
1310                    sumi_0 = __riscv_vadd_vv_i32m2(sumi_0, __riscv_vwadd_vv_i32m2(sumi_0_lo, sumi_0_hi, 16), 16);
1311                    sumi_1 = __riscv_vadd_vv_i32m2(sumi_1, __riscv_vwadd_vv_i32m2(sumi_1_lo, sumi_1_hi, 16), 16);
1312                    sumi_2 = __riscv_vadd_vv_i32m2(sumi_2, __riscv_vwadd_vv_i32m2(sumi_2_lo, sumi_2_hi, 16), 16);
1313                    sumi_3 = __riscv_vadd_vv_i32m2(sumi_3, __riscv_vwadd_vv_i32m2(sumi_3_lo, sumi_3_hi, 16), 16);
1314                }
1315
1316                const vfloat16m1_t b_d = __riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].d, 16);
1317                const vfloat32m2_t d_0 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[0], 16);
1318                const vfloat32m2_t d_1 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[1], 16);
1319                const vfloat32m2_t d_2 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[2], 16);
1320                const vfloat32m2_t d_3 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[3], 16);
1321
1322                sumf_0 = __riscv_vfmacc_vv_f32m2(sumf_0, __riscv_vfcvt_f_x_v_f32m2(sumi_0, 16), d_0, 16);
1323                sumf_1 = __riscv_vfmacc_vv_f32m2(sumf_1, __riscv_vfcvt_f_x_v_f32m2(sumi_1, 16), d_1, 16);
1324                sumf_2 = __riscv_vfmacc_vv_f32m2(sumf_2, __riscv_vfcvt_f_x_v_f32m2(sumi_2, 16), d_2, 16);
1325                sumf_3 = __riscv_vfmacc_vv_f32m2(sumf_3, __riscv_vfcvt_f_x_v_f32m2(sumi_3, 16), d_3, 16);
1326            }
1327
1328            __riscv_vse32_v_f32m2(s + (y * 4 + 0) * bs + x * 16, sumf_0, 16);
1329            __riscv_vse32_v_f32m2(s + (y * 4 + 1) * bs + x * 16, sumf_1, 16);
1330            __riscv_vse32_v_f32m2(s + (y * 4 + 2) * bs + x * 16, sumf_2, 16);
1331            __riscv_vse32_v_f32m2(s + (y * 4 + 3) * bs + x * 16, sumf_3, 16);
1332        }
1333    }
1334}
1335
1336void ggml_gemm_q8_0_16x1_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
1337    const int qk = QK8_0;
1338    const int nb = n / qk;
1339    const int ncols_interleaved = 16;
1340    const int blocklen = 1;
1341
1342    assert (n % qk == 0);
1343    assert (nr % 4 == 0);
1344    assert (nc % ncols_interleaved == 0);
1345
1346    UNUSED(s);
1347    UNUSED(bs);
1348    UNUSED(vx);
1349    UNUSED(vy);
1350    UNUSED(nr);
1351    UNUSED(nc);
1352    UNUSED(nb);
1353    UNUSED(ncols_interleaved);
1354    UNUSED(blocklen);
1355
1356    for (int y = 0; y < nr / 4; y++) {
1357        const block_q8_0x4 * a_ptr = (const block_q8_0x4 *) vy + (y * nb);
1358        for (int x = 0; x < nc / ncols_interleaved; x++) {
1359            const block_q8_0x16 * b_ptr = (const block_q8_0x16 *) vx + (x * nb);
1360
1361            // 4x16 Accumulators
1362            vfloat32m2_t sumf_0 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1363            vfloat32m2_t sumf_1 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1364            vfloat32m2_t sumf_2 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1365            vfloat32m2_t sumf_3 = __riscv_vfmv_v_f_f32m2(0.0f, 16);
1366
1367            for (int l = 0; l < nb; l++) {
1368                // 4x16 Integer Accumulators
1369                vint32m2_t sumi_0 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1370                vint32m2_t sumi_1 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1371                vint32m2_t sumi_2 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1372                vint32m2_t sumi_3 = __riscv_vmv_v_x_i32m2(0.0f, 16);
1373
1374                // Accumulation loop.
1375                for (int i = 0; i < QK8_0; i++) {
1376                    // Load `b_ptr`.
1377                    const vint8mf2_t b_0 = __riscv_vle8_v_i8mf2((const int8_t *)&b_ptr[l].qs[i * 16], 16);
1378                    // const vint16m1_t b_0_16 = __riscv_vwcvt_x_x_v_i16m1(b_0, 16);
1379
1380                    sumi_0 = __riscv_vwadd_wv_i32m2(sumi_0, __riscv_vwmul_vx_i16m1(b_0, a_ptr[l].qs[i * 4 + 0], 16), 16);
1381                    sumi_1 = __riscv_vwadd_wv_i32m2(sumi_1, __riscv_vwmul_vx_i16m1(b_0, a_ptr[l].qs[i * 4 + 1], 16), 16);
1382                    sumi_2 = __riscv_vwadd_wv_i32m2(sumi_2, __riscv_vwmul_vx_i16m1(b_0, a_ptr[l].qs[i * 4 + 2], 16), 16);
1383                    sumi_3 = __riscv_vwadd_wv_i32m2(sumi_3, __riscv_vwmul_vx_i16m1(b_0, a_ptr[l].qs[i * 4 + 3], 16), 16);
1384                }
1385
1386                const vfloat16m1_t b_d = __riscv_vle16_v_f16m1((const _Float16 *)b_ptr[l].d, 16);
1387                const vfloat32m2_t d_0 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[0], 16);
1388                const vfloat32m2_t d_1 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[1], 16);
1389                const vfloat32m2_t d_2 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[2], 16);
1390                const vfloat32m2_t d_3 = __riscv_vfwmul_vf_f32m2(b_d, *(const _Float16 *)&a_ptr[l].d[3], 16);
1391
1392                sumf_0 = __riscv_vfmacc_vv_f32m2(sumf_0, __riscv_vfcvt_f_x_v_f32m2(sumi_0, 16), d_0, 16);
1393                sumf_1 = __riscv_vfmacc_vv_f32m2(sumf_1, __riscv_vfcvt_f_x_v_f32m2(sumi_1, 16), d_1, 16);
1394                sumf_2 = __riscv_vfmacc_vv_f32m2(sumf_2, __riscv_vfcvt_f_x_v_f32m2(sumi_2, 16), d_2, 16);
1395                sumf_3 = __riscv_vfmacc_vv_f32m2(sumf_3, __riscv_vfcvt_f_x_v_f32m2(sumi_3, 16), d_3, 16);
1396            }
1397
1398            __riscv_vse32_v_f32m2(s + (y * 4 + 0) * bs + x * 16, sumf_0, 16);
1399            __riscv_vse32_v_f32m2(s + (y * 4 + 1) * bs + x * 16, sumf_1, 16);
1400            __riscv_vse32_v_f32m2(s + (y * 4 + 2) * bs + x * 16, sumf_2, 16);
1401            __riscv_vse32_v_f32m2(s + (y * 4 + 3) * bs + x * 16, sumf_3, 16);
1402        }
1403    }
1404}
1405
1406void ggml_gemm_q2_K_16x1_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy, int nr, int nc) {
1407    assert(n % QK_K == 0);
1408    const int num_k_blocks = n / QK_K;
1409    const int N_ROWS_TILE = 4;
1410    const int N_COLS_TILE = 16;
1411    assert(nr % N_ROWS_TILE == 0);
1412    assert(nc % N_COLS_TILE == 0);
1413
1414    const size_t vl = __riscv_vsetvl_e32m2(N_COLS_TILE);
1415    // --- Tiling Loops ---
1416#pragma GCC unroll 1
1417    for (int row_tile = 0; row_tile < nr; row_tile += N_ROWS_TILE) {
1418#pragma GCC unroll 1
1419        for (int col_tile = 0; col_tile < nc; col_tile += N_COLS_TILE) {
1420            // Base Pointers
1421            const block_q8_Kx4* lhs_base_ptr = (const block_q8_Kx4*)vy + (row_tile / N_ROWS_TILE) * num_k_blocks;
1422            const block_q2_Kx16* rhs_base_ptr = (const block_q2_Kx16*)vx + (col_tile / N_COLS_TILE) * num_k_blocks;
1423
1424            // Persistent Float Accumulators
1425            vfloat32m2_t v_sumf_0 = __riscv_vfmv_v_f_f32m2(0.0f, vl);
1426            vfloat32m2_t v_sumf_1 = __riscv_vfmv_v_f_f32m2(0.0f, vl);
1427            vfloat32m2_t v_sumf_2 = __riscv_vfmv_v_f_f32m2(0.0f, vl);
1428            vfloat32m2_t v_sumf_3 = __riscv_vfmv_v_f_f32m2(0.0f, vl);
1429
1430            // --- Super-Block Loop (K=0..255) ---
1431#pragma GCC unroll 1
1432            for (int k_block = 0; k_block < num_k_blocks; ++k_block) {
1433                const block_q8_Kx4* lhs_current = &lhs_base_ptr[k_block];
1434                const block_q2_Kx16* rhs_current = &rhs_base_ptr[k_block];
1435
1436                // 1. Load Global Min Scales (Keep as F16/LMUL=1 to save registers)
1437                vfloat16m1_t v_g_min_f16 = __riscv_vle16_v_f16m1((const _Float16*)rhs_current->dmin, vl);
1438                vfloat32m2_t v_g_min_base = __riscv_vfwcvt_f_f_v_f32m2(v_g_min_f16, vl);
1439
1440                // 2. Initialize Integer Accumulators
1441                vint32m2_t v_isum_0 = __riscv_vmv_v_x_i32m2(0, vl);
1442                vint32m2_t v_isum_1 = __riscv_vmv_v_x_i32m2(0, vl);
1443                vint32m2_t v_isum_2 = __riscv_vmv_v_x_i32m2(0, vl);
1444                vint32m2_t v_isum_3 = __riscv_vmv_v_x_i32m2(0, vl);
1445
1446                const uint8_t* rhs_qs_ptr = rhs_current->qs;
1447                const uint8_t* rhs_sc_ptr = rhs_current->scales;
1448                const int8_t*  lhs_qs_ptr = lhs_current->qs;
1449
1450                // --- Phase Loop (4 phases x 64 elements) ---
1451#pragma GCC unroll 1
1452                for (int phase = 0; phase < 4; ++phase) {
1453
1454                    // A. Load Scales/Mins for the 4 interleaved sub-blocks
1455                    vuint16m1_t v_d_sb_0, v_d_sb_1, v_d_sb_2, v_d_sb_3;
1456                    vuint16m1_t v_m_sb_0, v_m_sb_1, v_m_sb_2, v_m_sb_3;
1457
1458                    // Unrolled Load Logic
1459                    {
1460                        vuint8mf2_t v_raw;
1461                        // Sub-block 0
1462                        v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 0, vl);
1463                        v_d_sb_0 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
1464                        v_m_sb_0 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
1465
1466                        // Sub-block 1
1467                        v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 16, vl);
1468                        v_d_sb_1 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
1469                        v_m_sb_1 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
1470
1471                        // Sub-block 2
1472                        v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 32, vl);
1473                        v_d_sb_2 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
1474                        v_m_sb_2 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
1475
1476                        // Sub-block 3
1477                        v_raw = __riscv_vle8_v_u8mf2(rhs_sc_ptr + 48, vl);
1478                        v_d_sb_3 = __riscv_vzext_vf2_u16m1(__riscv_vand_vx_u8mf2(v_raw, 0xF, vl), vl);
1479                        v_m_sb_3 = __riscv_vzext_vf2_u16m1(__riscv_vsrl_vx_u8mf2(v_raw, 4, vl), vl);
1480
1481                        rhs_sc_ptr += 64;
1482                    }
1483
1484                    int base_k_phase = (phase < 2) ? (phase * 16) : (128 + (phase-2)*16);
1485                    int k_offsets[4] = {0, 32, 64, 96};
1486
1487                    // B. Inner Dot Product Loop
1488#pragma GCC unroll 1
1489                    for (int l = 0; l < 16; ++l) {
1490                        vuint8mf2_t v_rhs_data = __riscv_vle8_v_u8mf2(rhs_qs_ptr, vl);
1491                        rhs_qs_ptr += 16;
1492
1493                        // Unroll over 4 sub-blocks (0, 1, 2, 3 relative to phase)
1494
1495                        // --- Sub-block 0 ---
1496                        {
1497                            vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(v_rhs_data, 3, vl);
1498                            vint16m1_t v_w = __riscv_vmul_vv_i16m1(
1499                                __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
1500                                __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_0), vl);
1501
1502                            const int8_t* q8 = &lhs_qs_ptr[(base_k_phase + k_offsets[0] + l) * 4];
1503                            v_isum_0 = __riscv_vwmacc_vx_i32m2(v_isum_0, (int16_t)q8[0], v_w, vl);
1504                            v_isum_1 = __riscv_vwmacc_vx_i32m2(v_isum_1, (int16_t)q8[1], v_w, vl);
1505                            v_isum_2 = __riscv_vwmacc_vx_i32m2(v_isum_2, (int16_t)q8[2], v_w, vl);
1506                            v_isum_3 = __riscv_vwmacc_vx_i32m2(v_isum_3, (int16_t)q8[3], v_w, vl);
1507                        }
1508                        // --- Sub-block 1 ---
1509                        {
1510                            vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(v_rhs_data, 2, vl), 3, vl);
1511                            vint16m1_t v_w = __riscv_vmul_vv_i16m1(
1512                                __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
1513                                __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_1), vl);
1514
1515                            const int8_t* q8 = &lhs_qs_ptr[(base_k_phase + k_offsets[1] + l) * 4];
1516                            v_isum_0 = __riscv_vwmacc_vx_i32m2(v_isum_0, (int16_t)q8[0], v_w, vl);
1517                            v_isum_1 = __riscv_vwmacc_vx_i32m2(v_isum_1, (int16_t)q8[1], v_w, vl);
1518                            v_isum_2 = __riscv_vwmacc_vx_i32m2(v_isum_2, (int16_t)q8[2], v_w, vl);
1519                            v_isum_3 = __riscv_vwmacc_vx_i32m2(v_isum_3, (int16_t)q8[3], v_w, vl);
1520                        }
1521                        // --- Sub-block 2 ---
1522                        {
1523                            vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(v_rhs_data, 4, vl), 3, vl);
1524                            vint16m1_t v_w = __riscv_vmul_vv_i16m1(
1525                                __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
1526                                __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_2), vl);
1527
1528                            const int8_t* q8 = &lhs_qs_ptr[(base_k_phase + k_offsets[2] + l) * 4];
1529                            v_isum_0 = __riscv_vwmacc_vx_i32m2(v_isum_0, (int16_t)q8[0], v_w, vl);
1530                            v_isum_1 = __riscv_vwmacc_vx_i32m2(v_isum_1, (int16_t)q8[1], v_w, vl);
1531                            v_isum_2 = __riscv_vwmacc_vx_i32m2(v_isum_2, (int16_t)q8[2], v_w, vl);
1532                            v_isum_3 = __riscv_vwmacc_vx_i32m2(v_isum_3, (int16_t)q8[3], v_w, vl);
1533                        }
1534                        // --- Sub-block 3 ---
1535                        {
1536                            vuint8mf2_t v_q2 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(v_rhs_data, 6, vl), 3, vl);
1537                            vint16m1_t v_w = __riscv_vmul_vv_i16m1(
1538                                __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(v_q2, vl)),
1539                                __riscv_vreinterpret_v_u16m1_i16m1(v_d_sb_3), vl);
1540
1541                            const int8_t* q8 = &lhs_qs_ptr[(base_k_phase + k_offsets[3] + l) * 4];
1542                            v_isum_0 = __riscv_vwmacc_vx_i32m2(v_isum_0, (int16_t)q8[0], v_w, vl);
1543                            v_isum_1 = __riscv_vwmacc_vx_i32m2(v_isum_1, (int16_t)q8[1], v_w, vl);
1544                            v_isum_2 = __riscv_vwmacc_vx_i32m2(v_isum_2, (int16_t)q8[2], v_w, vl);
1545                            v_isum_3 = __riscv_vwmacc_vx_i32m2(v_isum_3, (int16_t)q8[3], v_w, vl);
1546                        }
1547                    }
1548
1549                    // C CORRECTION
1550                    int sb_base_abs = base_k_phase / 16;
1551
1552                    // --- Correction Sub-block 0 ---
1553                    {
1554                        int sb_abs = sb_base_abs + (k_offsets[0] / 16);
1555                        vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_0);
1556
1557                        // Row 0
1558                        vfloat32m2_t v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[0], vl);
1559                        vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 0], vl);
1560                        vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1561                        v_sumf_0 = __riscv_vfsub_vv_f32m2(v_sumf_0, vf_c, vl);
1562
1563                        // Row 1
1564                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[1], vl);
1565                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 1], vl);
1566                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1567                        v_sumf_1 = __riscv_vfsub_vv_f32m2(v_sumf_1, vf_c, vl);
1568
1569                        // Row 2
1570                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[2], vl);
1571                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 2], vl);
1572                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1573                        v_sumf_2 = __riscv_vfsub_vv_f32m2(v_sumf_2, vf_c, vl);
1574
1575                        // Row 3
1576                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[3], vl);
1577                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 3], vl);
1578                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1579                        v_sumf_3 = __riscv_vfsub_vv_f32m2(v_sumf_3, vf_c, vl);
1580                    }
1581
1582                    // --- Correction Sub-block 1 ---
1583                    {
1584                        int sb_abs = sb_base_abs + (k_offsets[1] / 16);
1585                        vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_1);
1586
1587                        vfloat32m2_t v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[0], vl);
1588                        vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 0], vl);
1589                        vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1590                        v_sumf_0 = __riscv_vfsub_vv_f32m2(v_sumf_0, vf_c, vl);
1591
1592                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[1], vl);
1593                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 1], vl);
1594                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1595                        v_sumf_1 = __riscv_vfsub_vv_f32m2(v_sumf_1, vf_c, vl);
1596
1597                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[2], vl);
1598                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 2], vl);
1599                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1600                        v_sumf_2 = __riscv_vfsub_vv_f32m2(v_sumf_2, vf_c, vl);
1601
1602                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[3], vl);
1603                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 3], vl);
1604                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1605                        v_sumf_3 = __riscv_vfsub_vv_f32m2(v_sumf_3, vf_c, vl);
1606                    }
1607
1608                    // --- Correction Sub-block 2 ---
1609                    {
1610                        int sb_abs = sb_base_abs + (k_offsets[2] / 16);
1611                        vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_2);
1612
1613                        vfloat32m2_t v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[0], vl);
1614                        vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 0], vl);
1615                        vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1616                        v_sumf_0 = __riscv_vfsub_vv_f32m2(v_sumf_0, vf_c, vl);
1617
1618                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[1], vl);
1619                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 1], vl);
1620                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1621                        v_sumf_1 = __riscv_vfsub_vv_f32m2(v_sumf_1, vf_c, vl);
1622
1623                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[2], vl);
1624                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 2], vl);
1625                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1626                        v_sumf_2 = __riscv_vfsub_vv_f32m2(v_sumf_2, vf_c, vl);
1627
1628                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[3], vl);
1629                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 3], vl);
1630                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1631                        v_sumf_3 = __riscv_vfsub_vv_f32m2(v_sumf_3, vf_c, vl);
1632                    }
1633
1634                    // --- Correction Sub-block 3 ---
1635                    {
1636                        int sb_abs = sb_base_abs + (k_offsets[3] / 16);
1637                        vint16m1_t v_min = __riscv_vreinterpret_v_u16m1_i16m1(v_m_sb_3);
1638
1639                        vfloat32m2_t v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[0], vl);
1640                        vint32m2_t v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 0], vl);
1641                        vfloat32m2_t vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1642                        v_sumf_0 = __riscv_vfsub_vv_f32m2(v_sumf_0, vf_c, vl);
1643
1644                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[1], vl);
1645                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 1], vl);
1646                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1647                        v_sumf_1 = __riscv_vfsub_vv_f32m2(v_sumf_1, vf_c, vl);
1648
1649                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[2], vl);
1650                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 2], vl);
1651                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1652                        v_sumf_2 = __riscv_vfsub_vv_f32m2(v_sumf_2, vf_c, vl);
1653
1654                        v_g_min = __riscv_vfmul_vf_f32m2(v_g_min_base, lhs_current->d[3], vl);
1655                        v_c = __riscv_vwmul_vx_i32m2(v_min, lhs_current->bsums[sb_abs * 4 + 3], vl);
1656                        vf_c = __riscv_vfmul_vv_f32m2(__riscv_vfcvt_f_x_v_f32m2(v_c, vl), v_g_min, vl);
1657                        v_sumf_3 = __riscv_vfsub_vv_f32m2(v_sumf_3, vf_c, vl);
1658                    }
1659
1660                } // End Phase Loop
1661
1662                // --- Apply Main Scales ---
1663                vfloat16m1_t v_g_all_f16 = __riscv_vle16_v_f16m1((const _Float16*)rhs_current->d, vl);
1664                vfloat32m2_t v_g_all_base = __riscv_vfwcvt_f_f_v_f32m2(v_g_all_f16, vl);
1665
1666                {
1667                    vfloat32m2_t v_g_all = __riscv_vfmul_vf_f32m2(v_g_all_base, lhs_current->d[0], vl);
1668                    vfloat32m2_t v_sum = __riscv_vfcvt_f_x_v_f32m2(v_isum_0, vl);
1669                    v_sum = __riscv_vfmul_vv_f32m2(v_sum, v_g_all, vl);
1670                    v_sumf_0 = __riscv_vfadd_vv_f32m2(v_sumf_0, v_sum, vl);
1671                }
1672                // Row 1
1673                {
1674                    vfloat32m2_t v_g_all = __riscv_vfmul_vf_f32m2(v_g_all_base, lhs_current->d[1], vl);
1675                    vfloat32m2_t v_sum = __riscv_vfcvt_f_x_v_f32m2(v_isum_1, vl);
1676                    v_sum = __riscv_vfmul_vv_f32m2(v_sum, v_g_all, vl);
1677                    v_sumf_1 = __riscv_vfadd_vv_f32m2(v_sumf_1, v_sum, vl);
1678                }
1679                // Row 2
1680                {
1681                    vfloat32m2_t v_g_all = __riscv_vfmul_vf_f32m2(v_g_all_base, lhs_current->d[2], vl);
1682                    vfloat32m2_t v_sum = __riscv_vfcvt_f_x_v_f32m2(v_isum_2, vl);
1683                    v_sum = __riscv_vfmul_vv_f32m2(v_sum, v_g_all, vl);
1684                    v_sumf_2 = __riscv_vfadd_vv_f32m2(v_sumf_2, v_sum, vl);
1685                }
1686                // Row 3
1687                {
1688                    vfloat32m2_t v_g_all = __riscv_vfmul_vf_f32m2(v_g_all_base, lhs_current->d[3], vl);
1689                    vfloat32m2_t v_sum = __riscv_vfcvt_f_x_v_f32m2(v_isum_3, vl);
1690                    v_sum = __riscv_vfmul_vv_f32m2(v_sum, v_g_all, vl);
1691                    v_sumf_3 = __riscv_vfadd_vv_f32m2(v_sumf_3, v_sum, vl);
1692                }
1693
1694            } // End K-Block
1695
1696            __riscv_vse32_v_f32m2(s + (row_tile + 0) * bs + col_tile, v_sumf_0, vl);
1697            __riscv_vse32_v_f32m2(s + (row_tile + 1) * bs + col_tile, v_sumf_1, vl);
1698            __riscv_vse32_v_f32m2(s + (row_tile + 2) * bs + col_tile, v_sumf_2, vl);
1699            __riscv_vse32_v_f32m2(s + (row_tile + 3) * bs + col_tile, v_sumf_3, vl);
1700        }
1701    }
1702}
1703#endif