char-fork/llama.cpp

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

rehan-10xengineerggml-cpu: extend RVV quantization vec dot to higher VLENs (#22754)3c7450cee

char/aliceai-t5-moe
287.2 KiB6596 linesraw
1#define GGML_COMMON_IMPL_C
2#include "ggml-common.h"
3#include "ggml-quants.h"
4#include "ggml-impl.h"
5#include "ggml-cpu.h"
6#include "simd-mappings.h"
7
8#include "../../quants.h"
9#include "../../ggml-cpu-impl.h"
10
11#include <math.h>
12#include <string.h>
13#include <assert.h>
14#include <float.h>
15#include <stdlib.h> // for qsort
16#include <stdio.h>  // for GGML_ASSERT
17
18#ifdef _MSC_VER
19#define NOINLINE __declspec(noinline)
20#else
21#define NOINLINE __attribute__((__noinline__))
22#endif
23
24#define GROUP_MAX_EPS 1e-15f
25#define GROUP_MAX_EPS_IQ3_XXS 1e-8f
26#define GROUP_MAX_EPS_IQ2_S 1e-8f
27#define GROUP_MAX_EPS_IQ1_M 1e-7f
28#define GROUP_MAX_EPS_IQ1_S 1e-12f
29
30#define UNUSED GGML_UNUSED
31
32void quantize_row_q8_0(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) {
33    assert(QK8_0 == 32);
34    assert(k % QK8_0 == 0);
35    const int nb = k / QK8_0;
36
37    block_q8_0 * GGML_RESTRICT y = vy;
38
39#if defined(__riscv_v)
40
41    size_t vl = QK8_0;
42
43    for (int i = 0; i < nb; i++) {
44        // load elements
45        vfloat32m8_t v_x   = __riscv_vle32_v_f32m8(x+i*QK8_0, vl);
46
47        vfloat32m8_t vfabs = __riscv_vfabs_v_f32m8(v_x, vl);
48        vfloat32m1_t tmp   = __riscv_vfmv_v_f_f32m1(0.0f, vl);
49        vfloat32m1_t vmax  = __riscv_vfredmax_vs_f32m8_f32m1(vfabs, tmp, vl);
50        float amax = __riscv_vfmv_f_s_f32m1_f32(vmax);
51
52        const float d = amax / ((1 << 7) - 1);
53        const float id = d ? 1.0f/d : 0.0f;
54
55        y[i].d = GGML_CPU_FP32_TO_FP16(d);
56
57        vfloat32m8_t x0 = __riscv_vfmul_vf_f32m8(v_x, id, vl);
58
59        // convert to integer
60        vint16m4_t   vi = __riscv_vfncvt_x_f_w_i16m4(x0, vl);
61        vint8m2_t    vs = __riscv_vncvt_x_x_w_i8m2(vi, vl);
62
63        // store result
64        __riscv_vse8_v_i8m2(y[i].qs , vs, vl);
65    }
66#else
67    GGML_UNUSED(nb);
68    // scalar
69    quantize_row_q8_0_ref(x, y, k);
70#endif
71}
72
73void quantize_row_q8_1(const float * GGML_RESTRICT x, void * GGML_RESTRICT vy, int64_t k) {
74    assert(k % QK8_1 == 0);
75    const int nb = k / QK8_1;
76
77    block_q8_1 * GGML_RESTRICT y = vy;
78
79#if defined(__riscv_v)
80
81    size_t vl = QK8_1;
82
83    for (int i = 0; i < nb; i++) {
84        // load elements
85        vfloat32m8_t v_x   = __riscv_vle32_v_f32m8(x+i*QK8_1, vl);
86
87        vfloat32m8_t vfabs = __riscv_vfabs_v_f32m8(v_x, vl);
88        vfloat32m1_t tmp   = __riscv_vfmv_v_f_f32m1(0.0, vl);
89        vfloat32m1_t vmax  = __riscv_vfredmax_vs_f32m8_f32m1(vfabs, tmp, vl);
90        float amax = __riscv_vfmv_f_s_f32m1_f32(vmax);
91
92        const float d  = amax / ((1 << 7) - 1);
93        const float id = d ? 1.0f/d : 0.0f;
94
95        y[i].d = GGML_CPU_FP32_TO_FP16(d);
96
97        vfloat32m8_t x0 = __riscv_vfmul_vf_f32m8(v_x, id, vl);
98
99        // convert to integer
100        vint16m4_t   vi = __riscv_vfncvt_x_f_w_i16m4(x0, vl);
101        vint8m2_t    vs = __riscv_vncvt_x_x_w_i8m2(vi, vl);
102
103        // store result
104        __riscv_vse8_v_i8m2(y[i].qs , vs, vl);
105
106        // compute sum for y[i].s
107        vint16m1_t tmp2 = __riscv_vmv_v_x_i16m1(0, vl);
108        vint16m1_t vwrs = __riscv_vwredsum_vs_i8m2_i16m1(vs, tmp2, vl);
109
110        // set y[i].s
111        int sum = __riscv_vmv_x_s_i16m1_i16(vwrs);
112        y[i].s = GGML_CPU_FP32_TO_FP16(sum*d);
113    }
114
115#else
116    GGML_UNUSED(nb);
117    // scalar
118    quantize_row_q8_1_ref(x, y, k);
119#endif
120}
121
122void quantize_row_q8_K(const float * GGML_RESTRICT x, void * GGML_RESTRICT y, int64_t k) {
123    assert(k % QK_K == 0);
124    size_t nb = k / QK_K;
125
126#if defined __riscv_v
127    block_q8_K * y_blocks = (block_q8_K *)y;
128    const size_t vlmax_f32m8 = __riscv_vsetvlmax_e32m8();
129
130    for (size_t i = 0; i < nb; i++) {
131        const float* x_block = x + i * QK_K;
132        block_q8_K* y_block = &y_blocks[i];
133
134        // 1. Calculate Min/Max
135        vfloat32m8_t max_v = __riscv_vfmv_v_f_f32m8(-__builtin_inff(), vlmax_f32m8);
136        vfloat32m8_t min_v = __riscv_vfmv_v_f_f32m8(__builtin_inff(), vlmax_f32m8);
137
138        size_t rem = QK_K;
139        size_t offset = 0;
140        while (rem > 0) {
141            size_t vl = __riscv_vsetvl_e32m8(rem);
142            vfloat32m8_t v_curr = __riscv_vle32_v_f32m8(x_block + offset, vl);
143            max_v = __riscv_vfmax_vv_f32m8(max_v, v_curr, vl);
144            min_v = __riscv_vfmin_vv_f32m8(min_v, v_curr, vl);
145            rem -= vl;
146            offset += vl;
147        }
148
149        vfloat32m1_t v_init_max = __riscv_vfmv_s_f_f32m1(-__builtin_inff(), 1);
150        vfloat32m1_t v_init_min = __riscv_vfmv_s_f_f32m1(__builtin_inff(), 1);
151
152        vfloat32m1_t v_scalar_max = __riscv_vfredmax_vs_f32m8_f32m1(max_v, v_init_max, vlmax_f32m8);
153        vfloat32m1_t v_scalar_min = __riscv_vfredmin_vs_f32m8_f32m1(min_v, v_init_min, vlmax_f32m8);
154
155        float max_val = __riscv_vfmv_f_s_f32m1_f32(v_scalar_max);
156        float min_val = __riscv_vfmv_f_s_f32m1_f32(v_scalar_min);
157
158        float amax = fabsf(max_val) > fabsf(min_val) ? fabsf(max_val) : fabsf(min_val);
159
160        if (amax == 0.0f) {
161            y_block->d = 0.0f;
162            memset(y_block->qs, 0, QK_K);
163            memset(y_block->bsums, 0, sizeof(y_block->bsums));
164            continue;
165        }
166
167        const float iscale = -127.f / (fabsf(max_val) > fabsf(min_val) ? max_val : min_val);
168        y_block->d = 1.0f / iscale;
169
170        // 2. Quantize and Calculate Sums
171        offset = 0;
172        rem = QK_K;
173        vint16m1_t v_zero_sum = __riscv_vmv_v_x_i16m1(0, 1);
174
175        while (rem > 0) {
176            size_t vl = __riscv_vsetvl_e32m8(rem);
177            vfloat32m8_t v_f = __riscv_vle32_v_f32m8(x_block + offset, vl);
178
179            v_f = __riscv_vfmul_vf_f32m8(v_f, iscale, vl);
180
181            vint32m8_t v_i32 = __riscv_vfcvt_x_f_v_i32m8_rm(v_f, __RISCV_FRM_RNE, vl);
182            vint16m4_t v_i16 = __riscv_vnclip_wx_i16m4(v_i32, 0, __RISCV_VXRM_RNE, vl);
183            vint8m2_t v_q = __riscv_vnclip_wx_i8m2(v_i16, 0, __RISCV_VXRM_RNE, vl);
184
185            __riscv_vse8_v_i8m2(y_block->qs + offset, v_q, vl);
186
187            // first iteration clear
188
189            int sum_idx;
190            vint8m1_t chunk_m1;
191            vint16m1_t v_sum;
192            sum_idx = offset / 16;
193            chunk_m1 = __riscv_vget_v_i8m2_i8m1(v_q, 0);
194            v_sum = __riscv_vwredsum_vs_i8m1_i16m1(chunk_m1, v_zero_sum, 16);
195            y_block->bsums[sum_idx] = (int16_t)__riscv_vmv_x_s_i16m1_i16(v_sum);
196
197            // remaining iterations
198            vint8m2_t slid_q = v_q;
199            for (size_t k = 16; k < vl; k += 16) {
200                slid_q = __riscv_vslidedown_vx_i8m2(slid_q, 16, vl);
201
202                sum_idx = (offset + k) / 16;
203                chunk_m1 = __riscv_vget_v_i8m2_i8m1(slid_q, 0);
204
205                v_sum = __riscv_vwredsum_vs_i8m1_i16m1(chunk_m1, v_zero_sum, 16);
206                y_block->bsums[sum_idx] =(int16_t)__riscv_vmv_x_s_i16m1_i16(v_sum);
207            }
208
209            rem -= vl;
210            offset += vl;
211        }
212    }
213#else
214    GGML_UNUSED(nb);
215    // scalar
216    quantize_row_q8_K_ref(x, y, k);
217#endif
218}
219
220//===================================== Dot products =================================
221
222void ggml_vec_dot_q4_0_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
223#if defined(__riscv_v)
224    const int qk = QK8_0;
225    const int nb = n / qk;
226
227    assert(n % qk == 0);
228    assert(nrc == 1);
229    UNUSED(nrc);
230    UNUSED(bx);
231    UNUSED(by);
232    UNUSED(bs);
233
234    const block_q4_0 * GGML_RESTRICT x = vx;
235    const block_q8_0 * GGML_RESTRICT y = vy;
236
237    int ib = 0;
238    float sumf = 0;
239
240    size_t vl = qk / 2;
241
242    for (; ib < nb; ++ib) {
243        // load elements
244        vuint8m1_t tx = __riscv_vle8_v_u8m1(x[ib].qs, vl);
245
246        vint8m1_t y0 = __riscv_vle8_v_i8m1(y[ib].qs, vl);
247        vint8m1_t y1 = __riscv_vle8_v_i8m1(y[ib].qs+16, vl);
248
249        // mask and store lower part of x, and then upper part
250        vuint8m1_t x_a = __riscv_vand_vx_u8m1(tx, 0x0F, vl);
251        vuint8m1_t x_l = __riscv_vsrl_vx_u8m1(tx, 0x04, vl);
252
253        vint8m1_t x_ai = __riscv_vreinterpret_v_u8m1_i8m1(x_a);
254        vint8m1_t x_li = __riscv_vreinterpret_v_u8m1_i8m1(x_l);
255
256        // subtract offset
257        vint8m1_t v0 = __riscv_vsub_vx_i8m1(x_ai, 8, vl);
258        vint8m1_t v1 = __riscv_vsub_vx_i8m1(x_li, 8, vl);
259
260        vint16m2_t vec_mul1 = __riscv_vwmul_vv_i16m2(v0, y0, vl);
261        vint16m2_t vec_mul2 = __riscv_vwmacc_vv_i16m2(vec_mul1, v1, y1, vl);
262
263        vint32m1_t vec_zero = __riscv_vmv_v_x_i32m1(0, vl);
264        vint32m1_t vs2 = __riscv_vwredsum_vs_i16m2_i32m1(vec_mul2, vec_zero, vl);
265
266        int sumi = __riscv_vmv_x_s_i32m1_i32(vs2);
267
268        sumf += sumi*GGML_CPU_FP16_TO_FP32(x[ib].d)*GGML_CPU_FP16_TO_FP32(y[ib].d);
269    }
270
271    *s = sumf;
272#else
273    ggml_vec_dot_q4_0_q8_0_generic(n, s, bs, vx, bx, vy, by, nrc);
274#endif
275}
276
277void ggml_vec_dot_q4_1_q8_1(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
278#if defined(__riscv_v)
279    const int qk = QK8_1;
280    const int nb = n / qk;
281
282    assert(n % qk == 0);
283    assert(nrc == 1);
284    UNUSED(nrc);
285    UNUSED(bx);
286    UNUSED(by);
287    UNUSED(bs);
288
289    const block_q4_1 * GGML_RESTRICT x = vx;
290    const block_q8_1 * GGML_RESTRICT y = vy;
291
292    int ib = 0;
293    float sumf = 0;
294
295    size_t vl = qk / 2;
296
297    for (; ib < nb; ++ib) {
298        // load elements
299        vuint8m1_t tx = __riscv_vle8_v_u8m1(x[ib].qs, vl);
300
301        vint8m1_t y0 = __riscv_vle8_v_i8m1(y[ib].qs, vl);
302        vint8m1_t y1 = __riscv_vle8_v_i8m1(y[ib].qs+16, vl);
303
304        // mask and store lower part of x, and then upper part
305        vuint8m1_t x_a = __riscv_vand_vx_u8m1(tx, 0x0F, vl);
306        vuint8m1_t x_l = __riscv_vsrl_vx_u8m1(tx, 0x04, vl);
307
308        vint8m1_t v0 = __riscv_vreinterpret_v_u8m1_i8m1(x_a);
309        vint8m1_t v1 = __riscv_vreinterpret_v_u8m1_i8m1(x_l);
310
311        vint16m2_t vec_mul1 = __riscv_vwmul_vv_i16m2(v0, y0, vl);
312        vint16m2_t vec_mul2 = __riscv_vwmacc_vv_i16m2(vec_mul1, v1, y1, vl);
313
314        vint32m1_t vec_zero = __riscv_vmv_v_x_i32m1(0, vl);
315        vint32m1_t vs2 = __riscv_vwredsum_vs_i16m2_i32m1(vec_mul2, vec_zero, vl);
316
317        int sumi = __riscv_vmv_x_s_i32m1_i32(vs2);
318
319        sumf += (GGML_CPU_FP16_TO_FP32(x[ib].d)*GGML_CPU_FP16_TO_FP32(y[ib].d))*sumi + GGML_CPU_FP16_TO_FP32(x[ib].m)*GGML_CPU_FP16_TO_FP32(y[ib].s);
320    }
321
322    *s = sumf;
323#else
324    ggml_vec_dot_q4_1_q8_1_generic(n, s, bs, vx, bx, vy, by, nrc);
325#endif
326}
327
328void ggml_vec_dot_q5_0_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
329#if defined(__riscv_v)
330    const int qk = QK8_0;
331    const int nb = n / qk;
332
333    int ib = 0;
334    float sumf = 0;
335
336    assert(n % qk == 0);
337    assert(qk == QK5_0);
338    assert(nrc == 1);
339    UNUSED(nrc);
340    UNUSED(bx);
341    UNUSED(by);
342    UNUSED(bs);
343
344    const block_q5_0 * GGML_RESTRICT x = vx;
345    const block_q8_0 * GGML_RESTRICT y = vy;
346
347    size_t vl;
348    size_t vlenb = __riscv_vlenb();
349
350    for (; ib < nb; ++ib) {
351        vl = qk / 2;
352        vuint8m1_t v0 = __riscv_vle8_v_u8m1(x[ib].qs, vl);
353        vint8m1_t v0l = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vand_vx_u8m1(v0, 0x0F, vl));
354        vint8m1_t v0h = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vsrl_vx_u8m1(v0, 4, vl));
355        vint8m2_t v0c;
356        if (vlenb == 16) {
357            v0c = __riscv_vcreate_v_i8m1_i8m2(v0l, v0h);
358        } else {
359            v0l = __riscv_vslideup_vx_i8m1(v0l, v0h, 16, 32);
360            v0c = __riscv_vlmul_ext_v_i8m1_i8m2(v0l);
361        }
362
363        vl = qk;
364        vbool4_t qh = __riscv_vlm_v_b4(x[ib].qh, vl);
365        qh = __riscv_vmnand_mm_b4(qh, qh, vl);
366        vint8m2_t v0f = __riscv_vsub_vx_i8m2_mu(qh, v0c, v0c, 0x10, vl);
367        vint8m2_t v1 = __riscv_vle8_v_i8m2(y[ib].qs, vl);
368        vint16m4_t mul = __riscv_vwmul_vv_i16m4(v0f, v1, vl);
369        vint32m1_t zero = __riscv_vmv_v_x_i32m1(0, vl);
370        vint32m1_t sum = __riscv_vwredsum_vs_i16m4_i32m1(mul, zero, vl);
371        int32_t sumi = __riscv_vmv_x_s_i32m1_i32(sum);
372
373        sumf += (GGML_CPU_FP16_TO_FP32(x[ib].d) * GGML_CPU_FP16_TO_FP32(y[ib].d)) * sumi;
374    }
375
376    *s = sumf;
377#else
378    ggml_vec_dot_q5_0_q8_0_generic(n, s, bs, vx, bx, vy, by, nrc);
379#endif
380}
381
382void ggml_vec_dot_q5_1_q8_1(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
383#if defined(__riscv_v)
384    const int qk = QK8_1;
385    const int nb = n / qk;
386
387    int ib = 0;
388    float sumf = 0;
389
390    assert(n % qk == 0);
391    assert(qk == QK5_1);
392    assert(nrc == 1);
393    UNUSED(nrc);
394    UNUSED(bx);
395    UNUSED(by);
396    UNUSED(bs);
397
398    const block_q5_1 * GGML_RESTRICT x = vx;
399    const block_q8_1 * GGML_RESTRICT y = vy;
400
401    size_t vl;
402    size_t vlenb = __riscv_vlenb();
403
404    for (; ib < nb; ++ib) {
405        vl = qk / 2;
406        vuint8m1_t v0 = __riscv_vle8_v_u8m1(x[ib].qs, vl);
407        vint8m1_t v0l = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vand_vx_u8m1(v0, 0x0F, vl));
408        vint8m1_t v0h = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vsrl_vx_u8m1(v0, 4, vl));
409        vint8m2_t v0c;
410        if (vlenb == 16) {
411            v0c = __riscv_vcreate_v_i8m1_i8m2(v0l, v0h);
412        } else {
413            v0l = __riscv_vslideup_vx_i8m1(v0l, v0h, 16, 32);
414            v0c = __riscv_vlmul_ext_v_i8m1_i8m2(v0l);
415        }
416
417        vl = qk;
418        vbool4_t qh = __riscv_vlm_v_b4(x[ib].qh, vl);
419        vint8m2_t v0f = __riscv_vor_vx_i8m2_mu(qh, v0c, v0c, 0x10, vl);
420        vint8m2_t v1 = __riscv_vle8_v_i8m2(y[ib].qs, vl);
421        vint16m4_t mul = __riscv_vwmul_vv_i16m4(v0f, v1, vl);
422        vint32m1_t zero = __riscv_vmv_v_x_i32m1(0, vl);
423        vint32m1_t sum = __riscv_vwredsum_vs_i16m4_i32m1(mul, zero, vl);
424        int32_t sumi = __riscv_vmv_x_s_i32m1_i32(sum);
425
426        sumf += (GGML_CPU_FP16_TO_FP32(x[ib].d)*GGML_CPU_FP16_TO_FP32(y[ib].d))*sumi + GGML_CPU_FP16_TO_FP32(x[ib].m)*GGML_CPU_FP16_TO_FP32(y[ib].s);
427    }
428
429    *s = sumf;
430#else
431    ggml_vec_dot_q5_1_q8_1_generic(n, s, bs, vx, bx, vy, by, nrc);
432#endif
433}
434
435void ggml_vec_dot_q8_0_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
436    const int qk = QK8_0;
437    const int nb = n / qk;
438
439    assert(n % qk == 0);
440    assert(nrc == 1);
441    UNUSED(nrc);
442    UNUSED(bx);
443    UNUSED(by);
444    UNUSED(bs);
445
446    const block_q8_0 * GGML_RESTRICT x = vx;
447    const block_q8_0 * GGML_RESTRICT y = vy;
448
449    int ib = 0;
450    float sumf = 0;
451
452#if defined(__riscv_v)
453    size_t vl = qk;
454
455    for (; ib < nb; ++ib) {
456        // load elements
457        vint8m2_t bx_0 = __riscv_vle8_v_i8m2(x[ib].qs, vl);
458        vint8m2_t by_0 = __riscv_vle8_v_i8m2(y[ib].qs, vl);
459
460        vint16m4_t vw_mul = __riscv_vwmul_vv_i16m4(bx_0, by_0, vl);
461
462        vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, vl);
463        vint32m1_t v_sum = __riscv_vwredsum_vs_i16m4_i32m1(vw_mul, v_zero, vl);
464
465        int sumi = __riscv_vmv_x_s_i32m1_i32(v_sum);
466
467        sumf += sumi*(GGML_CPU_FP16_TO_FP32(x[ib].d)*GGML_CPU_FP16_TO_FP32(y[ib].d));
468    }
469
470    *s = sumf;
471#else
472
473    UNUSED(nb);
474    UNUSED(x);
475    UNUSED(y);
476    UNUSED(ib);
477    UNUSED(sumf);
478
479    ggml_vec_dot_q8_0_q8_0_generic(n, s, bs, vx, bx, vy, by, nrc);
480#endif
481}
482
483#if defined(__riscv_v)
484static NOINLINE void ggml_vec_dot_q1_0_q8_0_vl256(const int n, float * GGML_RESTRICT s, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy) {
485    const int qk = QK1_0;
486    const int nb = n / qk;
487    assert(n % qk == 0);
488
489    const block_q1_0 * GGML_RESTRICT x = vx;
490    const block_q8_0 * GGML_RESTRICT y = vy;
491
492    //LMUL = 1, VLMAX = 32
493    const size_t vl32 = __riscv_vsetvl_e8m1(32);
494    assert(vl32 == 32);
495
496    const vint16m1_t zero = __riscv_vmv_v_x_i16m1(0, 1);
497
498    float sumf = 0;
499
500    for (int ib = 0; ib < nb; ++ib) {
501        const float d0 = GGML_CPU_FP16_TO_FP32(x[ib].d);
502
503        float acc = 0;
504
505        for (int k = 0; k < 4; ++k) {
506            const block_q8_0 * GGML_RESTRICT yb = &y[ib * 4 + k];
507            const vbool8_t is_not_zero = __riscv_vlm_v_b8(x[ib].qs + 4 * k, vl32);
508
509            const vint8m1_t qy = __riscv_vle8_v_i8m1(yb->qs, vl32);
510            const vint8m1_t neg_qy = __riscv_vneg_v_i8m1(qy, vl32);
511            const vint8m1_t sy = __riscv_vmerge_vvm_i8m1(neg_qy, qy, is_not_zero, vl32);
512
513            const vint16m1_t red = __riscv_vwredsum_vs_i8m1_i16m1(sy, zero, vl32);
514            acc += GGML_CPU_FP16_TO_FP32(yb->d) * (float)__riscv_vmv_x_s_i16m1_i16(red);
515        }
516
517        sumf += d0 * acc;
518    }
519
520    *s = sumf;
521}
522
523static NOINLINE void ggml_vec_dot_q1_0_q8_0_vl128(const int n, float * GGML_RESTRICT s, const void * GGML_RESTRICT vx, const void * GGML_RESTRICT vy) {
524    const int qk = QK1_0;
525    const int nb = n / qk;
526    assert(n % qk == 0);
527
528    const block_q1_0 * GGML_RESTRICT x = vx;
529    const block_q8_0 * GGML_RESTRICT y = vy;
530
531    //LMUL = 2, VLMAX = 32
532    const size_t vl32 = __riscv_vsetvl_e8m2(32);
533    assert(vl32 == 32);
534
535    const vint16m1_t zero = __riscv_vmv_v_x_i16m1(0, 1);
536
537    float sumf = 0;
538
539    for (int ib = 0; ib < nb; ++ib) {
540        const float d0 = GGML_CPU_FP16_TO_FP32(x[ib].d);
541
542        float acc = 0;
543
544        for (int k = 0; k < 4; ++k) {
545            const block_q8_0 * GGML_RESTRICT yb = &y[ib * 4 + k];
546            const vbool4_t is_not_zero = __riscv_vlm_v_b4(x[ib].qs + 4 * k, vl32);
547
548            const vint8m2_t qy = __riscv_vle8_v_i8m2(yb->qs, vl32);
549            const vint8m2_t neg_qy =__riscv_vneg_v_i8m2(qy, vl32);
550            const vint8m2_t sy = __riscv_vmerge_vvm_i8m2(neg_qy, qy, is_not_zero, vl32);
551
552            const vint16m1_t red = __riscv_vwredsum_vs_i8m2_i16m1(sy, zero, vl32);
553            acc += GGML_CPU_FP16_TO_FP32(yb->d) * (float)__riscv_vmv_x_s_i16m1_i16(red);
554        }
555
556        sumf += d0 * acc;
557    }
558
559    *s = sumf;
560}
561#endif
562
563void ggml_vec_dot_q1_0_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
564#if defined(__riscv_v)
565    assert(nrc == 1);
566
567    const size_t vlen_bits = __riscv_vlenb() * 8;
568
569    if (vlen_bits >= 256) {
570        ggml_vec_dot_q1_0_q8_0_vl256(n, s, vx, vy);
571    } else if (vlen_bits >= 128) {
572        ggml_vec_dot_q1_0_q8_0_vl128(n, s, vx, vy);
573    } else {
574        ggml_vec_dot_q1_0_q8_0_generic(n, s, bs, vx, bx, vy, by, nrc);
575    }
576#else
577    ggml_vec_dot_q1_0_q8_0_generic(n, s, bs, vx, bx, vy, by, nrc);
578#endif
579}
580
581#if defined __riscv_xtheadvector
582void ggml_vec_dot_q2_K_q8_K_xtheadvector(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
583    assert(nrc == 1);
584    UNUSED(nrc);
585    UNUSED(bx);
586    UNUSED(by);
587    UNUSED(bs);
588
589    const block_q2_K * GGML_RESTRICT x = vx;
590    const block_q8_K * GGML_RESTRICT y = vy;
591
592    const int nb = n / QK_K;
593
594    float sumf = 0;
595    uint8_t atmp[16];
596
597    for (int i = 0; i < nb; ++i) {
598        const uint8_t * q2 = x[i].qs;
599        const  int8_t * q8 = y[i].qs;
600        const uint8_t * sc = x[i].scales;
601        const float dall = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
602        const float dmin = -y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
603        uint8_t *patmp = atmp;
604        int vsums;
605        int tmp;
606        __asm__ __volatile__(
607            "th.vsetvli zero, %[vl16], e8, m1\n\t"
608            "th.vmv.v.x v8, zero\n\t"
609            "th.vlb.v v1, (%[sc])\n\t"
610            "th.vand.vi v0, v1, 0xF\n\t"
611            "th.vsrl.vi v1, v1, 4\n\t"
612            "th.vsb.v v0, (%[scale])\n\t"
613            "th.vwaddu.vx v16, v1, zero\n\t"
614            "th.vsetvli zero, %[vl16], e16, m2\n\t"
615            "th.vlh.v v2, (%[bsums])\n\t"
616            "th.vwmul.vv v4, v16, v2\n\t"
617            "th.vsetvli zero, %[vl16], e32, m4\n\t"
618            "th.vredsum.vs v8, v4, v8\n\t"
619            "th.vmv.x.s %[vsums], v8"
620            : [tmp] "=&r" (tmp), [vsums] "=&r" (vsums)
621            : [sc] "r" (sc), [scale] "r" (atmp), [bsums] "r" (y[i].bsums)
622            , [vl16] "r" (16)
623            : "memory"
624            , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
625            , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
626            , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
627            , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
628        );
629        sumf += dmin * vsums;
630        int isum = 0;
631
632        for (int j = 0; j < QK_K/128; ++j) {
633            __asm__ __volatile__(
634                "th.vsetvli zero, %[vl32], e8, m2\n\t"
635                "th.vlb.v v0, (%[q2])\n\t"
636                "th.vsrl.vi v2, v0, 2\n\t"
637                "th.vsrl.vi v4, v0, 4\n\t"
638                "th.vsrl.vi v6, v0, 6\n\t"
639                "th.vand.vi v0, v0, 0x3\n\t"
640                "th.vand.vi v2, v2, 0x3\n\t"
641                "th.vand.vi v4, v4, 0x3\n\t"
642                "th.vsetvli zero, %[vl128], e8, m8\n\t"
643                "th.vlb.v v8, (%[q8])\n\t"
644                "th.vsetvli zero, %[vl64], e8, m4\n\t"
645                "th.vwmul.vv v16, v0, v8\n\t"
646                "th.vwmul.vv v24, v4, v12\n\t"
647                "th.vsetvli zero, %[vl16], e16, m2\n\t"
648                "th.vmv.v.x v0, zero\n\t"
649                "th.vwredsum.vs v10, v16, v0\n\t"
650                "th.vwredsum.vs v9, v18, v0\n\t"
651                "th.vwredsum.vs v8, v20, v0\n\t"
652                "th.vwredsum.vs v7, v22, v0\n\t"
653                "th.vwredsum.vs v11, v24, v0\n\t"
654                "th.vwredsum.vs v12, v26, v0\n\t"
655                "th.vwredsum.vs v13, v28, v0\n\t"
656                "th.vwredsum.vs v14, v30, v0\n\t"
657                "li %[tmp], 4\n\t"
658                "th.vsetvli zero, %[tmp], e32, m1\n\t"
659                "th.vslideup.vi v10, v9, 1\n\t"
660                "th.vslideup.vi v8, v7, 1\n\t"
661                "th.vslideup.vi v11, v12, 1\n\t"
662                "th.vslideup.vi v13, v14, 1\n\t"
663                "th.vslideup.vi v10, v8, 2\n\t"
664                "th.vslideup.vi v11, v13, 2\n\t"
665                "li %[tmp], 8\n\t"
666                "th.vsetvli zero, %[tmp], e32, m2\n\t"
667                "th.vlbu.v v12, (%[scale])\n\t"
668                "th.vmul.vv v10, v10, v12\n\t"
669                "th.vredsum.vs v0, v10, v0\n\t"
670                "th.vmv.x.s %[tmp], v0\n\t"
671                "add %[isum], %[isum], %[tmp]"
672                : [tmp] "=&r" (tmp), [isum] "+&r" (isum)
673                : [q2] "r" (q2), [scale] "r" (patmp), [q8] "r" (q8)
674                , [vl16] "r" (16), [vl32] "r" (32), [vl64] "r" (64), [vl128] "r" (128)
675                : "memory"
676                , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
677                , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
678                , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
679                , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
680            );
681            q2 += 32; q8 += 128; patmp += 8;
682        }
683
684        sumf += dall * isum;
685    }
686
687    *s = sumf;
688}
689#endif
690
691#if defined __riscv_v
692void ggml_vec_dot_q2_K_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
693    assert(nrc == 1);
694    UNUSED(nrc);
695    UNUSED(bx);
696    UNUSED(by);
697    UNUSED(bs);
698
699    const block_q2_K * GGML_RESTRICT x = vx;
700    const block_q8_K * GGML_RESTRICT y = vy;
701
702    const int nb = n / QK_K;
703
704    float sumf = 0;
705    uint8_t atmp[16];
706
707    uint8_t temp_01[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
708                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
709
710    for (int i = 0; i < nb; ++i) {
711        const uint8_t * q2 = x[i].qs;
712        const  int8_t * q8 = y[i].qs;
713        const uint8_t * sc = x[i].scales;
714        const float dall = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
715        const float dmin = -y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
716        uint8_t *patmp = atmp;
717        int vsums;
718        int tmp, t1, t2, t3, t4, t5, t6, t7;
719        __asm__ __volatile__(
720            "vsetivli zero, 16, e8, m1\n\t"
721            "vmv.v.x v8, zero\n\t"
722            "lb zero, 15(%[sc])\n\t"
723            "vle8.v v1, (%[sc])\n\t"
724            "vle8.v v2, (%[bsums])\n\t"
725            "addi %[tmp], %[bsums], 16\n\t"
726            "vand.vi v0, v1, 0xF\n\t"
727            "vsrl.vi v1, v1, 4\n\t"
728            "vle8.v v3, (%[tmp])\n\t"
729            "vse8.v v0, (%[scale])\n\t"
730            "vsetivli zero, 16, e16, m2\n\t"
731            "vzext.vf2 v0, v1\n\t"
732            "vwmul.vv v4, v0, v2\n\t"
733            "vsetivli zero, 16, e32, m4\n\t"
734            "vredsum.vs v8, v4, v8\n\t"
735            "vmv.x.s %[vsums], v8"
736            : [tmp] "=&r" (tmp), [vsums] "=&r" (vsums)
737            : [sc] "r" (sc), [scale] "r" (atmp), [bsums] "r" (y[i].bsums)
738            : "memory"
739            , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
740            , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
741            , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
742            , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
743        );
744        sumf += dmin * vsums;
745        int isum = 0;
746
747        for (int j = 0; j < QK_K/128; ++j) {
748            __asm__ __volatile__(
749                "lb zero, 31(%[q2])\n\t"
750                "addi %[tmp], %[q2], 16\n\t"
751                "addi %[t1], %[q8], 16\n\t"
752                "vsetivli zero, 16, e8, m1\n\t"
753                "vle8.v v0, (%[q2])\n\t"
754                "vle8.v v1, (%[tmp])\n\t"
755                "vsrl.vi v2, v0, 2\n\t"
756                "vsrl.vi v3, v1, 2\n\t"
757                "vsrl.vi v4, v0, 4\n\t"
758                "addi %[tmp], %[q8], 32\n\t"
759                "vle8.v v8, (%[q8])\n\t"
760                "vle8.v v9, (%[t1])\n\t"
761                "addi %[t1], %[t1], 32\n\t"
762                "vsrl.vi v5, v1, 4\n\t"
763                "vsrl.vi v6, v0, 6\n\t"
764                "vsrl.vi v7, v1, 6\n\t"
765                "vle8.v v10, (%[tmp])\n\t"
766                "vle8.v v11, (%[t1])\n\t"
767                "addi %[tmp], %[tmp], 32\n\t"
768                "addi %[t1], %[t1], 32\n\t"
769                "vand.vi v0, v0, 0x3\n\t"
770                "vand.vi v1, v1, 0x3\n\t"
771                "vand.vi v2, v2, 0x3\n\t"
772                "vle8.v v12, (%[tmp])\n\t"
773                "vle8.v v13, (%[t1])\n\t"
774                "addi %[tmp], %[tmp], 32\n\t"
775                "addi %[t1], %[t1], 32\n\t"
776                "vand.vi v3, v3, 0x3\n\t"
777                "vand.vi v4, v4, 0x3\n\t"
778                "vand.vi v5, v5, 0x3\n\t"
779                "vle8.v v14, (%[tmp])\n\t"
780                "vle8.v v15, (%[t1])\n\t"
781                "vwmul.vv v16, v0, v8\n\t"
782                "vwmul.vv v18, v1, v9\n\t"
783                "vwmul.vv v20, v2, v10\n\t"
784                "vwmul.vv v22, v3, v11\n\t"
785                "vwmul.vv v24, v4, v12\n\t"
786                "vwmul.vv v26, v5, v13\n\t"
787                "vwmul.vv v28, v6, v14\n\t"
788                "vwmul.vv v30, v7, v15\n\t"
789                "vsetivli zero, 8, e16, m1\n\t"
790                "vmv.v.x v0, zero\n\t"
791                "lbu %[tmp], 0(%[scale])\n\t"
792                "vwredsum.vs v8, v16, v0\n\t"
793                "vwredsum.vs v9, v18, v0\n\t"
794                "lbu %[t1], 1(%[scale])\n\t"
795                "vwredsum.vs v10, v20, v0\n\t"
796                "vwredsum.vs v11, v22, v0\n\t"
797                "lbu %[t2], 2(%[scale])\n\t"
798                "vwredsum.vs v12, v24, v0\n\t"
799                "vwredsum.vs v13, v26, v0\n\t"
800                "lbu %[t3], 3(%[scale])\n\t"
801                "vwredsum.vs v14, v28, v0\n\t"
802                "vwredsum.vs v15, v30, v0\n\t"
803                "lbu %[t4], 4(%[scale])\n\t"
804                "vwredsum.vs v8, v17, v8\n\t"
805                "vwredsum.vs v9, v19, v9\n\t"
806                "lbu %[t5], 5(%[scale])\n\t"
807                "vwredsum.vs v10, v21, v10\n\t"
808                "vwredsum.vs v11, v23, v11\n\t"
809                "lbu %[t6], 6(%[scale])\n\t"
810                "vwredsum.vs v12, v25, v12\n\t"
811                "vwredsum.vs v13, v27, v13\n\t"
812                "lbu %[t7], 7(%[scale])\n\t"
813                "vwredsum.vs v14, v29, v14\n\t"
814                "vwredsum.vs v15, v31, v15\n\t"
815                "vsetivli zero, 4, e32, m1\n\t"
816                "vmul.vx v0, v8, %[tmp]\n\t"
817                "vmul.vx v1, v9, %[t1]\n\t"
818                "vmacc.vx v0, %[t2], v10\n\t"
819                "vmacc.vx v1, %[t3], v11\n\t"
820                "vmacc.vx v0, %[t4], v12\n\t"
821                "vmacc.vx v1, %[t5], v13\n\t"
822                "vmacc.vx v0, %[t6], v14\n\t"
823                "vmacc.vx v1, %[t7], v15\n\t"
824                "vmv.x.s %[tmp], v0\n\t"
825                "vmv.x.s %[t1], v1\n\t"
826                "add %[isum], %[isum], %[tmp]\n\t"
827                "add %[isum], %[isum], %[t1]"
828                : [tmp] "=&r" (tmp), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" (t3)
829                , [t4] "=&r" (t4), [t5] "=&r" (t5), [t6] "=&r" (t6), [t7] "=&r" (t7)
830                , [isum] "+&r" (isum)
831                : [q2] "r" (q2), [scale] "r" (patmp), [q8] "r" (q8)
832                : "memory"
833                , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
834                , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
835                , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
836                , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
837            );
838            q2 += 32; q8 += 128; patmp += 8;
839        }
840
841        sumf += dall * isum;
842    }
843
844    *s = sumf;
845}
846
847void ggml_vec_dot_q2_K_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
848    assert(nrc == 1);
849    UNUSED(nrc);
850    UNUSED(bx);
851    UNUSED(by);
852    UNUSED(bs);
853
854    const block_q2_K * GGML_RESTRICT x = vx;
855    const block_q8_K * GGML_RESTRICT y = vy;
856
857    const int nb = n / QK_K;
858
859    float sumf = 0;
860    uint8_t atmp[16];
861
862    uint8_t temp_01[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
863                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
864
865    for (int i = 0; i < nb; ++i) {
866        const uint8_t * q2 = x[i].qs;
867        const int8_t *  q8 = y[i].qs;
868        const uint8_t * sc = x[i].scales;
869
870        const float dall = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
871        const float dmin = -y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
872
873        size_t vl = 16;
874
875        vuint8m1_t scales = __riscv_vle8_v_u8m1(sc, vl);
876        vuint8m1_t aux    = __riscv_vand_vx_u8m1(scales, 0x0F, vl);
877
878        vint16m1_t q8sums = __riscv_vle16_v_i16m1(y[i].bsums, vl);
879
880        vuint8mf2_t scales_2 = __riscv_vle8_v_u8mf2(sc, vl);
881        vuint8mf2_t mins8    = __riscv_vsrl_vx_u8mf2(scales_2, 0x4, vl);
882        vint16m1_t  mins     = __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(mins8, vl));
883        vint32m2_t  prod     = __riscv_vwmul_vv_i32m2(q8sums, mins, vl);
884        vint32m1_t  vsums    = __riscv_vredsum_vs_i32m2_i32m1(prod, __riscv_vmv_v_x_i32m1(0, 1), vl);
885
886        sumf += dmin * __riscv_vmv_x_s_i32m1_i32(vsums);
887
888        vl = 32;
889
890        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
891        vuint8m1_t v_b   = __riscv_vle8_v_u8m1(temp_01, vl);
892
893        uint8_t is   = 0;
894        int     isum = 0;
895
896        for (int j = 0; j < QK_K / 128; ++j) {
897            // load Q2
898            vuint8m1_t q2_x = __riscv_vle8_v_u8m1(q2, vl);
899
900            vuint8m1_t q2_0 = __riscv_vand_vx_u8m1(q2_x, 0x03, vl);
901            vuint8m1_t q2_1 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(q2_x, 0x2, vl), 0x03, vl);
902            vuint8m1_t q2_2 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(q2_x, 0x4, vl), 0x03, vl);
903            vuint8m1_t q2_3 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(q2_x, 0x6, vl), 0x03, vl);
904
905            // duplicate scale elements for product
906            vuint8m1_t sc0 = __riscv_vrgather_vv_u8m1(aux, __riscv_vadd_vx_u8m1(v_b, 0 + is, vl), vl);
907            vuint8m1_t sc1 = __riscv_vrgather_vv_u8m1(aux, __riscv_vadd_vx_u8m1(v_b, 2 + is, vl), vl);
908            vuint8m1_t sc2 = __riscv_vrgather_vv_u8m1(aux, __riscv_vadd_vx_u8m1(v_b, 4 + is, vl), vl);
909            vuint8m1_t sc3 = __riscv_vrgather_vv_u8m1(aux, __riscv_vadd_vx_u8m1(v_b, 6 + is, vl), vl);
910
911            vint16m2_t p0 = __riscv_vreinterpret_v_u16m2_i16m2(__riscv_vwmulu_vv_u16m2(q2_0, sc0, vl));
912            vint16m2_t p1 = __riscv_vreinterpret_v_u16m2_i16m2(__riscv_vwmulu_vv_u16m2(q2_1, sc1, vl));
913            vint16m2_t p2 = __riscv_vreinterpret_v_u16m2_i16m2(__riscv_vwmulu_vv_u16m2(q2_2, sc2, vl));
914            vint16m2_t p3 = __riscv_vreinterpret_v_u16m2_i16m2(__riscv_vwmulu_vv_u16m2(q2_3, sc3, vl));
915
916            // load Q8
917            vint8m1_t q8_0 = __riscv_vle8_v_i8m1(q8, vl);
918            vint8m1_t q8_1 = __riscv_vle8_v_i8m1(q8 + 32, vl);
919            vint8m1_t q8_2 = __riscv_vle8_v_i8m1(q8 + 64, vl);
920            vint8m1_t q8_3 = __riscv_vle8_v_i8m1(q8 + 96, vl);
921
922            vint32m4_t s0 = __riscv_vwmul_vv_i32m4(p0, __riscv_vwcvt_x_x_v_i16m2(q8_0, vl), vl);
923            vint32m4_t s1 = __riscv_vwmul_vv_i32m4(p1, __riscv_vwcvt_x_x_v_i16m2(q8_1, vl), vl);
924            vint32m4_t s2 = __riscv_vwmul_vv_i32m4(p2, __riscv_vwcvt_x_x_v_i16m2(q8_2, vl), vl);
925            vint32m4_t s3 = __riscv_vwmul_vv_i32m4(p3, __riscv_vwcvt_x_x_v_i16m2(q8_3, vl), vl);
926
927            vint32m1_t isum0 = __riscv_vredsum_vs_i32m4_i32m1(__riscv_vadd_vv_i32m4(s0, s1, vl), vzero, vl);
928            vint32m1_t isum1 = __riscv_vredsum_vs_i32m4_i32m1(__riscv_vadd_vv_i32m4(s2, s3, vl), isum0, vl);
929
930            isum += __riscv_vmv_x_s_i32m1_i32(isum1);
931
932            q2 += 32;
933            q8 += 128;
934            is = 8;
935        }
936
937        sumf += dall * isum;
938    }
939
940    *s = sumf;
941}
942#endif
943
944void ggml_vec_dot_q2_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
945#if defined __riscv_xtheadvector
946    ggml_vec_dot_q2_K_q8_K_xtheadvector(n, s, bs, vx, bx, vy, by, nrc);
947#elif defined __riscv_v
948    switch (__riscv_vlenb() * 8) {
949        case 128:
950            ggml_vec_dot_q2_K_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
951            break;
952        default:
953            ggml_vec_dot_q2_K_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
954            break;
955    }
956#else
957    ggml_vec_dot_q2_K_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
958#endif
959}
960
961#if defined __riscv_xtheadvector
962void ggml_vec_dot_q3_K_q8_K_xtheadvector(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
963    assert(n % QK_K == 0);
964    assert(nrc == 1);
965    UNUSED(nrc);
966    UNUSED(bx);
967    UNUSED(by);
968    UNUSED(bs);
969
970    const uint32_t kmask1 = 0x03030303;
971    const uint32_t kmask2 = 0x0f0f0f0f;
972
973    const block_q3_K * GGML_RESTRICT x = vx;
974    const block_q8_K * GGML_RESTRICT y = vy;
975
976    const int nb = n / QK_K;
977
978    uint32_t utmp[4];
979    float sumf = 0;
980
981    for (int i = 0; i < nb; ++i) {
982        const uint8_t * restrict q3 = x[i].qs;
983        const uint8_t * restrict qh = x[i].hmask;
984        const  int8_t * restrict q8 = y[i].qs;
985
986        int8_t * scale = (int8_t *)utmp;
987        int tmp;
988        __asm__ __volatile__(
989            "li %[tmp], 12\n\t"
990            "th.vsetvli zero, %[tmp], e8, m1\n\t"
991            "th.vlb.v v0, (%[s6b])\n\t"
992            "th.vmv.v.v v2, v0\n\t"
993            "li %[tmp], 2\n\t"
994            "th.vsetvli zero, %[tmp], e64, m1\n\t"
995            "th.vmv.v.x v9, %[sh]\n\t"\
996            "th.vslidedown.vi v1, v0, 1\n\t"
997            "th.vslide1up.vx v8, v9, zero\n\t" // {0, 0, 4, 4}
998            "th.vslideup.vi v0, v2, 1\n\t" // {aux[0], aux[1], aux[0], aux[1]}
999            "li %[tmp], 4\n\t"
1000            "th.vsetvli zero, %[tmp], e32, m1\n\t"
1001            "th.vid.v v9\n\t"
1002            "th.vmv.x.s %[tmp], v1\n\t"
1003            "th.vsll.vi v9, v9, 1\n\t" // {0, 2, 4, 6}
1004            "th.vmv.v.x v1, %[tmp]\n\t" // {aux[2], aux[2], aux[2], aux[2]}
1005            "th.vsrl.vv v4, v1, v9\n\t"
1006            "th.vsrl.vv v2, v0, v8\n\t"
1007            "th.vand.vx v5, v4, %[kmask1]\n\t"
1008            "th.vand.vx v3, v2, %[kmask2]\n\t"
1009            "th.vsll.vi v6, v5, 4\n\t"
1010            "th.vor.vv v7, v6, v3\n\t"
1011            "li %[tmp], 16\n\t"
1012            "th.vsetvli zero, %[tmp], e8, m1\n\t"
1013            "th.vsub.vx v0, v7, %[c]\n\t"
1014            "th.vsb.v v0, (%[scale])"
1015            : [tmp] "=&r" (tmp)
1016            : [sh] "r" (0x0000000400000004), [s6b] "r" (x[i].scales), [c] "r" (32)
1017            , [scale] "r" (scale), [kmask1] "r" (kmask1), [kmask2] "r" (kmask2)
1018            : "memory"
1019            , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
1020            , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
1021            , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
1022            , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
1023        );
1024
1025        uint8_t m = 1;
1026        int isum = 0;
1027        for (int j = 0; j < QK_K; j += 128) {
1028            __asm__ __volatile__(
1029                // fixme: use v0p7 mask layout directly
1030                "th.vsetvli zero, %[vl32], e8, m2\n\t"
1031                "th.vlb.v v8, (%[q3])\n\t"
1032                "th.vsrl.vi v10, v8, 2\n\t"
1033                "th.vsrl.vi v12, v8, 4\n\t"
1034                "th.vsrl.vi v14, v8, 6\n\t"
1035                "th.vand.vi v8, v8, 3\n\t"
1036                "th.vand.vi v10, v10, 3\n\t"
1037                "th.vand.vi v12, v12, 3\n\t"
1038                "th.vlb.v v2, (%[qh])\n\t"
1039                "th.vand.vx v4, v2, %[m]\n\t"
1040                "slli %[m], %[m], 1\n\t"
1041                "th.vmseq.vx v0, v4, zero\n\t"
1042                "th.vadd.vi v8, v8, -4, v0.t\n\t"
1043                "th.vand.vx v4, v2, %[m]\n\t"
1044                "slli %[m], %[m], 1\n\t"
1045                "th.vmseq.vx v0, v4, zero\n\t"
1046                "th.vadd.vi v10, v10, -4, v0.t\n\t"
1047                "th.vand.vx v4, v2, %[m]\n\t"
1048                "slli %[m], %[m], 1\n\t"
1049                "th.vmseq.vx v0, v4, zero\n\t"
1050                "th.vadd.vi v12, v12, -4, v0.t\n\t"
1051                "th.vand.vx v4, v2, %[m]\n\t"
1052                "slli %[m], %[m], 1\n\t"
1053                "th.vmseq.vx v0, v4, zero\n\t"
1054                "th.vadd.vi v14, v14, -4, v0.t\n\t"
1055                "th.vsetvli zero, %[vl128], e8, m8\n\t"
1056                "th.vlb.v v0, (%[q8])\n\t"
1057                "th.vsetvli zero, %[vl64], e8, m4\n\t"
1058                "th.vwmul.vv v16, v0, v8\n\t"
1059                "th.vwmul.vv v24, v4, v12\n\t"
1060                "li %[tmp], 16\n\t"
1061                "th.vsetvli zero, %[tmp], e16, m2\n\t"
1062                "th.vmv.v.x v0, zero\n\t"
1063                "th.vwredsum.vs v10, v16, v0\n\t"
1064                "th.vwredsum.vs v9, v18, v0\n\t"
1065                "th.vwredsum.vs v8, v20, v0\n\t"
1066                "th.vwredsum.vs v7, v22, v0\n\t"
1067                "th.vwredsum.vs v11, v24, v0\n\t"
1068                "th.vwredsum.vs v12, v26, v0\n\t"
1069                "th.vwredsum.vs v13, v28, v0\n\t"
1070                "th.vwredsum.vs v14, v30, v0\n\t"
1071                "li %[tmp], 4\n\t"
1072                "th.vsetvli zero, %[tmp], e32, m1\n\t"
1073                "th.vslideup.vi v10, v9, 1\n\t"
1074                "th.vslideup.vi v8, v7, 1\n\t"
1075                "th.vslideup.vi v11, v12, 1\n\t"
1076                "th.vslideup.vi v13, v14, 1\n\t"
1077                "th.vslideup.vi v10, v8, 2\n\t"
1078                "th.vslideup.vi v11, v13, 2\n\t"
1079                "li %[tmp], 8\n\t"
1080                "th.vsetvli zero, %[tmp], e32, m2\n\t"
1081                "th.vlb.v v12, (%[scale])\n\t"
1082                "th.vmul.vv v10, v10, v12\n\t"
1083                "th.vredsum.vs v0, v10, v0\n\t"
1084                "th.vmv.x.s %[tmp], v0\n\t"
1085                "add %[isum], %[isum], %[tmp]"
1086                : [tmp] "=&r" (tmp), [m] "+&r" (m), [isum] "+&r" (isum)
1087                : [vl128] "r" (128), [vl64] "r" (64), [vl32] "r" (32)
1088                , [q3] "r" (q3), [qh] "r" (qh), [scale] "r" (scale), [q8] "r" (q8)
1089                : "memory"
1090                , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
1091                , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
1092                , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
1093                , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
1094            );
1095            q3 += 32;    q8 += 128;   scale += 8;
1096        }
1097
1098        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
1099        sumf += d * isum;
1100    }
1101
1102    *s = sumf;
1103}
1104#endif
1105
1106#if defined __riscv_v
1107void ggml_vec_dot_q3_K_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1108    assert(n % QK_K == 0);
1109    assert(nrc == 1);
1110    UNUSED(nrc);
1111    UNUSED(bx);
1112    UNUSED(by);
1113    UNUSED(bs);
1114
1115    const uint32_t kmask1 = 0x03030303;
1116    const uint32_t kmask2 = 0x0f0f0f0f;
1117
1118    const block_q3_K * GGML_RESTRICT x = vx;
1119    const block_q8_K * GGML_RESTRICT y = vy;
1120
1121    const int nb = n / QK_K;
1122
1123    uint32_t utmp[4];
1124    float sumf = 0;
1125    uint32_t aux[3];
1126
1127    for (int i = 0; i < nb; ++i) {
1128        const uint8_t * restrict q3 = x[i].qs;
1129        const uint8_t * restrict qh = x[i].hmask;
1130        const  int8_t * restrict q8 = y[i].qs;
1131
1132        int8_t * scale = (int8_t *)utmp;
1133        int tmp, t1, t2, t3, t4, t5, t6, t7;
1134        __asm__ __volatile__(
1135            "vsetivli zero, 12, e8, m1\n\t"
1136            "vle8.v v0, (%[s6b])\n\t"
1137            "vmv1r.v v2, v0\n\t"
1138            "vsetivli zero, 2, e64, m1\n\t"
1139            "vmv.v.x v9, %[sh]\n\t"\
1140            "vslidedown.vi v1, v0, 1\n\t"
1141            "vslide1up.vx v8, v9, zero\n\t" // {0, 0, 4, 4}
1142            "vslideup.vi v0, v2, 1\n\t" // {aux[0], aux[1], aux[0], aux[1]}
1143            "vsetivli zero, 4, e32, m1\n\t"
1144            "vid.v v9\n\t"
1145            "vmv.x.s %[tmp], v1\n\t"
1146            "vsll.vi v9, v9, 1\n\t" // {0, 2, 4, 6}
1147            "vmv.v.x v1, %[tmp]\n\t" // {aux[2], aux[2], aux[2], aux[2]}
1148            "vsrl.vv v4, v1, v9\n\t"
1149            "vsrl.vv v2, v0, v8\n\t"
1150            "vand.vx v5, v4, %[kmask1]\n\t"
1151            "vand.vx v3, v2, %[kmask2]\n\t"
1152            "vsll.vi v6, v5, 4\n\t"
1153            "vor.vv v7, v6, v3\n\t"
1154            "vsetivli zero, 16, e8, m1\n\t"
1155            "vsub.vx v0, v7, %[c]\n\t"
1156            "vse8.v v0, (%[scale])"
1157            : [tmp] "=&r" (tmp)
1158            : [sh] "r" (0x0000000400000004), [s6b] "r" (x[i].scales), [c] "r" (32)
1159            , [scale] "r" (scale), [kmask1] "r" (kmask1), [kmask2] "r" (kmask2)
1160            : "memory"
1161            , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
1162            , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
1163            , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
1164            , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
1165        );
1166
1167        uint8_t m = 1;
1168        int isum = 0;
1169        for (int j = 0; j < QK_K; j += 128) {
1170            __asm__ __volatile__(
1171                "lb zero, 31(%[q3])\n\t"
1172                "vsetvli zero, %[vl32], e8, m2, ta, mu\n\t"
1173                "vle8.v v8, (%[q3])\n\t"
1174                "vsrl.vi v10, v8, 2\n\t"
1175                "vsrl.vi v12, v8, 4\n\t"
1176                "vsrl.vi v14, v8, 6\n\t"
1177                "lb zero, 64(%[q8])\n\t"
1178                "vand.vi v8, v8, 3\n\t"
1179                "vand.vi v10, v10, 3\n\t"
1180                "vand.vi v12, v12, 3\n\t"
1181                "vle8.v v2, (%[qh])\n\t"
1182                "lb zero, 127(%[q8])\n\t"
1183                "vand.vx v4, v2, %[m]\n\t"
1184                "slli %[m], %[m], 1\n\t"
1185                "vmseq.vx v0, v4, zero\n\t"
1186                "vadd.vi v8, v8, -4, v0.t\n\t"
1187                "lb zero, 0(%[q8])\n\t"
1188                "vand.vx v4, v2, %[m]\n\t"
1189                "slli %[m], %[m], 1\n\t"
1190                "vmseq.vx v0, v4, zero\n\t"
1191                "vadd.vi v10, v10, -4, v0.t\n\t"
1192                "vand.vx v4, v2, %[m]\n\t"
1193                "slli %[m], %[m], 1\n\t"
1194                "vmseq.vx v0, v4, zero\n\t"
1195                "vadd.vi v12, v12, -4, v0.t\n\t"
1196                "vand.vx v4, v2, %[m]\n\t"
1197                "slli %[m], %[m], 1\n\t"
1198                "vmseq.vx v0, v4, zero\n\t"
1199                "vadd.vi v14, v14, -4, v0.t\n\t"
1200                "vsetvli zero, %[vl128], e8, m8\n\t"
1201                "vle8.v v0, (%[q8])\n\t"
1202                "lb %[tmp], 0(%[scale])\n\t"
1203                "lb %[t1], 1(%[scale])\n\t"
1204                "lb %[t2], 2(%[scale])\n\t"
1205                "lb %[t3], 3(%[scale])\n\t"
1206                "vsetvli zero, %[vl64], e8, m4\n\t"
1207                "vwmul.vv v16, v0, v8\n\t"
1208                "vwmul.vv v24, v4, v12\n\t"
1209                "vsetivli zero, 16, e16, m2\n\t"
1210                "vmv.v.x v0, zero\n\t"
1211                "vwredsum.vs v8, v16, v0\n\t"
1212                "lb %[t4], 4(%[scale])\n\t"
1213                "lb %[t5], 5(%[scale])\n\t"
1214                "vwredsum.vs v9, v18, v0\n\t"
1215                "vwredsum.vs v10, v20, v0\n\t"
1216                "vwredsum.vs v11, v22, v0\n\t"
1217                "vwredsum.vs v12, v24, v0\n\t"
1218                "lb %[t6], 6(%[scale])\n\t"
1219                "lb %[t7], 7(%[scale])\n\t"
1220                "vwredsum.vs v13, v26, v0\n\t"
1221                "vwredsum.vs v14, v28, v0\n\t"
1222                "vwredsum.vs v15, v30, v0\n\t"
1223                "vsetivli zero, 4, e32, m1\n\t"
1224                "vmul.vx v0, v8, %[tmp]\n\t"
1225                "vmul.vx v1, v9, %[t1]\n\t"
1226                "vmacc.vx v0, %[t2], v10\n\t"
1227                "vmacc.vx v1, %[t3], v11\n\t"
1228                "vmacc.vx v0, %[t4], v12\n\t"
1229                "vmacc.vx v1, %[t5], v13\n\t"
1230                "vmacc.vx v0, %[t6], v14\n\t"
1231                "vmacc.vx v1, %[t7], v15\n\t"
1232                "vmv.x.s %[tmp], v0\n\t"
1233                "vmv.x.s %[t1], v1\n\t"
1234                "add %[isum], %[isum], %[tmp]\n\t"
1235                "add %[isum], %[isum], %[t1]"
1236                : [tmp] "=&r" (tmp), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" (t3)
1237                , [t4] "=&r" (t4), [t5] "=&r" (t5), [t6] "=&r" (t6), [t7] "=&r" (t7)
1238                , [m] "+&r" (m), [isum] "+&r" (isum)
1239                : [vl128] "r" (128), [vl64] "r" (64), [vl32] "r" (32)
1240                , [q3] "r" (q3), [qh] "r" (qh), [scale] "r" (scale), [q8] "r" (q8)
1241                : "memory"
1242                , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
1243                , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
1244                , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
1245                , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
1246            );
1247            q3 += 32;    q8 += 128;   scale += 8;
1248        }
1249
1250        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
1251        sumf += d * isum;
1252    }
1253
1254    *s = sumf;
1255}
1256
1257void ggml_vec_dot_q3_K_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1258    assert(n % QK_K == 0);
1259    assert(nrc == 1);
1260    UNUSED(nrc);
1261    UNUSED(bx);
1262    UNUSED(by);
1263    UNUSED(bs);
1264
1265    const uint32_t kmask1 = 0x03030303;
1266    const uint32_t kmask2 = 0x0f0f0f0f;
1267
1268    const block_q3_K * GGML_RESTRICT x = vx;
1269    const block_q8_K * GGML_RESTRICT y = vy;
1270
1271    const int nb = n / QK_K;
1272    uint32_t utmp[4];
1273    float sumf = 0;
1274    uint32_t aux[3];
1275
1276    for (int i = 0; i < nb; ++i) {
1277        const uint8_t * GGML_RESTRICT q3 = x[i].qs;
1278        const uint8_t * GGML_RESTRICT qh = x[i].hmask;
1279        const  int8_t * GGML_RESTRICT q8 = y[i].qs;
1280
1281        memcpy(aux, x[i].scales, 12);
1282        utmp[3] = ((aux[1] >> 4) & kmask2) | (((aux[2] >> 6) & kmask1) << 4);
1283        utmp[2] = ((aux[0] >> 4) & kmask2) | (((aux[2] >> 4) & kmask1) << 4);
1284        utmp[1] = (aux[1] & kmask2) | (((aux[2] >> 2) & kmask1) << 4);
1285        utmp[0] = (aux[0] & kmask2) | (((aux[2] >> 0) & kmask1) << 4);
1286
1287        int8_t * scale = (int8_t *)utmp;
1288        for (int j = 0; j < 16; ++j) scale[j] -= 32;
1289
1290
1291        size_t vl = 32;
1292        uint8_t m =  1;
1293
1294        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
1295        vuint8m1_t vqh = __riscv_vle8_v_u8m1(qh, vl);
1296
1297        int sum_t = 0;
1298
1299        for (int j = 0; j < QK_K; j += 128) {
1300
1301            vl = 32;
1302
1303            // load Q3
1304            vuint8m1_t q3_x = __riscv_vle8_v_u8m1(q3, vl);
1305
1306            vint8m1_t q3_0 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vand_vx_u8m1(q3_x, 0x03, vl));
1307            vint8m1_t q3_1 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(q3_x, 0x2, vl), 0x03 , vl));
1308            vint8m1_t q3_2 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(q3_x, 0x4, vl), 0x03 , vl));
1309            vint8m1_t q3_3 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(q3_x, 0x6, vl), 0x03 , vl));
1310
1311            // compute mask for subtraction
1312            vuint8m1_t qh_m0 = __riscv_vand_vx_u8m1(vqh, m, vl);
1313            vbool8_t vmask_0 = __riscv_vmseq_vx_u8m1_b8(qh_m0, 0, vl);
1314            vint8m1_t q3_m0 = __riscv_vsub_vx_i8m1_mu(vmask_0, q3_0, q3_0, 0x4, vl);
1315            m <<= 1;
1316
1317            vuint8m1_t qh_m1 = __riscv_vand_vx_u8m1(vqh, m, vl);
1318            vbool8_t vmask_1 = __riscv_vmseq_vx_u8m1_b8(qh_m1, 0, vl);
1319            vint8m1_t q3_m1 = __riscv_vsub_vx_i8m1_mu(vmask_1, q3_1, q3_1, 0x4, vl);
1320            m <<= 1;
1321
1322            vuint8m1_t qh_m2 = __riscv_vand_vx_u8m1(vqh, m, vl);
1323            vbool8_t vmask_2 = __riscv_vmseq_vx_u8m1_b8(qh_m2, 0, vl);
1324            vint8m1_t q3_m2 = __riscv_vsub_vx_i8m1_mu(vmask_2, q3_2, q3_2, 0x4, vl);
1325            m <<= 1;
1326
1327            vuint8m1_t qh_m3 = __riscv_vand_vx_u8m1(vqh, m, vl);
1328            vbool8_t vmask_3 = __riscv_vmseq_vx_u8m1_b8(qh_m3, 0, vl);
1329            vint8m1_t q3_m3 = __riscv_vsub_vx_i8m1_mu(vmask_3, q3_3, q3_3, 0x4, vl);
1330            m <<= 1;
1331
1332            // load Q8 and take product with Q3
1333            vint16m2_t a0 = __riscv_vwmul_vv_i16m2(q3_m0, __riscv_vle8_v_i8m1(q8, vl), vl);
1334            vint16m2_t a1 = __riscv_vwmul_vv_i16m2(q3_m1, __riscv_vle8_v_i8m1(q8+32, vl), vl);
1335            vint16m2_t a2 = __riscv_vwmul_vv_i16m2(q3_m2, __riscv_vle8_v_i8m1(q8+64, vl), vl);
1336            vint16m2_t a3 = __riscv_vwmul_vv_i16m2(q3_m3, __riscv_vle8_v_i8m1(q8+96, vl), vl);
1337
1338            vl = 16;
1339
1340            // retrieve lane to multiply with scale
1341            vint32m2_t aux0_0 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a0, 0), (scale[0]), vl);
1342            vint32m2_t aux0_1 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a0, 1), (scale[1]), vl);
1343            vint32m2_t aux1_0 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a1, 0), (scale[2]), vl);
1344            vint32m2_t aux1_1 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a1, 1), (scale[3]), vl);
1345            vint32m2_t aux2_0 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a2, 0), (scale[4]), vl);
1346            vint32m2_t aux2_1 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a2, 1), (scale[5]), vl);
1347            vint32m2_t aux3_0 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a3, 0), (scale[6]), vl);
1348            vint32m2_t aux3_1 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(a3, 1), (scale[7]), vl);
1349
1350            vint32m1_t isum0 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(aux0_0, aux0_1, vl), vzero, vl);
1351            vint32m1_t isum1 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(aux1_0, aux1_1, vl), isum0, vl);
1352            vint32m1_t isum2 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(aux2_0, aux2_1, vl), isum1, vl);
1353            vint32m1_t isum3 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(aux3_0, aux3_1, vl), isum2, vl);
1354
1355            sum_t +=  __riscv_vmv_x_s_i32m1_i32(isum3);
1356
1357            q3 += 32;    q8 += 128;   scale += 8;
1358
1359        }
1360
1361        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
1362
1363        sumf += d*sum_t;
1364
1365    }
1366
1367    *s = sumf;
1368}
1369
1370void ggml_vec_dot_q3_K_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1371    assert(n % QK_K == 0);
1372    assert(nrc == 1);
1373    UNUSED(nrc);
1374    UNUSED(bx);
1375    UNUSED(by);
1376    UNUSED(bs);
1377
1378    const uint32_t kmask1 = 0x03030303;
1379    const uint32_t kmask2 = 0x0f0f0f0f;
1380
1381    const block_q3_K * GGML_RESTRICT x = vx;
1382    const block_q8_K * GGML_RESTRICT y = vy;
1383
1384    const int nb = n / QK_K;
1385
1386    // mask for processing 16 elements per prod register
1387    const vuint16m1_t va_index = __riscv_vid_v_u16m1(32);
1388    const vbool16_t va_mask = __riscv_vmsgtu_vx_u16m1_b16(va_index, 15, 32);
1389
1390    uint32_t utmp[4];
1391    float sumf = 0;
1392    uint32_t aux[3];
1393
1394    for (int i = 0; i < nb; ++i) {
1395        const uint8_t * GGML_RESTRICT q3 = x[i].qs;
1396        const uint8_t * GGML_RESTRICT qh = x[i].hmask;
1397        const  int8_t * GGML_RESTRICT q8 = y[i].qs;
1398
1399        memcpy(aux, x[i].scales, 12);
1400        utmp[3] = ((aux[1] >> 4) & kmask2) | (((aux[2] >> 6) & kmask1) << 4);
1401        utmp[2] = ((aux[0] >> 4) & kmask2) | (((aux[2] >> 4) & kmask1) << 4);
1402        utmp[1] = (aux[1] & kmask2) | (((aux[2] >> 2) & kmask1) << 4);
1403        utmp[0] = (aux[0] & kmask2) | (((aux[2] >> 0) & kmask1) << 4);
1404
1405        int8_t * scale = (int8_t *)utmp;
1406        for (int j = 0; j < 16; ++j) scale[j] -= 32;
1407
1408
1409        size_t vl = 32;
1410        uint8_t m =  1;
1411
1412        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
1413        vuint8mf2_t vqh = __riscv_vle8_v_u8mf2(qh, vl);
1414
1415        int sum_t = 0;
1416
1417        vint32m2_t vaux_0 = __riscv_vmv_v_x_i32m2(0, vl);
1418        vint32m2_t vaux_1 = __riscv_vmv_v_x_i32m2(0, vl);
1419        vint32m2_t vaux_2 = __riscv_vmv_v_x_i32m2(0, vl);
1420        vint32m2_t vaux_3 = __riscv_vmv_v_x_i32m2(0, vl);
1421
1422        for (int j = 0; j < QK_K; j += 128) {
1423
1424            vl = 32;
1425
1426            // load Q3
1427            vuint8mf2_t q3_x = __riscv_vle8_v_u8mf2(q3, vl);
1428
1429            vint8mf2_t q3_0 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(q3_x, 0x03, vl));
1430            vint8mf2_t q3_1 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(q3_x, 0x2, vl), 0x03 , vl));
1431            vint8mf2_t q3_2 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(q3_x, 0x4, vl), 0x03 , vl));
1432            vint8mf2_t q3_3 = __riscv_vreinterpret_v_u8mf2_i8mf2(__riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(q3_x, 0x6, vl), 0x03 , vl));
1433
1434            // compute mask for subtraction
1435            vuint8mf2_t qh_m0 = __riscv_vand_vx_u8mf2(vqh, m, vl);
1436            vbool16_t vmask_0 = __riscv_vmseq_vx_u8mf2_b16(qh_m0, 0, vl);
1437            vint8mf2_t q3_m0 = __riscv_vsub_vx_i8mf2_mu(vmask_0, q3_0, q3_0, 0x4, vl);
1438            m <<= 1;
1439
1440            vuint8mf2_t qh_m1 = __riscv_vand_vx_u8mf2(vqh, m, vl);
1441            vbool16_t vmask_1 = __riscv_vmseq_vx_u8mf2_b16(qh_m1, 0, vl);
1442            vint8mf2_t q3_m1 = __riscv_vsub_vx_i8mf2_mu(vmask_1, q3_1, q3_1, 0x4, vl);
1443            m <<= 1;
1444
1445            vuint8mf2_t qh_m2 = __riscv_vand_vx_u8mf2(vqh, m, vl);
1446            vbool16_t vmask_2 = __riscv_vmseq_vx_u8mf2_b16(qh_m2, 0, vl);
1447            vint8mf2_t q3_m2 = __riscv_vsub_vx_i8mf2_mu(vmask_2, q3_2, q3_2, 0x4, vl);
1448            m <<= 1;
1449
1450            vuint8mf2_t qh_m3 = __riscv_vand_vx_u8mf2(vqh, m, vl);
1451            vbool16_t vmask_3 = __riscv_vmseq_vx_u8mf2_b16(qh_m3, 0, vl);
1452            vint8mf2_t q3_m3 = __riscv_vsub_vx_i8mf2_mu(vmask_3, q3_3, q3_3, 0x4, vl);
1453            m <<= 1;
1454
1455            // load Q8 and take product
1456            vint16m1_t va_q_0 = __riscv_vwmul_vv_i16m1(q3_m0, __riscv_vle8_v_i8mf2(q8, vl), vl);
1457            vint16m1_t va_q_1 = __riscv_vwmul_vv_i16m1(q3_m1, __riscv_vle8_v_i8mf2(q8+32, vl), vl);
1458            vint16m1_t va_q_2 = __riscv_vwmul_vv_i16m1(q3_m2, __riscv_vle8_v_i8mf2(q8+64, vl), vl);
1459            vint16m1_t va_q_3 = __riscv_vwmul_vv_i16m1(q3_m3, __riscv_vle8_v_i8mf2(q8+96, vl), vl);
1460
1461            // accumulate
1462            vaux_0 = __riscv_vwmacc_vx_i32m2(vaux_0, scale[0], va_q_0, 16);
1463            vaux_1 = __riscv_vwmacc_vx_i32m2(vaux_1, scale[2], va_q_1, 16);
1464            vaux_2 = __riscv_vwmacc_vx_i32m2(vaux_2, scale[4], va_q_2, 16);
1465            vaux_3 = __riscv_vwmacc_vx_i32m2(vaux_3, scale[6], va_q_3, 16);
1466            //
1467            vaux_0 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_0, scale[1], va_q_0, vl);
1468            vaux_1 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_1, scale[3], va_q_1, vl);
1469            vaux_2 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_2, scale[5], va_q_2, vl);
1470            vaux_3 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_3, scale[7], va_q_3, vl);
1471
1472            q3 += 32;    q8 += 128;   scale += 8;
1473        }
1474
1475        vint32m1_t isum0 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_0, vaux_1, vl), vzero, vl);
1476        vint32m1_t isum1 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_2, vaux_3, vl), isum0, vl);
1477
1478        sum_t += __riscv_vmv_x_s_i32m1_i32(isum1);
1479
1480        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
1481
1482        sumf += d*sum_t;
1483    }
1484
1485    *s = sumf;
1486}
1487
1488void ggml_vec_dot_q3_K_q8_K_vl1024(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1489    assert(n % QK_K == 0);
1490    assert(nrc == 1);
1491    UNUSED(nrc);
1492    UNUSED(bx);
1493    UNUSED(by);
1494    UNUSED(bs);
1495
1496    const uint32_t kmask1 = 0x03030303;
1497    const uint32_t kmask2 = 0x0f0f0f0f;
1498
1499    const block_q3_K * GGML_RESTRICT x = vx;
1500    const block_q8_K * GGML_RESTRICT y = vy;
1501
1502    const int nb = n / QK_K;
1503
1504    // mask for processing 16 elements per prod register
1505    const vuint16mf2_t va_index = __riscv_vid_v_u16mf2(32);
1506    const vbool32_t va_mask = __riscv_vmsgtu_vx_u16mf2_b32(va_index, 15, 32);
1507
1508    uint32_t utmp[4];
1509    float sumf = 0;
1510    uint32_t aux[3];
1511
1512    for (int i = 0; i < nb; ++i) {
1513        const uint8_t * GGML_RESTRICT q3 = x[i].qs;
1514        const uint8_t * GGML_RESTRICT qh = x[i].hmask;
1515        const  int8_t * GGML_RESTRICT q8 = y[i].qs;
1516
1517        memcpy(aux, x[i].scales, 12);
1518        utmp[3] = ((aux[1] >> 4) & kmask2) | (((aux[2] >> 6) & kmask1) << 4);
1519        utmp[2] = ((aux[0] >> 4) & kmask2) | (((aux[2] >> 4) & kmask1) << 4);
1520        utmp[1] = (aux[1] & kmask2) | (((aux[2] >> 2) & kmask1) << 4);
1521        utmp[0] = (aux[0] & kmask2) | (((aux[2] >> 0) & kmask1) << 4);
1522
1523        int8_t * scale = (int8_t *)utmp;
1524        for (int j = 0; j < 16; ++j) scale[j] -= 32;
1525
1526
1527        size_t vl = 32;
1528        uint8_t m =  1;
1529
1530        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
1531        vuint8mf4_t vqh = __riscv_vle8_v_u8mf4(qh, vl);
1532
1533        int sum_t = 0;
1534
1535        vint32m1_t vaux_0 = __riscv_vmv_v_x_i32m1(0, vl);
1536        vint32m1_t vaux_1 = __riscv_vmv_v_x_i32m1(0, vl);
1537        vint32m1_t vaux_2 = __riscv_vmv_v_x_i32m1(0, vl);
1538        vint32m1_t vaux_3 = __riscv_vmv_v_x_i32m1(0, vl);
1539
1540        for (int j = 0; j < QK_K; j += 128) {
1541
1542            vl = 32;
1543
1544            // load Q3
1545            vuint8mf4_t q3_x = __riscv_vle8_v_u8mf4(q3, vl);
1546
1547            vint8mf4_t q3_0 = __riscv_vreinterpret_v_u8mf4_i8mf4(__riscv_vand_vx_u8mf4(q3_x, 0x03, vl));
1548            vint8mf4_t q3_1 = __riscv_vreinterpret_v_u8mf4_i8mf4(__riscv_vand_vx_u8mf4(__riscv_vsrl_vx_u8mf4(q3_x, 0x2, vl), 0x03 , vl));
1549            vint8mf4_t q3_2 = __riscv_vreinterpret_v_u8mf4_i8mf4(__riscv_vand_vx_u8mf4(__riscv_vsrl_vx_u8mf4(q3_x, 0x4, vl), 0x03 , vl));
1550            vint8mf4_t q3_3 = __riscv_vreinterpret_v_u8mf4_i8mf4(__riscv_vand_vx_u8mf4(__riscv_vsrl_vx_u8mf4(q3_x, 0x6, vl), 0x03 , vl));
1551
1552            // compute mask for subtraction
1553            vuint8mf4_t qh_m0 = __riscv_vand_vx_u8mf4(vqh, m, vl);
1554            vbool32_t vmask_0 = __riscv_vmseq_vx_u8mf4_b32(qh_m0, 0, vl);
1555            vint8mf4_t q3_m0 = __riscv_vsub_vx_i8mf4_mu(vmask_0, q3_0, q3_0, 0x4, vl);
1556            m <<= 1;
1557
1558            vuint8mf4_t qh_m1 = __riscv_vand_vx_u8mf4(vqh, m, vl);
1559            vbool32_t vmask_1 = __riscv_vmseq_vx_u8mf4_b32(qh_m1, 0, vl);
1560            vint8mf4_t q3_m1 = __riscv_vsub_vx_i8mf4_mu(vmask_1, q3_1, q3_1, 0x4, vl);
1561            m <<= 1;
1562
1563            vuint8mf4_t qh_m2 = __riscv_vand_vx_u8mf4(vqh, m, vl);
1564            vbool32_t vmask_2 = __riscv_vmseq_vx_u8mf4_b32(qh_m2, 0, vl);
1565            vint8mf4_t q3_m2 = __riscv_vsub_vx_i8mf4_mu(vmask_2, q3_2, q3_2, 0x4, vl);
1566            m <<= 1;
1567
1568            vuint8mf4_t qh_m3 = __riscv_vand_vx_u8mf4(vqh, m, vl);
1569            vbool32_t vmask_3 = __riscv_vmseq_vx_u8mf4_b32(qh_m3, 0, vl);
1570            vint8mf4_t q3_m3 = __riscv_vsub_vx_i8mf4_mu(vmask_3, q3_3, q3_3, 0x4, vl);
1571            m <<= 1;
1572
1573            // load Q8 and take product
1574            vint16mf2_t va_q_0 = __riscv_vwmul_vv_i16mf2(q3_m0, __riscv_vle8_v_i8mf4(q8, vl), vl);
1575            vint16mf2_t va_q_1 = __riscv_vwmul_vv_i16mf2(q3_m1, __riscv_vle8_v_i8mf4(q8+32, vl), vl);
1576            vint16mf2_t va_q_2 = __riscv_vwmul_vv_i16mf2(q3_m2, __riscv_vle8_v_i8mf4(q8+64, vl), vl);
1577            vint16mf2_t va_q_3 = __riscv_vwmul_vv_i16mf2(q3_m3, __riscv_vle8_v_i8mf4(q8+96, vl), vl);
1578
1579            // accumulate
1580            vaux_0 = __riscv_vwmacc_vx_i32m1(vaux_0, scale[0], va_q_0, 16);
1581            vaux_1 = __riscv_vwmacc_vx_i32m1(vaux_1, scale[2], va_q_1, 16);
1582            vaux_2 = __riscv_vwmacc_vx_i32m1(vaux_2, scale[4], va_q_2, 16);
1583            vaux_3 = __riscv_vwmacc_vx_i32m1(vaux_3, scale[6], va_q_3, 16);
1584            //
1585            vaux_0 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_0, scale[1], va_q_0, vl);
1586            vaux_1 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_1, scale[3], va_q_1, vl);
1587            vaux_2 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_2, scale[5], va_q_2, vl);
1588            vaux_3 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_3, scale[7], va_q_3, vl);
1589
1590            q3 += 32;    q8 += 128;   scale += 8;
1591        }
1592
1593        vint32m1_t isum0 = __riscv_vredsum_vs_i32m1_i32m1(__riscv_vadd_vv_i32m1(vaux_0, vaux_1, vl), vzero, vl);
1594        vint32m1_t isum1 = __riscv_vredsum_vs_i32m1_i32m1(__riscv_vadd_vv_i32m1(vaux_2, vaux_3, vl), isum0, vl);
1595
1596        sum_t += __riscv_vmv_x_s_i32m1_i32(isum1);
1597
1598        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
1599
1600        sumf += d*sum_t;
1601    }
1602
1603    *s = sumf;
1604}
1605#endif
1606
1607void ggml_vec_dot_q3_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1608#if defined __riscv_xtheadvector
1609    ggml_vec_dot_q3_K_q8_K_xtheadvector(n, s, bs, vx, bx, vy, by, nrc);
1610#elif defined __riscv_v
1611    switch (__riscv_vlenb() * 8) {
1612        case 128:
1613            ggml_vec_dot_q3_K_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
1614            break;
1615        case 256:
1616            ggml_vec_dot_q3_K_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
1617            break;
1618        case 512:
1619            ggml_vec_dot_q3_K_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
1620            break;
1621        case 1024:
1622            ggml_vec_dot_q3_K_q8_K_vl1024(n, s, bs, vx, bx, vy, by, nrc);
1623            break;
1624        default:
1625            ggml_vec_dot_q3_K_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
1626            break;
1627    }
1628#else
1629    ggml_vec_dot_q3_K_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
1630#endif
1631}
1632
1633#if defined __riscv_xtheadvector
1634static NOINLINE void ggml_vec_dot_q4_K_q8_K_xtheadvector(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1635    assert(n % QK_K == 0);
1636    assert(nrc == 1);
1637    UNUSED(nrc);
1638    UNUSED(bx);
1639    UNUSED(by);
1640    UNUSED(bs);
1641
1642    const block_q4_K * GGML_RESTRICT x = vx;
1643    const block_q8_K * GGML_RESTRICT y = vy;
1644
1645    const int nb = n / QK_K;
1646
1647    static const uint32_t kmask1 = 0x3f3f3f3f;
1648    static const uint32_t kmask2 = 0x0f0f0f0f;
1649    static const uint32_t kmask3 = 0x03030303;
1650
1651    uint32_t utmp[4];
1652
1653    const uint8_t * scales = (const uint8_t*)&utmp[0];
1654    const uint8_t * mins   = (const uint8_t*)&utmp[2];
1655
1656    float sumf = 0;
1657
1658    for (int i = 0; i < nb; ++i) {
1659        const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
1660        const float dmin = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
1661
1662        int tmp, tmp2, sumi;
1663        __asm__ __volatile__(
1664            "li %[t1], 12\n\t"
1665            "th.vsetvli zero, %[t1], e8, m1\n\t"
1666            "th.vlb.v v1, (%[s6b])\n\t" // {aux[0], aux[1], aux[2]}
1667            "li %[t1], 4\n\t"
1668            "th.vsetvli zero, %[t1], e32, m1\n\t"
1669            "th.vslidedown.vi v2, v1, 2\n\t"
1670            "th.vmv.v.v v3, v2\n\t"
1671            "th.vslideup.vi v2, v3, 1\n\t" // {aux[2], aux[2]}
1672            "li %[t1], 2\n\t"
1673            "th.vsetvli zero, %[t1], e32, m1\n\t"
1674            "th.vmv.v.i v4, 4\n\t"
1675            "th.vand.vx v8, v1, %[kmask1]\n\t"
1676            "th.vslide1up.vx v5, v4, zero\n\t" // {0, 4}
1677            "th.vsrl.vi v6, v1, 6\n\t"
1678            "th.vsrl.vv v7, v2, v5\n\t"
1679            "th.vand.vx v0, v6, %[kmask3]\n\t"
1680            "th.vand.vx v2, v7, %[kmask2]\n\t"
1681            "th.vsll.vi v6, v0, 4\n\t"
1682            "li %[t2], 8\n\t"
1683            "addi %[t1], %[utmp], 4\n\t"
1684            "th.vor.vv v1, v6, v2\n\t"
1685            "th.vssw.v v8, (%[utmp]), %[t2]\n\t"
1686            "th.vssw.v v1, (%[t1]), %[t2]\n\t"
1687            "th.vsetvli zero, zero, e32, m2\n\t" // vl == 8
1688            "th.vlw.v v2, (%[bsums])\n\t"
1689            "th.vsetvli zero, %[t2], e16, m1\n\t"
1690            "th.vnsrl.vi v0, v2, 0\n\t"
1691            "th.vnsrl.vi v1, v2, 16\n\t"
1692            "th.vadd.vv v2, v0, v1\n\t"
1693            "th.vlbu.v v4, (%[mins])\n\t"
1694            "th.vwmul.vv v6, v4, v2\n\t"
1695            "th.vmv.v.x v0, zero\n\t"
1696            "th.vsetvli zero, %[t2], e32, m2\n\t"
1697            "th.vredsum.vs v0, v6, v0\n\t"
1698            "th.vmv.x.s %[sumi], v0"
1699            : [t1] "=&r" (tmp), [t2] "=&r" (tmp2), [sumi] "=&r" (sumi)
1700            : [bsums] "r" (y[i].bsums), [mins] "r" (mins), [utmp] "r" (utmp)
1701            , [s6b] "r" (x[i].scales), [kmask1] "r" (kmask1)
1702            , [kmask2] "r" (kmask2), [kmask3] "r" (kmask3)
1703            : "memory"
1704            , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
1705            , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
1706            , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
1707            , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
1708        );
1709        sumf -= dmin * sumi;
1710
1711        const uint8_t * restrict q4 = x[i].qs;
1712        const int8_t  * restrict q8 = y[i].qs;
1713
1714        sumi = 0;
1715        const uint8_t * scale = scales;
1716
1717        for (int j = 0; j < QK_K/128; ++j) {
1718            int vl128 = 128, vl64 = 64, vl32 = 32;
1719            __asm__ __volatile__(
1720                "th.vsetvli zero, %[vl128], e8, m8\n\t"
1721                "th.vlb.v v8, (%[q8])\n\t"
1722                "th.vsetvli zero, %[vl64], e8, m4\n\t"
1723                "th.vlb.v v0, (%[q4])\n\t"
1724                "th.vsrl.vi v4, v0, 4\n\t"
1725                "th.vand.vi v0, v0, 0xF\n\t"
1726                "th.vsetvli zero, %[vl32], e8, m2\n\t"
1727                "th.vwmul.vv v28, v6, v14\n\t"
1728                "th.vwmul.vv v20, v4, v10\n\t"
1729                "th.vwmul.vv v24, v2, v12\n\t"
1730                "th.vwmul.vv v16, v0, v8\n\t"
1731                "li %[tmp], 4\n\t"
1732                "th.vsetvli zero, %[tmp], e32, m1\n\t"
1733                "th.vlbu.v v1, (%[scale])\n\t"
1734                "th.vmv.v.x v0, zero\n\t"
1735                "th.vsetvli zero, %[vl32], e16, m4\n\t"
1736                "th.vwredsum.vs v6, v24, v0\n\t"
1737                "th.vwredsum.vs v7, v28, v0\n\t"
1738                "th.vwredsum.vs v4, v16, v0\n\t"
1739                "th.vwredsum.vs v5, v20, v0\n\t"
1740                "th.vsetvli zero, %[tmp], e32, m1\n\t"
1741                "th.vslideup.vi v6, v7, 1\n\t"
1742                "th.vslideup.vi v4, v5, 1\n\t"
1743                "th.vslideup.vi v4, v6, 2\n\t"
1744                "th.vmul.vv v8, v4, v1\n\t"
1745                "th.vredsum.vs v0, v8, v0\n\t"
1746                "th.vmv.x.s %[tmp], v0\n\t"
1747                "add %[sumi], %[sumi], %[tmp]"
1748                : [tmp] "=&r" (tmp), [sumi] "+&r" (sumi)
1749                : [vl128] "r" (vl128), [vl64] "r" (vl64), [vl32] "r" (vl32)
1750                , [q4] "r" (q4), [q8] "r" (q8), [scale] "r" (scale)
1751                : "memory"
1752                , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
1753                , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
1754                , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
1755                , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
1756            );
1757
1758            q4 += 64;    q8 += 128;    scale += 4;
1759        }
1760
1761        sumf += d * sumi;
1762
1763    }
1764
1765    *s = sumf;
1766}
1767#endif
1768
1769#if defined __riscv_v
1770static NOINLINE void ggml_vec_dot_q4_K_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1771    assert(n % QK_K == 0);
1772    assert(nrc == 1);
1773    UNUSED(nrc);
1774    UNUSED(bx);
1775    UNUSED(by);
1776    UNUSED(bs);
1777
1778    const block_q4_K * GGML_RESTRICT x = vx;
1779    const block_q8_K * GGML_RESTRICT y = vy;
1780
1781    const int nb = n / QK_K;
1782
1783    static const uint32_t kmask1 = 0x3f3f3f3f;
1784    static const uint32_t kmask2 = 0x0f0f0f0f;
1785    static const uint32_t kmask3 = 0x03030303;
1786
1787    uint32_t utmp[4];
1788
1789    const uint8_t * scales = (const uint8_t*)&utmp[0];
1790    const uint8_t * mins   = (const uint8_t*)&utmp[2];
1791
1792    float sumf = 0;
1793    for (int i = 0; i < nb; ++i) {
1794        const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
1795        const float dmin = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
1796
1797        float ftmp, ft2;
1798        const uint8_t * restrict q40;
1799        const uint8_t * restrict q41;
1800        const uint8_t * restrict q42;
1801        const uint8_t * restrict q43;
1802        const int8_t  * restrict q80;
1803        const int8_t  * restrict q81;
1804        const int8_t  * restrict q82;
1805        const int8_t  * restrict q83;
1806        int s0, s1, s2, s3;
1807
1808        __asm__ __volatile__(
1809            "li %[s1], 8\n\t"
1810            "vsetivli zero, 4, e32, m1, ta, ma\n\t"
1811            "vle32.v v1, (%[s6b])\n\t"
1812            "vslide1down.vx v1, v1, zero\n\t"
1813            "vmv.v.x v16, zero\n\t"
1814            "vslidedown.vi v2, v1, 2\n\t"
1815            "vmv1r.v v3, v2\n\t"
1816            "vslideup.vi v2, v3, 1\n\t" // {aux[2], aux[2]}
1817            "vsetivli zero, 2, e32, m1, ta, ma\n\t"
1818            "vmv.v.i v4, 4\n\t"
1819            "vand.vx v8, v1, %[kmask1]\n\t"
1820            "vslide1up.vx v5, v4, zero\n\t" // {0, 4}
1821            "vsrl.vi v6, v1, 6\n\t"
1822            "vsrl.vv v7, v2, v5\n\t"
1823            "vsse32.v v8, (%[utmp]), %[s1]\n\t"
1824            "vand.vx v0, v6, %[kmask3]\n\t"
1825            "vand.vx v2, v7, %[kmask2]\n\t"
1826            "vsll.vi v6, v0, 4\n\t"
1827            "addi %[s0], %[utmp], 4\n\t"
1828            "vor.vv v1, v6, v2\n\t"
1829            "vsse32.v v1, (%[s0]), %[s1]\n\t"
1830            "vsetivli zero, 8, e16, m1, ta, ma\n\t"
1831            "vle32.v v2, (%[bsums])\n\t"
1832            "vnsrl.wi v0, v2, 0\n\t"
1833            "vnsrl.wi v1, v2, 16\n\t"
1834            "vadd.vv v2, v0, v1\n\t"
1835            "vle8.v v3, (%[mins])\n\t"
1836            "vzext.vf2 v4, v3\n\t"
1837            "vwmul.vv v6, v4, v2\n\t"
1838            "vsetivli zero, 4, e32, m1, ta, ma\n\t"
1839            "vredsum.vs v0, v6, v16\n\t"
1840            "vredsum.vs v0, v7, v0\n\t"
1841            "vfcvt.f.x.v v0, v0\n\t"
1842            "vfmv.f.s %[ftmp], v0\n\t"
1843            "vsetivli zero, 16, e8, m1, ta, ma\n\t"
1844            "vle8.v v0, (%[xs])\n\t"
1845            "fnmsub.s %[sumf], %[dmin], %[ftmp], %[sumf]\n\t"
1846            "addi %[q40], %[xs], 64\n\t"
1847            "addi %[q41], %[xs], 16\n\t"
1848            "addi %[q42], %[xs], 32\n\t"
1849            "addi %[q43], %[xs], 48\n\t"
1850            "addi %[q80], %[ys], 64\n\t"
1851            "vle8.v v1, (%[q41])\n\t"
1852            "vle8.v v2, (%[q42])\n\t"
1853            "addi %[q81], %[ys], 16\n\t"
1854            "addi %[q41], %[q41], 64\n\t"
1855            "addi %[q82], %[ys], 32\n\t"
1856            "vle8.v v3, (%[q43])\n\t"
1857            "vle8.v v8, (%[ys])\n\t"
1858            "addi %[q42], %[q42], 64\n\t"
1859            "addi %[q83], %[ys], 48\n\t"
1860            "addi %[q43], %[q43], 64\n\t"
1861            "vsrl.vi v4, v0, 4\n\t"
1862            "vle8.v v9, (%[q81])\n\t"
1863            "vle8.v v10, (%[q82])\n\t"
1864            "vand.vi v0, v0, 0xF\n\t"
1865            "addi %[q81], %[q81], 64\n\t"
1866            "vsrl.vi v5, v1, 4\n\t"
1867            "addi %[q82], %[q82], 64\n\t"
1868            "vle8.v v11, (%[q83])\n\t"
1869            "vle8.v v12, (%[q80])\n\t"
1870            "vand.vi v1, v1, 0xF\n\t"
1871            "addi %[q83], %[q83], 64\n\t"
1872            "vsrl.vi v6, v2, 4\n\t"
1873            "addi %[q80], %[q80], 64\n\t"
1874            "vle8.v v13, (%[q81])\n\t"
1875            "vle8.v v14, (%[q82])\n\t"
1876            "vand.vi v2, v2, 0xF\n\t"
1877            "addi %[q81], %[q81], 64\n\t"
1878            "vsrl.vi v7, v3, 4\n\t"
1879            "addi %[q82], %[q82], 64\n\t"
1880            "vwmul.vv v16, v0, v8\n\t"
1881            "vle8.v v15, (%[q83])\n\t"
1882            "vle8.v v0, (%[q40])\n\t"
1883            "vand.vi v3, v3, 0xF\n\t"
1884            "addi %[q83], %[q83], 64\n\t"
1885            "vwmul.vv v24, v2, v12\n\t"
1886            "vwmul.vv v20, v4, v10\n\t"
1887            "vwmul.vv v28, v6, v14\n\t"
1888            "vwmacc.vv v16, v1, v9\n\t"
1889            "vle8.v v1, (%[q41])\n\t"
1890            "vle8.v v2, (%[q42])\n\t"
1891            "vwmacc.vv v24, v3, v13\n\t"
1892            "vwmacc.vv v20, v5, v11\n\t"
1893            "vwmacc.vv v28, v7, v15\n\t"
1894            "addi %[q40], %[q80], 64\n\t"
1895            "addi %[q41], %[q81], 64\n\t"
1896            "vle8.v v3, (%[q43])\n\t"
1897            "vle8.v v8, (%[q80])\n\t"
1898            "addi %[q42], %[q82], 64\n\t"
1899            "addi %[q43], %[q83], 64\n\t"
1900            "vsrl.vi v4, v0, 4\n\t"
1901            "vle8.v v9, (%[q81])\n\t"
1902            "vle8.v v10, (%[q82])\n\t"
1903            "vand.vi v0, v0, 0xF\n\t"
1904            "vsrl.vi v5, v1, 4\n\t"
1905            "vsrl.vi v7, v3, 4\n\t"
1906            "vand.vi v3, v3, 0xF\n\t"
1907            "vle8.v v11, (%[q83])\n\t"
1908            "vle8.v v12, (%[q40])\n\t"
1909            "vand.vi v1, v1, 0xF\n\t"
1910            "vsrl.vi v6, v2, 4\n\t"
1911            "vand.vi v2, v2, 0xF\n\t"
1912            "vwmul.vv v18, v0, v8\n\t"
1913            "vle8.v v13, (%[q41])\n\t"
1914            "vle8.v v14, (%[q42])\n\t"
1915            "vwmul.vv v26, v2, v12\n\t"
1916            "vwmul.vv v22, v4, v10\n\t"
1917            "vwmul.vv v30, v6, v14\n\t"
1918            "vwmacc.vv v18, v1, v9\n\t"
1919            "vle8.v v15, (%[q43])\n\t"
1920            "vwmacc.vv v26, v3, v13\n\t"
1921            "vwmacc.vv v22, v5, v11\n\t"
1922            "vwmacc.vv v30, v7, v15\n\t"
1923            "vmv.v.x v0, zero\n\t"
1924            "vsetivli zero, 16, e16, m2, ta, ma\n\t"
1925            "vwredsum.vs v4, v16, v0\n\t"
1926            "lbu %[s0], 0(%[scale])\n\t"
1927            "vwredsum.vs v5, v20, v0\n\t"
1928            "lbu %[s1], 1(%[scale])\n\t"
1929            "vwredsum.vs v6, v24, v0\n\t"
1930            "lbu %[s2], 2(%[scale])\n\t"
1931            "vwredsum.vs v7, v28, v0\n\t"
1932            "lbu %[s3], 3(%[scale])\n\t"
1933            "vwredsum.vs v8, v18, v0\n\t"
1934            "lbu %[q40], 4(%[scale])\n\t"
1935            "vwredsum.vs v9, v22, v0\n\t"
1936            "lbu %[q41], 5(%[scale])\n\t"
1937            "vwredsum.vs v10, v26, v0\n\t"
1938            "lbu %[q42], 6(%[scale])\n\t"
1939            "vwredsum.vs v11, v30, v0\n\t"
1940            "lbu %[q43], 7(%[scale])\n\t"
1941            "vsetivli zero, 4, e32, m1, ta, ma\n\t"
1942            "vmul.vx v0, v4, %[s0]\n\t"
1943            "vmul.vx v1, v8, %[q40]\n\t"
1944            "vmacc.vx v0, %[s1], v5\n\t"
1945            "vmacc.vx v1, %[q41], v9\n\t"
1946            "vmacc.vx v0, %[s2], v6\n\t"
1947            "vmacc.vx v1, %[q42], v10\n\t"
1948            "vmacc.vx v0, %[s3], v7\n\t"
1949            "vmacc.vx v1, %[q43], v11\n\t"
1950            "vfcvt.f.x.v v0, v0\n\t"
1951            "vfcvt.f.x.v v1, v1\n\t"
1952            "vfmv.f.s %[ft2], v0\n\t"
1953            "vfmv.f.s %[ftmp], v1\n\t"
1954            "fadd.s %[ft2], %[ft2], %[ftmp]\n\t"
1955            "fmadd.s %[sumf], %[d], %[ft2], %[sumf]"
1956            : [ftmp] "=&f" (ftmp), [sumf] "+&f" (sumf), [ft2] "=&f" (ft2)
1957            , [s0] "=&r" (s0), [s1] "=&r" (s1), [s2] "=&r" (s2), [s3] "=&r" (s3)
1958            , [q40] "=&r" (q40), [q41] "=&r" (q41), [q42] "=&r" (q42), [q43] "=&r" (q43)
1959            , [q80] "=&r" (q80), [q81] "=&r" (q81), [q82] "=&r" (q82), [q83] "=&r" (q83)
1960            : [d] "f" (d), [ys] "r" (y[i].qs), [xs] "r" (x[i].qs), [scale] "r" (scales)
1961            , [bsums] "r" (y[i].bsums), [mins] "r" (mins), [utmp] "r" (utmp)
1962            , [s6b] "r" (&x[i]), [kmask1] "r" (kmask1), [dmin] "f" (dmin)
1963            , [kmask2] "r" (kmask2), [kmask3] "r" (kmask3)
1964            : "memory"
1965            , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
1966            , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
1967            , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
1968            , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
1969        );
1970    }
1971
1972    *s = sumf;
1973}
1974
1975static NOINLINE void ggml_vec_dot_q4_K_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
1976    assert(n % QK_K == 0);
1977    assert(nrc == 1);
1978    UNUSED(nrc);
1979    UNUSED(bx);
1980    UNUSED(by);
1981    UNUSED(bs);
1982
1983    const block_q4_K * GGML_RESTRICT x = vx;
1984    const block_q8_K * GGML_RESTRICT y = vy;
1985
1986    const int nb = n / QK_K;
1987
1988    static const uint32_t kmask1 = 0x3f3f3f3f;
1989    static const uint32_t kmask2 = 0x0f0f0f0f;
1990    static const uint32_t kmask3 = 0x03030303;
1991
1992    uint32_t utmp[4];
1993
1994    const uint8_t * scales = (const uint8_t*)&utmp[0];
1995    const uint8_t * mins   = (const uint8_t*)&utmp[2];
1996
1997    float sumf = 0;
1998    for (int i = 0; i < nb; ++i) {
1999        size_t vl = 8;
2000
2001        const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
2002        const float dmin = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].dmin);
2003
2004        vint16mf2_t q8sums_0 = __riscv_vlse16_v_i16mf2(y[i].bsums, 4, vl);
2005        vint16mf2_t q8sums_1 = __riscv_vlse16_v_i16mf2(y[i].bsums+1, 4, vl);
2006        vint16mf2_t q8sums   = __riscv_vadd_vv_i16mf2(q8sums_0, q8sums_1, vl);
2007
2008        memcpy(utmp, x[i].scales, 12);
2009        utmp[3] = ((utmp[2] >> 4) & kmask2) | (((utmp[1] >> 6) & kmask3) << 4);
2010        const uint32_t uaux = utmp[1] & kmask1;
2011        utmp[1] = (utmp[2] & kmask2) | (((utmp[0] >> 6) & kmask3) << 4);
2012        utmp[2] = uaux;
2013        utmp[0] &= kmask1;
2014
2015        vuint8mf4_t mins8  = __riscv_vle8_v_u8mf4(mins, vl);
2016        vint16mf2_t v_mins = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vzext_vf2_u16mf2(mins8, vl));
2017        vint32m1_t  prod   = __riscv_vwmul_vv_i32m1(q8sums, v_mins, vl);
2018
2019        vint32m1_t sumi = __riscv_vredsum_vs_i32m1_i32m1(prod, __riscv_vmv_v_x_i32m1(0, 1), vl);
2020        sumf -= dmin * __riscv_vmv_x_s_i32m1_i32(sumi);
2021
2022        const uint8_t * GGML_RESTRICT q4 = x[i].qs;
2023        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
2024
2025        vl = 32;
2026
2027        int32_t sum_1 = 0;
2028        int32_t sum_2 = 0;
2029
2030        vint16m1_t vzero = __riscv_vmv_v_x_i16m1(0, 1);
2031
2032        for (int j = 0; j < QK_K/64; ++j) {
2033            // load Q4
2034            vuint8m1_t q4_x = __riscv_vle8_v_u8m1(q4, vl);
2035
2036            // load Q8 and multiply it with lower Q4 nibble
2037            vint8m1_t  q8_0 = __riscv_vle8_v_i8m1(q8, vl);
2038            vint8m1_t  q4_0 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vand_vx_u8m1(q4_x, 0x0F, vl));
2039            vint16m2_t qv_0 = __riscv_vwmul_vv_i16m2(q4_0, q8_0, vl);
2040            vint16m1_t vs_0 = __riscv_vredsum_vs_i16m2_i16m1(qv_0, vzero, vl);
2041
2042            sum_1 += __riscv_vmv_x_s_i16m1_i16(vs_0) * scales[2*j+0];
2043
2044            // load Q8 and multiply it with upper Q4 nibble
2045            vint8m1_t  q8_1 = __riscv_vle8_v_i8m1(q8+32, vl);
2046            vint8m1_t  q4_1 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vsrl_vx_u8m1(q4_x, 0x04, vl));
2047            vint16m2_t qv_1 = __riscv_vwmul_vv_i16m2(q4_1, q8_1, vl);
2048            vint16m1_t vs_1 = __riscv_vredsum_vs_i16m2_i16m1(qv_1, vzero, vl);
2049
2050            sum_2 += __riscv_vmv_x_s_i16m1_i16(vs_1) * scales[2*j+1];
2051
2052            q4 += 32;    q8 += 64;
2053
2054        }
2055
2056        sumf += d*(sum_1 + sum_2);
2057
2058    }
2059
2060    *s = sumf;
2061}
2062#endif
2063
2064void ggml_vec_dot_q4_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2065#if defined __riscv_xtheadvector
2066    ggml_vec_dot_q4_K_q8_K_xtheadvector(n, s, bs, vx, bx, vy, by, nrc);
2067#elif defined __riscv_v
2068    switch (__riscv_vlenb() * 8) {
2069        case 128:
2070            ggml_vec_dot_q4_K_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
2071            break;
2072        default: // 256 and above
2073            ggml_vec_dot_q4_K_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
2074            break;
2075    }
2076#else
2077    ggml_vec_dot_q4_K_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
2078#endif
2079}
2080
2081void ggml_vec_dot_q5_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy,  size_t by, int nrc) {
2082    assert(n % QK_K == 0);
2083    assert(nrc == 1);
2084    UNUSED(nrc);
2085    UNUSED(bx);
2086    UNUSED(by);
2087    UNUSED(bs);
2088
2089    const block_q5_K * GGML_RESTRICT x = vx;
2090    const block_q8_K * GGML_RESTRICT y = vy;
2091
2092    const int nb = n / QK_K;
2093
2094    static const uint32_t kmask1 = 0x3f3f3f3f;
2095    static const uint32_t kmask2 = 0x0f0f0f0f;
2096    static const uint32_t kmask3 = 0x03030303;
2097
2098    uint32_t utmp[4];
2099
2100#if defined __riscv_v
2101
2102    const uint8_t * scales = (const uint8_t*)&utmp[0];
2103    const uint8_t * mins   = (const uint8_t*)&utmp[2];
2104
2105    float sumf = 0;
2106    float sums = 0.0;
2107
2108    size_t vl;
2109
2110    for (int i = 0; i < nb; ++i) {
2111
2112        vl = 8;
2113
2114        const uint8_t * GGML_RESTRICT q5 = x[i].qs;
2115        const uint8_t * GGML_RESTRICT hm = x[i].qh;
2116        const  int8_t * GGML_RESTRICT q8 = y[i].qs;
2117
2118        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
2119        const float dmin = GGML_CPU_FP16_TO_FP32(x[i].dmin) * y[i].d;
2120
2121        vint16m1_t q8sums_0 = __riscv_vlse16_v_i16m1(y[i].bsums, 4, vl);
2122        vint16m1_t q8sums_1 = __riscv_vlse16_v_i16m1(y[i].bsums+1, 4, vl);
2123        vint16m1_t q8sums = __riscv_vadd_vv_i16m1(q8sums_0, q8sums_1, vl);
2124
2125        memcpy(utmp, x[i].scales, 12);
2126        utmp[3] = ((utmp[2] >> 4) & kmask2) | (((utmp[1] >> 6) & kmask3) << 4);
2127        const uint32_t uaux = utmp[1] & kmask1;
2128        utmp[1] = (utmp[2] & kmask2) | (((utmp[0] >> 6) & kmask3) << 4);
2129        utmp[2] = uaux;
2130        utmp[0] &= kmask1;
2131
2132        vuint8mf2_t mins8 = __riscv_vle8_v_u8mf2(mins, vl);
2133        vint16m1_t v_mins = __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vzext_vf2_u16m1(mins8, vl));
2134        vint32m2_t prod = __riscv_vwmul_vv_i32m2(q8sums, v_mins, vl);
2135
2136        vint32m1_t sumi = __riscv_vredsum_vs_i32m2_i32m1(prod, __riscv_vmv_v_x_i32m1(0, 1), vl);
2137        sumf -= dmin * __riscv_vmv_x_s_i32m1_i32(sumi);
2138
2139        vl = 32;
2140        int32_t aux32 = 0;
2141        int is = 0;
2142
2143        uint8_t m = 1;
2144        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
2145        vuint8m2_t vqh = __riscv_vle8_v_u8m2(hm, vl);
2146
2147        for (int j = 0; j < QK_K/64; ++j) {
2148            // load Q5 and Q8
2149            vuint8m2_t q5_x = __riscv_vle8_v_u8m2(q5, vl);
2150            vint8m2_t  q8_y1 = __riscv_vle8_v_i8m2(q8, vl);
2151            vint8m2_t  q8_y2 = __riscv_vle8_v_i8m2(q8+32, vl);
2152
2153            // compute mask for addition
2154            vint8m2_t q5_a = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vand_vx_u8m2(q5_x, 0x0F, vl));
2155            vuint8m2_t qh_m1 = __riscv_vand_vx_u8m2(vqh, m, vl);
2156            vbool4_t vmask_1 = __riscv_vmsne_vx_u8m2_b4(qh_m1, 0, vl);
2157            vint8m2_t q5_m1 = __riscv_vadd_vx_i8m2_mu(vmask_1, q5_a, q5_a, 16, vl);
2158            m <<= 1;
2159
2160            vint8m2_t q5_l = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vsrl_vx_u8m2(q5_x, 0x04, vl));
2161            vuint8m2_t qh_m2 = __riscv_vand_vx_u8m2(vqh, m, vl);
2162            vbool4_t vmask_2 = __riscv_vmsne_vx_u8m2_b4(qh_m2, 0, vl);
2163            vint8m2_t q5_m2 = __riscv_vadd_vx_i8m2_mu(vmask_2, q5_l, q5_l, 16, vl);
2164            m <<= 1;
2165
2166            vint16m4_t v0 = __riscv_vwmul_vv_i16m4(q5_m1, q8_y1, vl);
2167            vint16m4_t v1 = __riscv_vwmul_vv_i16m4(q5_m2, q8_y2, vl);
2168
2169            vint32m8_t vs1 = __riscv_vwmul_vx_i32m8(v0, scales[is++], vl);
2170            vint32m8_t vs2 = __riscv_vwmul_vx_i32m8(v1, scales[is++], vl);
2171
2172            vint32m1_t vacc1 = __riscv_vredsum_vs_i32m8_i32m1(vs1, vzero, vl);
2173            vint32m1_t vacc2 = __riscv_vredsum_vs_i32m8_i32m1(vs2, vacc1, vl);
2174
2175            aux32 += __riscv_vmv_x_s_i32m1_i32(vacc2);
2176            q5 += 32;    q8 += 64;
2177        }
2178
2179        sums += aux32 * d;
2180
2181    }
2182
2183    *s = sumf+sums;
2184
2185#else
2186
2187    UNUSED(x);
2188    UNUSED(y);
2189    UNUSED(kmask1);
2190    UNUSED(kmask2);
2191    UNUSED(kmask3);
2192    UNUSED(nb);
2193    UNUSED(utmp);
2194
2195    ggml_vec_dot_q5_K_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
2196#endif
2197}
2198
2199#if defined __riscv_xtheadvector
2200static NOINLINE void ggml_vec_dot_q6_K_q8_K_xtheadvector(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2201    assert(n % QK_K == 0);
2202    assert(nrc == 1);
2203    UNUSED(nrc);
2204    UNUSED(bx);
2205    UNUSED(by);
2206    UNUSED(bs);
2207
2208    const block_q6_K * GGML_RESTRICT x = vx;
2209    const block_q8_K * GGML_RESTRICT y = vy;
2210
2211    const int nb = n / QK_K;
2212
2213    float sumf = 0;
2214
2215    for (int i = 0; i < nb; ++i) {
2216
2217        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
2218
2219        const uint8_t * restrict q6 = x[i].ql;
2220        const uint8_t * restrict qh = x[i].qh;
2221        const  int8_t * restrict q8 = y[i].qs;
2222
2223        const int8_t * restrict scale = x[i].scales;
2224
2225        int sum_t = 0;
2226        int t0;
2227
2228        for (int j = 0; j < QK_K/128; ++j) {
2229            __asm__ __volatile__(
2230                "th.vsetvli zero, %[vl32], e8, m2\n\t" // vl == 32
2231                "th.vlb.v v4, (%[qh])\n\t"
2232                "th.vsll.vi v0, v4, 4\n\t"
2233                "th.vsll.vi v2, v4, 2\n\t"
2234                "th.vsrl.vi v6, v4, 2\n\t"
2235                "th.vsetvli zero, %[vl64], e8, m4\n\t" // vl == 64
2236                "th.vlb.v v8, (%[q6])\n\t"
2237                "th.vsrl.vi v12, v8, 4\n\t"
2238                "th.vand.vi v8, v8, 0xF\n\t"
2239                "th.vsetvli zero, %[vl128], e8, m8\n\t" // vl == 128
2240                "th.vand.vx v0, v0, %[mask]\n\t"
2241                "th.vor.vv v8, v8, v0\n\t"
2242                "th.vlb.v v0, (%[q8])\n\t"
2243                "th.vsub.vx v8, v8, %[vl32]\n\t"
2244                "th.vsetvli zero, %[vl64], e8, m4\n\t" // vl == 64
2245                "th.vwmul.vv v16, v0, v8\n\t"
2246                "th.vwmul.vv v24, v4, v12\n\t"
2247                "li %[t0], 16\n\t"
2248                "th.vsetvli zero, %[t0], e16, m2\n\t" // vl == 16
2249                "th.vmv.v.x v0, zero\n\t"
2250                "th.vwredsum.vs v10, v16, v0\n\t"
2251                "th.vwredsum.vs v9, v18, v0\n\t"
2252                "th.vwredsum.vs v8, v20, v0\n\t"
2253                "th.vwredsum.vs v7, v22, v0\n\t"
2254                "th.vwredsum.vs v11, v24, v0\n\t"
2255                "th.vwredsum.vs v12, v26, v0\n\t"
2256                "th.vwredsum.vs v13, v28, v0\n\t"
2257                "th.vwredsum.vs v14, v30, v0\n\t"
2258                "li %[t0], 4\n\t"
2259                "th.vsetvli zero, %[t0], e32, m1\n\t" // vl == 4
2260                "th.vslideup.vi v10, v9, 1\n\t"
2261                "th.vslideup.vi v8, v7, 1\n\t"
2262                "th.vslideup.vi v11, v12, 1\n\t"
2263                "th.vslideup.vi v13, v14, 1\n\t"
2264                "th.vslideup.vi v10, v8, 2\n\t"
2265                "th.vslideup.vi v11, v13, 2\n\t"
2266                "li %[t0], 8\n\t"
2267                "th.vsetvli zero, %[t0], e32, m2\n\t" // vl == 8
2268                "th.vlb.v v4, (%[scale])\n\t"
2269                "th.vmul.vv v2, v4, v10\n\t"
2270                "th.vredsum.vs v0, v2, v0\n\t"
2271                "th.vmv.x.s %[t0], v0\n\t"
2272                "add %[sumi], %[sumi], %[t0]"
2273                : [sumi] "+&r" (sum_t), [t0] "=&r" (t0)
2274                : [qh] "r" (qh), [q6] "r" (q6), [q8] "r" (q8), [scale] "r" (scale)
2275                , [vl32] "r" (32), [vl64] "r" (64), [vl128] "r" (128)
2276                , [mask] "r" (0x30)
2277                : "memory"
2278                , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
2279                , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
2280                , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
2281                , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
2282            );
2283            q6 += 64;   qh += 32;   q8 += 128;   scale += 8;
2284        }
2285
2286        sumf += d * sum_t;
2287
2288    }
2289
2290    *s = sumf;
2291}
2292#endif
2293
2294#if defined __riscv_v
2295static NOINLINE void ggml_vec_dot_q6_K_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2296    assert(n % QK_K == 0);
2297    assert(nrc == 1);
2298    UNUSED(nrc);
2299    UNUSED(bx);
2300    UNUSED(by);
2301    UNUSED(bs);
2302
2303    const block_q6_K * GGML_RESTRICT x = vx;
2304    const block_q8_K * GGML_RESTRICT y = vy;
2305
2306    const int nb = n / QK_K;
2307
2308    float sumf = 0.0f;
2309    for (int i = 0; i < nb; ++i) {
2310        __builtin_prefetch(&x[i + 1].d, 0, 1);
2311
2312        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
2313
2314        const uint8_t * restrict q6 = x[i].ql;
2315        const uint8_t * restrict qh = x[i].qh;
2316        const  int8_t * restrict q8 = y[i].qs;
2317
2318        const int8_t * restrict scale = x[i].scales;
2319
2320        int q6h;
2321        float ftmp;
2322
2323        for (int j = 0; j < QK_K/128; ++j) {
2324            __asm__ __volatile__(
2325                "addi %[q6h], %[q6], 32\n\t"
2326                "ld t0, 0(%[scale])\n\t"
2327                "addi %[scale], %[scale], 8\n\t"
2328                "slli t6, t0, 1 * 8\n\t"
2329                "lb zero, 0(%[q6])\n\t"
2330                "slli t5, t0, 2 * 8\n\t"
2331                "slli t4, t0, 3 * 8\n\t"
2332                "lb zero, 0(%[q6h])\n\t"
2333                "slli t3, t0, 4 * 8\n\t"
2334                "slli t2, t0, 5 * 8\n\t"
2335                "lb zero, 0(%[qh])\n\t"
2336                "lb zero, 31(%[q6h])\n\t"
2337                "slli t1, t0, 6 * 8\n\t"
2338                "srai a7, t0, 56\n\t"
2339                "vsetvli zero, %[vl32], e8, m2\n\t"
2340                "vle8.v v8, (%[q6])\n\t"
2341                "srai t6, t6, 56\n\t"
2342                "srai t5, t5, 56\n\t"
2343                "srai t4, t4, 56\n\t"
2344                "srai t3, t3, 56\n\t"
2345                "vle8.v v10, (%[q6h])\n\t"
2346                "addi %[q6], %[q6], 64\n\t"
2347                "slli t0, t0, 7 * 8\n\t"
2348                "srai t2, t2, 56\n\t"
2349                "srai t1, t1, 56\n\t"
2350                "srai t0, t0, 56\n\t"
2351                "vle8.v v4, (%[qh])\n\t"
2352                "vsrl.vi v12, v8, 4\n\t"
2353                "vsrl.vi v14, v10, 4\n\t"
2354                "lb zero, 0(%[q8])\n\t"
2355                "vand.vi v8, v8, 0xF\n\t"
2356                "vand.vi v10, v10, 0xF\n\t"
2357                "lb zero, 32(%[q8])\n\t"
2358                "vsll.vi v0, v4, 4\n\t"
2359                "vsll.vi v2, v4, 2\n\t"
2360                "lb zero, 64(%[q8])\n\t"
2361                "vsrl.vi v6, v4, 2\n\t"
2362                "vand.vx v0, v0, %[mask]\n\t"
2363                "lb zero, 96(%[q8])\n\t"
2364                "vand.vx v2, v2, %[mask]\n\t"
2365                "vand.vx v4, v4, %[mask]\n\t"
2366                "vand.vx v6, v6, %[mask]\n\t"
2367                "vor.vv v8, v8, v0\n\t"
2368                "lb zero, 127(%[q8])\n\t"
2369                "vor.vv v10, v10, v2\n\t"
2370                "vor.vv v12, v12, v4\n\t"
2371                "vor.vv v14, v14, v6\n\t"
2372                "vsetvli zero, %[vl128], e8, m8\n\t"
2373                "vle8.v v0, (%[q8])\n\t"
2374                "vsub.vx v8, v8, %[vl32]\n\t"
2375                "vsetvli zero, %[vl64], e8, m4\n\t"
2376                "vwmul.vv v16, v0, v8\n\t"
2377                "vwmul.vv v24, v4, v12\n\t"
2378                "vsetivli zero, 16, e16, m2\n\t"
2379                "vmv.v.x v0, zero\n\t"
2380                "vwredsum.vs v10, v16, v0\n\t"
2381                "vwredsum.vs v9, v18, v0\n\t"
2382                "vwredsum.vs v8, v20, v0\n\t"
2383                "vwredsum.vs v7, v22, v0\n\t"
2384                "vwredsum.vs v11, v24, v0\n\t"
2385                "vwredsum.vs v12, v26, v0\n\t"
2386                "vwredsum.vs v13, v28, v0\n\t"
2387                "vwredsum.vs v14, v30, v0\n\t"
2388                "vsetivli zero, 4, e32, m1\n\t"
2389                "vmul.vx v0, v10, t0\n\t"
2390                "vmul.vx v1, v9, t1\n\t"
2391                "vmacc.vx v0, t2, v8\n\t"
2392                "vmacc.vx v1, t3, v7\n\t"
2393                "vmacc.vx v0, t4, v11\n\t"
2394                "vmacc.vx v1, t5, v12\n\t"
2395                "vmacc.vx v0, t6, v13\n\t"
2396                "vmacc.vx v1, a7, v14\n\t"
2397                "vadd.vv v0, v0, v1\n\t"
2398                "vfcvt.f.x.v v0, v0\n\t"
2399                "vfmv.f.s %[ftmp], v0\n\t"
2400                "fmadd.s %[sumf], %[d], %[ftmp], %[sumf]"
2401                : [q6] "+&r" (q6), [q6h] "=&r" (q6h)
2402                , [scale] "+&r" (scale)
2403                , [sumf] "+&f" (sumf), [ftmp] "=&f" (ftmp)
2404                : [qh] "r" (qh), [q8] "r" (q8)
2405                , [vl32] "r" (32), [vl64] "r" (64), [vl128] "r" (128)
2406                , [mask] "r" (0x30), [d] "f" (d)
2407                : "memory"
2408                , "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7"
2409                , "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15"
2410                , "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23"
2411                , "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
2412                , "t0", "t1", "t2", "t3", "t4", "t5", "t6", "a7"
2413                , "a6", "a5", "a4", "a3"
2414            );
2415            qh += 32;   q8 += 128;
2416        }
2417    }
2418
2419    *s = sumf;
2420}
2421
2422static NOINLINE void ggml_vec_dot_q6_K_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2423    assert(n % QK_K == 0);
2424    assert(nrc == 1);
2425    UNUSED(nrc);
2426    UNUSED(bx);
2427    UNUSED(by);
2428    UNUSED(bs);
2429
2430    const block_q6_K * GGML_RESTRICT x = vx;
2431    const block_q8_K * GGML_RESTRICT y = vy;
2432
2433    const int nb = n / QK_K;
2434
2435    float sumf = 0;
2436    for (int i = 0; i < nb; ++i) {
2437        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
2438
2439        const uint8_t * GGML_RESTRICT q6 = x[i].ql;
2440        const uint8_t * GGML_RESTRICT qh = x[i].qh;
2441        const  int8_t * GGML_RESTRICT q8 = y[i].qs;
2442
2443        const int8_t * GGML_RESTRICT scale = x[i].scales;
2444
2445        size_t vl;
2446
2447        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
2448
2449        int sum_t = 0;
2450        int is = 0;
2451
2452        for (int j = 0; j < QK_K/128; ++j) {
2453
2454            vl = 32;
2455
2456            // load qh
2457            vuint8m1_t qh_x = __riscv_vle8_v_u8m1(qh, vl);
2458
2459            // load Q6
2460            vuint8m1_t q6_0 = __riscv_vle8_v_u8m1(q6, vl);
2461            vuint8m1_t q6_1 = __riscv_vle8_v_u8m1(q6+32, vl);
2462
2463            vuint8m1_t q6a_0 = __riscv_vand_vx_u8m1(q6_0, 0x0F, vl);
2464            vuint8m1_t q6a_1 = __riscv_vand_vx_u8m1(q6_1, 0x0F, vl);
2465            vuint8m1_t q6s_0 = __riscv_vsrl_vx_u8m1(q6_0, 0x04, vl);
2466            vuint8m1_t q6s_1 = __riscv_vsrl_vx_u8m1(q6_1, 0x04, vl);
2467
2468            vuint8m1_t qh_0 = __riscv_vand_vx_u8m1(qh_x, 0x03, vl);
2469            vuint8m1_t qh_1 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(qh_x, 0x2, vl), 0x03 , vl);
2470            vuint8m1_t qh_2 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(qh_x, 0x4, vl), 0x03 , vl);
2471            vuint8m1_t qh_3 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(qh_x, 0x6, vl), 0x03 , vl);
2472
2473            vuint8m1_t qhi_0 = __riscv_vor_vv_u8m1(q6a_0, __riscv_vsll_vx_u8m1(qh_0, 0x04, vl), vl);
2474            vuint8m1_t qhi_1 = __riscv_vor_vv_u8m1(q6a_1, __riscv_vsll_vx_u8m1(qh_1, 0x04, vl), vl);
2475            vuint8m1_t qhi_2 = __riscv_vor_vv_u8m1(q6s_0, __riscv_vsll_vx_u8m1(qh_2, 0x04, vl), vl);
2476            vuint8m1_t qhi_3 = __riscv_vor_vv_u8m1(q6s_1, __riscv_vsll_vx_u8m1(qh_3, 0x04, vl), vl);
2477
2478            vint8m1_t a_0 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(qhi_0), 32, vl);
2479            vint8m1_t a_1 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(qhi_1), 32, vl);
2480            vint8m1_t a_2 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(qhi_2), 32, vl);
2481            vint8m1_t a_3 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(qhi_3), 32, vl);
2482
2483            // load Q8 and take product
2484            vint16m2_t va_q_0 = __riscv_vwmul_vv_i16m2(a_0, __riscv_vle8_v_i8m1(q8, vl), vl);
2485            vint16m2_t va_q_1 = __riscv_vwmul_vv_i16m2(a_1, __riscv_vle8_v_i8m1(q8+32, vl), vl);
2486            vint16m2_t va_q_2 = __riscv_vwmul_vv_i16m2(a_2, __riscv_vle8_v_i8m1(q8+64, vl), vl);
2487            vint16m2_t va_q_3 = __riscv_vwmul_vv_i16m2(a_3, __riscv_vle8_v_i8m1(q8+96, vl), vl);
2488
2489            vl = 16;
2490
2491            vint32m2_t vaux_0 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_0, 0), scale[is+0], vl);
2492            vint32m2_t vaux_1 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_0, 1), scale[is+1], vl);
2493            vint32m2_t vaux_2 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_1, 0), scale[is+2], vl);
2494            vint32m2_t vaux_3 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_1, 1), scale[is+3], vl);
2495            vint32m2_t vaux_4 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_2, 0), scale[is+4], vl);
2496            vint32m2_t vaux_5 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_2, 1), scale[is+5], vl);
2497            vint32m2_t vaux_6 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_3, 0), scale[is+6], vl);
2498            vint32m2_t vaux_7 = __riscv_vwmul_vx_i32m2(__riscv_vget_v_i16m2_i16m1(va_q_3, 1), scale[is+7], vl);
2499
2500            vint32m1_t isum0 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_0, vaux_1, vl), vzero, vl);
2501            vint32m1_t isum1 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_2, vaux_3, vl), isum0, vl);
2502            vint32m1_t isum2 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_4, vaux_5, vl), isum1, vl);
2503            vint32m1_t isum3 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_6, vaux_7, vl), isum2, vl);
2504
2505            sum_t += __riscv_vmv_x_s_i32m1_i32(isum3);
2506
2507            q6 += 64;   qh += 32;   q8 += 128;   is=8;
2508
2509        }
2510
2511        sumf += d * sum_t;
2512
2513    }
2514
2515    *s = sumf;
2516}
2517
2518static NOINLINE void ggml_vec_dot_q6_K_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2519    assert(n % QK_K == 0);
2520    assert(nrc == 1);
2521    UNUSED(nrc);
2522    UNUSED(bx);
2523    UNUSED(by);
2524    UNUSED(bs);
2525
2526    const block_q6_K * GGML_RESTRICT x = vx;
2527    const block_q8_K * GGML_RESTRICT y = vy;
2528
2529    const int nb = n / QK_K;
2530
2531    // mask for processing 16 elements per prod register
2532    const vuint16m1_t va_index = __riscv_vid_v_u16m1(32);
2533    const vbool16_t va_mask = __riscv_vmsgtu_vx_u16m1_b16(va_index, 15, 32);
2534
2535    float sumf = 0;
2536
2537    for (int i = 0; i < nb; ++i) {
2538        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
2539
2540        const uint8_t * GGML_RESTRICT q6 = x[i].ql;
2541        const uint8_t * GGML_RESTRICT qh = x[i].qh;
2542        const  int8_t * GGML_RESTRICT q8 = y[i].qs;
2543
2544        const int8_t * GGML_RESTRICT scale = x[i].scales;
2545
2546        size_t vl = 32;
2547
2548        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
2549
2550        int sum_t = 0;
2551        int is = 0;
2552
2553        vint32m2_t vaux_0 = __riscv_vmv_v_x_i32m2(0, vl);
2554        vint32m2_t vaux_1 = __riscv_vmv_v_x_i32m2(0, vl);
2555        vint32m2_t vaux_2 = __riscv_vmv_v_x_i32m2(0, vl);
2556        vint32m2_t vaux_3 = __riscv_vmv_v_x_i32m2(0, vl);
2557
2558        for (int j = 0; j < QK_K/128; ++j) {
2559            // load qh
2560            vuint8mf2_t qh_x = __riscv_vle8_v_u8mf2(qh, vl);
2561
2562            // load Q6
2563            vuint8mf2_t q6_0 = __riscv_vle8_v_u8mf2(q6, vl);
2564            vuint8mf2_t q6_1 = __riscv_vle8_v_u8mf2(q6+32, vl);
2565
2566            vuint8mf2_t q6a_0 = __riscv_vand_vx_u8mf2(q6_0, 0x0F, vl);
2567            vuint8mf2_t q6a_1 = __riscv_vand_vx_u8mf2(q6_1, 0x0F, vl);
2568            vuint8mf2_t q6s_0 = __riscv_vsrl_vx_u8mf2(q6_0, 0x04, vl);
2569            vuint8mf2_t q6s_1 = __riscv_vsrl_vx_u8mf2(q6_1, 0x04, vl);
2570
2571            vuint8mf2_t qh_0 = __riscv_vand_vx_u8mf2(qh_x, 0x03, vl);
2572            vuint8mf2_t qh_1 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(qh_x, 0x2, vl), 0x03 , vl);
2573            vuint8mf2_t qh_2 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(qh_x, 0x4, vl), 0x03 , vl);
2574            vuint8mf2_t qh_3 = __riscv_vand_vx_u8mf2(__riscv_vsrl_vx_u8mf2(qh_x, 0x6, vl), 0x03 , vl);
2575
2576            vuint8mf2_t qhi_0 = __riscv_vor_vv_u8mf2(q6a_0, __riscv_vsll_vx_u8mf2(qh_0, 0x04, vl), vl);
2577            vuint8mf2_t qhi_1 = __riscv_vor_vv_u8mf2(q6a_1, __riscv_vsll_vx_u8mf2(qh_1, 0x04, vl), vl);
2578            vuint8mf2_t qhi_2 = __riscv_vor_vv_u8mf2(q6s_0, __riscv_vsll_vx_u8mf2(qh_2, 0x04, vl), vl);
2579            vuint8mf2_t qhi_3 = __riscv_vor_vv_u8mf2(q6s_1, __riscv_vsll_vx_u8mf2(qh_3, 0x04, vl), vl);
2580
2581            vint8mf2_t a_0 = __riscv_vsub_vx_i8mf2(__riscv_vreinterpret_v_u8mf2_i8mf2(qhi_0), 32, vl);
2582            vint8mf2_t a_1 = __riscv_vsub_vx_i8mf2(__riscv_vreinterpret_v_u8mf2_i8mf2(qhi_1), 32, vl);
2583            vint8mf2_t a_2 = __riscv_vsub_vx_i8mf2(__riscv_vreinterpret_v_u8mf2_i8mf2(qhi_2), 32, vl);
2584            vint8mf2_t a_3 = __riscv_vsub_vx_i8mf2(__riscv_vreinterpret_v_u8mf2_i8mf2(qhi_3), 32, vl);
2585
2586            // load Q8 and take product
2587            vint16m1_t va_q_0 = __riscv_vwmul_vv_i16m1(a_0, __riscv_vle8_v_i8mf2(q8, vl), vl);
2588            vint16m1_t va_q_1 = __riscv_vwmul_vv_i16m1(a_1, __riscv_vle8_v_i8mf2(q8+32, vl), vl);
2589            vint16m1_t va_q_2 = __riscv_vwmul_vv_i16m1(a_2, __riscv_vle8_v_i8mf2(q8+64, vl), vl);
2590            vint16m1_t va_q_3 = __riscv_vwmul_vv_i16m1(a_3, __riscv_vle8_v_i8mf2(q8+96, vl), vl);
2591
2592            // accumulate
2593            vaux_0 = __riscv_vwmacc_vx_i32m2(vaux_0, scale[is+0], va_q_0, 16);
2594            vaux_1 = __riscv_vwmacc_vx_i32m2(vaux_1, scale[is+2], va_q_1, 16);
2595            vaux_2 = __riscv_vwmacc_vx_i32m2(vaux_2, scale[is+4], va_q_2, 16);
2596            vaux_3 = __riscv_vwmacc_vx_i32m2(vaux_3, scale[is+6], va_q_3, 16);
2597            //
2598            vaux_0 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_0, scale[is+1], va_q_0, vl);
2599            vaux_1 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_1, scale[is+3], va_q_1, vl);
2600            vaux_2 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_2, scale[is+5], va_q_2, vl);
2601            vaux_3 = __riscv_vwmacc_vx_i32m2_m(va_mask, vaux_3, scale[is+7], va_q_3, vl);
2602
2603            q6 += 64;   qh += 32;   q8 += 128;   is=8;
2604        }
2605
2606        vint32m1_t isum0 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_0, vaux_1, vl), vzero, vl);
2607        vint32m1_t isum1 = __riscv_vredsum_vs_i32m2_i32m1(__riscv_vadd_vv_i32m2(vaux_2, vaux_3, vl), isum0, vl);
2608
2609        sum_t += __riscv_vmv_x_s_i32m1_i32(isum1);
2610
2611        sumf += d * sum_t;
2612
2613    }
2614
2615    *s = sumf;
2616}
2617
2618static NOINLINE void ggml_vec_dot_q6_K_q8_K_vl1024(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2619    assert(n % QK_K == 0);
2620    assert(nrc == 1);
2621    UNUSED(nrc);
2622    UNUSED(bx);
2623    UNUSED(by);
2624    UNUSED(bs);
2625
2626    const block_q6_K * GGML_RESTRICT x = vx;
2627    const block_q8_K * GGML_RESTRICT y = vy;
2628
2629    const int nb = n / QK_K;
2630
2631    // mask for processing 16 elements per prod register
2632    const vuint16mf2_t va_index = __riscv_vid_v_u16mf2(32);
2633    const vbool32_t va_mask = __riscv_vmsgtu_vx_u16mf2_b32(va_index, 15, 32);
2634
2635    float sumf = 0;
2636
2637    for (int i = 0; i < nb; ++i) {
2638        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
2639
2640        const uint8_t * GGML_RESTRICT q6 = x[i].ql;
2641        const uint8_t * GGML_RESTRICT qh = x[i].qh;
2642        const  int8_t * GGML_RESTRICT q8 = y[i].qs;
2643
2644        const int8_t * GGML_RESTRICT scale = x[i].scales;
2645
2646        size_t vl = 32;
2647
2648        vint32m1_t vzero = __riscv_vmv_v_x_i32m1(0, 1);
2649
2650        int sum_t = 0;
2651        int is = 0;
2652
2653        vint32m1_t vaux_0 = __riscv_vmv_v_x_i32m1(0, vl);
2654        vint32m1_t vaux_1 = __riscv_vmv_v_x_i32m1(0, vl);
2655        vint32m1_t vaux_2 = __riscv_vmv_v_x_i32m1(0, vl);
2656        vint32m1_t vaux_3 = __riscv_vmv_v_x_i32m1(0, vl);
2657
2658        for (int j = 0; j < QK_K/128; ++j) {
2659            // load qh
2660            vuint8mf4_t qh_x = __riscv_vle8_v_u8mf4(qh, vl);
2661
2662            // load Q6
2663            vuint8mf4_t q6_0 = __riscv_vle8_v_u8mf4(q6, vl);
2664            vuint8mf4_t q6_1 = __riscv_vle8_v_u8mf4(q6+32, vl);
2665
2666            vuint8mf4_t q6a_0 = __riscv_vand_vx_u8mf4(q6_0, 0x0F, vl);
2667            vuint8mf4_t q6a_1 = __riscv_vand_vx_u8mf4(q6_1, 0x0F, vl);
2668            vuint8mf4_t q6s_0 = __riscv_vsrl_vx_u8mf4(q6_0, 0x04, vl);
2669            vuint8mf4_t q6s_1 = __riscv_vsrl_vx_u8mf4(q6_1, 0x04, vl);
2670
2671            vuint8mf4_t qh_0 = __riscv_vand_vx_u8mf4(qh_x, 0x03, vl);
2672            vuint8mf4_t qh_1 = __riscv_vand_vx_u8mf4(__riscv_vsrl_vx_u8mf4(qh_x, 0x2, vl), 0x03 , vl);
2673            vuint8mf4_t qh_2 = __riscv_vand_vx_u8mf4(__riscv_vsrl_vx_u8mf4(qh_x, 0x4, vl), 0x03 , vl);
2674            vuint8mf4_t qh_3 = __riscv_vand_vx_u8mf4(__riscv_vsrl_vx_u8mf4(qh_x, 0x6, vl), 0x03 , vl);
2675
2676            vuint8mf4_t qhi_0 = __riscv_vor_vv_u8mf4(q6a_0, __riscv_vsll_vx_u8mf4(qh_0, 0x04, vl), vl);
2677            vuint8mf4_t qhi_1 = __riscv_vor_vv_u8mf4(q6a_1, __riscv_vsll_vx_u8mf4(qh_1, 0x04, vl), vl);
2678            vuint8mf4_t qhi_2 = __riscv_vor_vv_u8mf4(q6s_0, __riscv_vsll_vx_u8mf4(qh_2, 0x04, vl), vl);
2679            vuint8mf4_t qhi_3 = __riscv_vor_vv_u8mf4(q6s_1, __riscv_vsll_vx_u8mf4(qh_3, 0x04, vl), vl);
2680
2681            vint8mf4_t a_0 = __riscv_vsub_vx_i8mf4(__riscv_vreinterpret_v_u8mf4_i8mf4(qhi_0), 32, vl);
2682            vint8mf4_t a_1 = __riscv_vsub_vx_i8mf4(__riscv_vreinterpret_v_u8mf4_i8mf4(qhi_1), 32, vl);
2683            vint8mf4_t a_2 = __riscv_vsub_vx_i8mf4(__riscv_vreinterpret_v_u8mf4_i8mf4(qhi_2), 32, vl);
2684            vint8mf4_t a_3 = __riscv_vsub_vx_i8mf4(__riscv_vreinterpret_v_u8mf4_i8mf4(qhi_3), 32, vl);
2685
2686            // load Q8 and take product
2687            vint16mf2_t va_q_0 = __riscv_vwmul_vv_i16mf2(a_0, __riscv_vle8_v_i8mf4(q8, vl), vl);
2688            vint16mf2_t va_q_1 = __riscv_vwmul_vv_i16mf2(a_1, __riscv_vle8_v_i8mf4(q8+32, vl), vl);
2689            vint16mf2_t va_q_2 = __riscv_vwmul_vv_i16mf2(a_2, __riscv_vle8_v_i8mf4(q8+64, vl), vl);
2690            vint16mf2_t va_q_3 = __riscv_vwmul_vv_i16mf2(a_3, __riscv_vle8_v_i8mf4(q8+96, vl), vl);
2691
2692            // accumulate
2693            vaux_0 = __riscv_vwmacc_vx_i32m1(vaux_0, scale[is+0], va_q_0, 16);
2694            vaux_1 = __riscv_vwmacc_vx_i32m1(vaux_1, scale[is+2], va_q_1, 16);
2695            vaux_2 = __riscv_vwmacc_vx_i32m1(vaux_2, scale[is+4], va_q_2, 16);
2696            vaux_3 = __riscv_vwmacc_vx_i32m1(vaux_3, scale[is+6], va_q_3, 16);
2697            //
2698            vaux_0 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_0, scale[is+1], va_q_0, vl);
2699            vaux_1 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_1, scale[is+3], va_q_1, vl);
2700            vaux_2 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_2, scale[is+5], va_q_2, vl);
2701            vaux_3 = __riscv_vwmacc_vx_i32m1_m(va_mask, vaux_3, scale[is+7], va_q_3, vl);
2702
2703            q6 += 64;   qh += 32;   q8 += 128;   is=8;
2704
2705        }
2706
2707        vint32m1_t isum0 = __riscv_vredsum_vs_i32m1_i32m1(__riscv_vadd_vv_i32m1(vaux_0, vaux_1, vl), vzero, vl);
2708        vint32m1_t isum1 = __riscv_vredsum_vs_i32m1_i32m1(__riscv_vadd_vv_i32m1(vaux_2, vaux_3, vl), isum0, vl);
2709
2710        sum_t += __riscv_vmv_x_s_i32m1_i32(isum1);
2711
2712        sumf += d * sum_t;
2713
2714    }
2715
2716    *s = sumf;
2717}
2718#endif
2719
2720void ggml_vec_dot_q6_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2721#if defined __riscv_xtheadvector
2722    ggml_vec_dot_q6_K_q8_K_xtheadvector(n, s, bs, vx, bx, vy, by, nrc);
2723#elif defined __riscv_v
2724    switch (__riscv_vlenb() * 8) {
2725        case 128:
2726            ggml_vec_dot_q6_K_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
2727            break;
2728        case 256:
2729            ggml_vec_dot_q6_K_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
2730            break;
2731        case 512:
2732            ggml_vec_dot_q6_K_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
2733            break;
2734        case 1024:
2735            ggml_vec_dot_q6_K_q8_K_vl1024(n, s, bs, vx, bx, vy, by, nrc);
2736            break;
2737        default:
2738            ggml_vec_dot_q6_K_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
2739            break;
2740    }
2741#else
2742    ggml_vec_dot_q6_K_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
2743#endif
2744}
2745
2746#if defined __riscv_v
2747static NOINLINE void ggml_vec_dot_iq1_s_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2748    assert(n % QK_K == 0);
2749    assert(nrc == 1);
2750    UNUSED(nrc);
2751    UNUSED(bx);
2752    UNUSED(by);
2753    UNUSED(bs);
2754
2755    const block_iq1_s * GGML_RESTRICT x = vx;
2756    const block_q8_K  * GGML_RESTRICT y = vy;
2757
2758    const int nb = n / QK_K;
2759
2760    float sumf = 0;
2761    for (int i = 0; i < nb; ++i) {
2762        // Load qh once for the entire superblock.
2763        vuint16m1_t qh = __riscv_vle16_v_u16m1(x[i].qh, 8);
2764
2765        // Calculate ls.
2766        vuint16m1_t temp = __riscv_vsrl_vx_u16m1(qh, 12, 8);
2767        temp = __riscv_vand_vx_u16m1(temp, 7, 8);
2768        vint32m2_t ls = __riscv_vreinterpret_v_u32m2_i32m2(__riscv_vwmulu_vx_u32m2(temp, 2, 8));
2769        ls = __riscv_vadd_vx_i32m2(ls, 1, 8);
2770
2771        // Calculate delta.
2772        vbool16_t mask = __riscv_vmseq_vx_u16m1_b16(__riscv_vand_vx_u16m1(qh, 0x8000, 8), 0, 8);
2773        vint32m2_t delta_neg = __riscv_vmv_v_x_i32m2(-1, 8);
2774        vint32m2_t delta_pos = __riscv_vmv_v_x_i32m2(1, 8);
2775        vint32m2_t delta = __riscv_vmerge_vvm_i32m2(delta_neg, delta_pos, mask, 8);
2776
2777        // Load qs.
2778        vuint8m2_t qs = __riscv_vle8_v_u8m2(x[i].qs, 32);
2779
2780        // Prepare the indices.
2781        const uint64_t shift = 0x0009000600030000;
2782        vuint16m4_t qh_shift = __riscv_vreinterpret_v_u64m4_u16m4(__riscv_vmv_v_x_u64m4(shift, 8));
2783        vuint16m4_t qh_gather_index = __riscv_vreinterpret_v_i16m4_u16m4(
2784            __riscv_vdiv_vx_i16m4(__riscv_vreinterpret_v_u16m4_i16m4(__riscv_vid_v_u16m4(32)), 4, 32));
2785        vuint16m4_t qh_ext = __riscv_vlmul_ext_v_u16m2_u16m4(__riscv_vlmul_ext_v_u16m1_u16m2(qh));
2786        vuint16m4_t qh_index = __riscv_vrgather_vv_u16m4(qh_ext, qh_gather_index, 32);
2787        qh_index = __riscv_vsrl_vv_u16m4(qh_index, qh_shift, 32);
2788        qh_index = __riscv_vand_vx_u16m4(qh_index, 7, 32);
2789        qh_index = __riscv_vsll_vx_u16m4(qh_index, 8, 32);
2790        qh_index = __riscv_vor_vv_u16m4(qh_index, __riscv_vzext_vf2_u16m4(qs, 32), 32);
2791        vuint16m4_t index = __riscv_vsll_vx_u16m4(qh_index, 3, 32);
2792
2793        // Final lsums.
2794        int32_t lsums_s[8];
2795        vint32m1_t one_scalar = __riscv_vmv_v_x_i32m1(0, 1);
2796
2797        // Sub-blocks 1-2
2798        {
2799            vuint16m1_t grid_index0 = __riscv_vget_v_u16m4_u16m1(index, 0);
2800            vint8m4_t grid0 = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vluxei16_v_i64m4((const int64_t*)iq1s_grid, grid_index0, 8));
2801            vint8m4_t q80 = __riscv_vle8_v_i8m4(&y[i].qs[0], 64);
2802            vint16m8_t lsum0 = __riscv_vwmul_vv_i16m8(grid0, q80, 128);
2803            lsums_s[0] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 0), one_scalar, 32));
2804            lsums_s[1] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 1), one_scalar, 32));
2805        }
2806        __asm__ __volatile__("" ::: "memory");
2807        // Sub-blocks 3-4
2808        {
2809            vuint16m1_t grid_index0 = __riscv_vget_v_u16m4_u16m1(index, 1);
2810            vint8m4_t grid0 = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vluxei16_v_i64m4((const int64_t*)iq1s_grid, grid_index0, 8));
2811            vint8m4_t q80 = __riscv_vle8_v_i8m4(&y[i].qs[64], 64);
2812            vint16m8_t lsum0 = __riscv_vwmul_vv_i16m8(grid0, q80, 128);
2813            lsums_s[2] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 0), one_scalar, 32));
2814            lsums_s[3] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 1), one_scalar, 32));
2815        }
2816        __asm__ __volatile__("" ::: "memory");
2817        // Sub-blocks 5-6
2818        {
2819            vuint16m1_t grid_index0 = __riscv_vget_v_u16m4_u16m1(index, 2);
2820            vint8m4_t grid0 = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vluxei16_v_i64m4((const int64_t*)iq1s_grid, grid_index0, 8));
2821            vint8m4_t q80 = __riscv_vle8_v_i8m4(&y[i].qs[128], 64);
2822            vint16m8_t lsum0 = __riscv_vwmul_vv_i16m8(grid0, q80, 128);
2823            lsums_s[4] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 0), one_scalar, 32));
2824            lsums_s[5] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 1), one_scalar, 32));
2825        }
2826        __asm__ __volatile__("" ::: "memory");
2827        // Sub-blocks 7-8
2828        {
2829            vuint16m1_t grid_index0 = __riscv_vget_v_u16m4_u16m1(index, 3);
2830            vint8m4_t grid0 = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vluxei16_v_i64m4((const int64_t*)iq1s_grid, grid_index0, 8));
2831            vint8m4_t q80 = __riscv_vle8_v_i8m4(&y[i].qs[192], 64);
2832            vint16m8_t lsum0 = __riscv_vwmul_vv_i16m8(grid0, q80, 128);
2833            lsums_s[6] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 0), one_scalar, 32));
2834            lsums_s[7] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(lsum0, 1), one_scalar, 32));
2835        }
2836        __asm__ __volatile__("" ::: "memory");
2837        vint32m2_t lsums = __riscv_vle32_v_i32m2(&lsums_s[0], 8);
2838
2839        // Calculate the bsums.
2840        vint16m2_t bsums_0 = __riscv_vle16_v_i16m2(y[i].bsums, 16);
2841        const vuint32m2_t bsums_i32 = __riscv_vreinterpret_v_u16m2_u32m2(__riscv_vreinterpret_v_i16m2_u16m2(bsums_0));
2842        const vint16m1_t bsums_i32_0 = __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vnsrl_wx_u16m1(bsums_i32, 0, 8));
2843        const vint16m1_t bsums_i32_1 = __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vnsrl_wx_u16m1(bsums_i32, 16, 8));
2844        const vint32m2_t bsums = __riscv_vwadd_vv_i32m2(bsums_i32_0, bsums_i32_1, 8);
2845
2846        // Accumulation.
2847        vint32m2_t sumi_v = __riscv_vmul_vv_i32m2(ls, lsums, 8);
2848        vint32m2_t sumi1_v = __riscv_vmul_vv_i32m2(__riscv_vmul_vv_i32m2(ls, delta, 8), bsums, 8);
2849
2850        // Update sumf.
2851        int sumi = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(sumi_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
2852        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(sumi1_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
2853        sumf += GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d * (sumi + IQ1S_DELTA * sumi1);
2854    }
2855
2856    *s = sumf;
2857}
2858
2859static NOINLINE void ggml_vec_dot_iq1_s_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2860    assert(n % QK_K == 0);
2861    assert(nrc == 1);
2862    UNUSED(nrc);
2863    UNUSED(bx);
2864    UNUSED(by);
2865    UNUSED(bs);
2866
2867    const block_iq1_s * GGML_RESTRICT x = vx;
2868    const block_q8_K  * GGML_RESTRICT y = vy;
2869
2870    const int nb = n / QK_K;
2871
2872    float sumf = 0;
2873    for (int i = 0; i < nb; ++i) {
2874        // Load qh once for the entire superblock.
2875        vuint16mf2_t qh = __riscv_vle16_v_u16mf2(x[i].qh, 8);
2876
2877        // Calculate ls.
2878        vuint16mf2_t temp = __riscv_vsrl_vx_u16mf2(qh, 12, 8);
2879        temp = __riscv_vand_vx_u16mf2(temp, 7, 8);
2880        vint32m1_t ls = __riscv_vreinterpret_v_u32m1_i32m1(__riscv_vwmulu_vx_u32m1(temp, 2, 8));
2881        ls = __riscv_vadd_vx_i32m1(ls, 1, 8);
2882
2883        // Calculate delta.
2884        vbool32_t mask = __riscv_vmseq_vx_u16mf2_b32(__riscv_vand_vx_u16mf2(qh, 0x8000, 8), 0, 8);
2885        vint32m1_t delta_neg = __riscv_vmv_v_x_i32m1(-1, 8);
2886        vint32m1_t delta_pos = __riscv_vmv_v_x_i32m1(1, 8);
2887        vint32m1_t delta = __riscv_vmerge_vvm_i32m1(delta_neg, delta_pos, mask, 8);
2888
2889        // Load qs.
2890        vuint8m1_t qs = __riscv_vle8_v_u8m1(x[i].qs, 32);
2891
2892        // Prepare the indices.
2893        const uint64_t shift = 0x0009000600030000;
2894        vuint16m2_t qh_shift = __riscv_vreinterpret_v_u64m2_u16m2(__riscv_vmv_v_x_u64m2(shift, 8));
2895        vuint16m2_t qh_gather_index = __riscv_vreinterpret_v_i16m2_u16m2(
2896            __riscv_vdiv_vx_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vid_v_u16m2(32)), 4, 32));
2897        vuint16m2_t qh_ext = __riscv_vlmul_ext_v_u16m1_u16m2(__riscv_vlmul_ext_v_u16mf2_u16m1(qh));
2898        vuint16m2_t qh_index = __riscv_vrgather_vv_u16m2(qh_ext, qh_gather_index, 32);
2899        qh_index = __riscv_vsrl_vv_u16m2(qh_index, qh_shift, 32);
2900        qh_index = __riscv_vand_vx_u16m2(qh_index, 7, 32);
2901        qh_index = __riscv_vsll_vx_u16m2(qh_index, 8, 32);
2902        qh_index = __riscv_vor_vv_u16m2(qh_index, __riscv_vzext_vf2_u16m2(qs, 32), 32);
2903        vuint16m2_t index = __riscv_vsll_vx_u16m2(qh_index, 3, 32);
2904
2905        // Final lsums.
2906        int32_t lsums_s[8];
2907        vint32m1_t one_scalar = __riscv_vmv_v_x_i32m1(0, 1);
2908
2909        // Sub-blocks 1-4
2910        {
2911            vuint16m1_t grid_index0 = __riscv_vget_v_u16m2_u16m1(index, 0);
2912            vint8m4_t grid0 = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vluxei16_v_i64m4((const int64_t*)iq1s_grid, grid_index0, 16));
2913            vint8m4_t q80 = __riscv_vle8_v_i8m4(y[i].qs, 128);
2914            vint16m8_t lsum0 = __riscv_vwmul_vv_i16m8(grid0, q80, 128);
2915            lsums_s[0] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum0, 0), one_scalar, 32));
2916            lsums_s[1] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum0, 1), one_scalar, 32));
2917            lsums_s[2] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum0, 2), one_scalar, 32));
2918            lsums_s[3] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum0, 3), one_scalar, 32));
2919        }
2920        __asm__ __volatile__("" ::: "memory");
2921        // Sub-blocks 5-8
2922        {
2923            vuint16m1_t grid_index1 = __riscv_vget_v_u16m2_u16m1(index, 1);
2924            vint8m4_t grid1 = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vluxei16_v_i64m4((const int64_t*)iq1s_grid, grid_index1, 16));
2925            vint8m4_t q81 = __riscv_vle8_v_i8m4(&y[i].qs[128], 128);
2926            vint16m8_t lsum1 = __riscv_vwmul_vv_i16m8(grid1, q81, 128);
2927            lsums_s[4] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum1, 0), one_scalar, 32));
2928            lsums_s[5] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum1, 1), one_scalar, 32));
2929            lsums_s[6] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum1, 2), one_scalar, 32));
2930            lsums_s[7] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(lsum1, 3), one_scalar, 32));
2931        }
2932        __asm__ __volatile__("" ::: "memory");
2933        vint32m1_t lsums = __riscv_vle32_v_i32m1(&lsums_s[0], 8);
2934
2935        // Calculate the bsums.
2936        vint16m1_t bsums_0 = __riscv_vle16_v_i16m1(y[i].bsums, 16);
2937        const vuint32m1_t bsums_i32 = __riscv_vreinterpret_v_u16m1_u32m1(__riscv_vreinterpret_v_i16m1_u16m1(bsums_0));
2938        const vint16mf2_t bsums_i32_0 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(bsums_i32, 0, 8));
2939        const vint16mf2_t bsums_i32_1 = __riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vnsrl_wx_u16mf2(bsums_i32, 16, 8));
2940        const vint32m1_t bsums = __riscv_vwadd_vv_i32m1(bsums_i32_0, bsums_i32_1, 8);
2941
2942        // Accumulation.
2943        vint32m1_t sumi_v = __riscv_vmul_vv_i32m1(ls, lsums, 8);
2944        vint32m1_t sumi1_v = __riscv_vmul_vv_i32m1(__riscv_vmul_vv_i32m1(ls, delta, 8), bsums, 8);
2945
2946        // Update sumf.
2947        int sumi = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m1_i32m1(sumi_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
2948        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m1_i32m1(sumi1_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
2949        sumf += GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d * (sumi + IQ1S_DELTA * sumi1);
2950    }
2951
2952    *s = sumf;
2953}
2954
2955static NOINLINE void ggml_vec_dot_iq1_s_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
2956    assert(n % QK_K == 0);
2957    assert(nrc == 1);
2958    UNUSED(nrc);
2959    UNUSED(bx);
2960    UNUSED(by);
2961    UNUSED(bs);
2962
2963    const block_iq1_s * GGML_RESTRICT x = vx;
2964    const block_q8_K  * GGML_RESTRICT y = vy;
2965
2966    const int nb = n / QK_K;
2967
2968    float sumf = 0;
2969    for (int i = 0; i < nb; ++i) {
2970        // Load qh once for the entire superblock.
2971        vuint16mf4_t qh = __riscv_vle16_v_u16mf4(x[i].qh, 8);
2972
2973        // Calculate ls.
2974        vuint16mf4_t temp = __riscv_vsrl_vx_u16mf4(qh, 12, 8);
2975        temp = __riscv_vand_vx_u16mf4(temp, 7, 8);
2976        vint32mf2_t ls = __riscv_vreinterpret_v_u32mf2_i32mf2(__riscv_vwmulu_vx_u32mf2(temp, 2, 8));
2977        ls = __riscv_vadd_vx_i32mf2(ls, 1, 8);
2978
2979        // Calculate delta.
2980        vbool64_t mask = __riscv_vmseq_vx_u16mf4_b64(__riscv_vand_vx_u16mf4(qh, 0x8000, 8), 0, 8);
2981        vint32mf2_t delta_neg = __riscv_vmv_v_x_i32mf2(-1, 8);
2982        vint32mf2_t delta_pos = __riscv_vmv_v_x_i32mf2(1, 8);
2983        vint32mf2_t delta = __riscv_vmerge_vvm_i32mf2(delta_neg, delta_pos, mask, 8);
2984
2985        // Load qs.
2986        vuint8mf2_t qs = __riscv_vle8_v_u8mf2(x[i].qs, 32);
2987
2988        // Prepare the indices.
2989        const uint64_t shift = 0x0009000600030000;
2990        vuint16m1_t qh_shift = __riscv_vreinterpret_v_u64m1_u16m1(__riscv_vmv_v_x_u64m1(shift, 8));
2991        vuint16m1_t qh_gather_index = __riscv_vreinterpret_v_i16m1_u16m1(
2992            __riscv_vdiv_vx_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vid_v_u16m1(32)), 4, 32));
2993        vuint16m1_t qh_ext = __riscv_vlmul_ext_v_u16mf2_u16m1(__riscv_vlmul_ext_v_u16mf4_u16mf2(qh));
2994        vuint16m1_t qh_index = __riscv_vrgather_vv_u16m1(qh_ext, qh_gather_index, 32);
2995        qh_index = __riscv_vsrl_vv_u16m1(qh_index, qh_shift, 32);
2996        qh_index = __riscv_vand_vx_u16m1(qh_index, 7, 32);
2997        qh_index = __riscv_vsll_vx_u16m1(qh_index, 8, 32);
2998        qh_index = __riscv_vor_vv_u16m1(qh_index, __riscv_vzext_vf2_u16m1(qs, 32), 32);
2999        vuint16m1_t index = __riscv_vsll_vx_u16m1(qh_index, 3, 32);
3000
3001        // Final lsums.
3002        int32_t lsums_s[8];
3003        vint32m1_t one_scalar = __riscv_vmv_v_x_i32m1(0, 1);
3004
3005        // Sub-blocks 1-8
3006        {
3007            vint8m4_t grid0 = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vluxei16_v_i64m4((const int64_t*)iq1s_grid, index, 32));
3008            vint8m4_t q80 = __riscv_vle8_v_i8m4(y[i].qs, 256);
3009            vint16m8_t lsum0 = __riscv_vwmul_vv_i16m8(grid0, q80, 256);
3010            lsums_s[0] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 0), one_scalar, 32));
3011            lsums_s[1] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 1), one_scalar, 32));
3012            lsums_s[2] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 2), one_scalar, 32));
3013            lsums_s[3] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 3), one_scalar, 32));
3014            lsums_s[4] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 4), one_scalar, 32));
3015            lsums_s[5] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 5), one_scalar, 32));
3016            lsums_s[6] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 6), one_scalar, 32));
3017            lsums_s[7] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(lsum0, 7), one_scalar, 32));
3018        }
3019        __asm__ __volatile__("" ::: "memory");
3020        vint32mf2_t lsums = __riscv_vle32_v_i32mf2(&lsums_s[0], 8);
3021
3022        // Calculate the bsums.
3023        vint16mf2_t bsums_0 = __riscv_vle16_v_i16mf2(y[i].bsums, 16);
3024        const vuint32mf2_t bsums_i32 = __riscv_vreinterpret_v_u16mf2_u32mf2(__riscv_vreinterpret_v_i16mf2_u16mf2(bsums_0));
3025        const vint16mf4_t bsums_i32_0 = __riscv_vreinterpret_v_u16mf4_i16mf4(__riscv_vnsrl_wx_u16mf4(bsums_i32, 0, 8));
3026        const vint16mf4_t bsums_i32_1 = __riscv_vreinterpret_v_u16mf4_i16mf4(__riscv_vnsrl_wx_u16mf4(bsums_i32, 16, 8));
3027        const vint32mf2_t bsums = __riscv_vwadd_vv_i32mf2(bsums_i32_0, bsums_i32_1, 8);
3028
3029        // Accumulation.
3030        vint32mf2_t sumi_v = __riscv_vmul_vv_i32mf2(ls, lsums, 8);
3031        vint32mf2_t sumi1_v = __riscv_vmul_vv_i32mf2(__riscv_vmul_vv_i32mf2(ls, delta, 8), bsums, 8);
3032
3033        // Update sumf.
3034        int sumi = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32mf2_i32m1(sumi_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
3035        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32mf2_i32m1(sumi1_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
3036        sumf += GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d * (sumi + IQ1S_DELTA * sumi1);
3037    }
3038
3039    *s = sumf;
3040}
3041
3042static NOINLINE void ggml_vec_dot_iq1_s_q8_K_vl1024(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3043    assert(n % QK_K == 0);
3044    assert(nrc == 1);
3045    UNUSED(nrc);
3046    UNUSED(bx);
3047    UNUSED(by);
3048    UNUSED(bs);
3049
3050    const block_iq1_s * GGML_RESTRICT x = vx;
3051    const block_q8_K  * GGML_RESTRICT y = vy;
3052
3053    const int nb = n / QK_K;
3054
3055    // Mask for processing 32 elements per lsum register.
3056    vuint16m1_t l_index = __riscv_vid_v_u16m1(64);
3057    vbool16_t l_mask = __riscv_vmsgtu_vx_u16m1_b16(l_index, 31, 64);
3058
3059    float sumf = 0;
3060    for (int i = 0; i < nb; ++i) {
3061        // Load qh once for the entire superblock.
3062        vuint16mf4_t qh = __riscv_vle16_v_u16mf4(x[i].qh, 8);
3063
3064        // Calculate ls.
3065        vuint16mf4_t temp = __riscv_vsrl_vx_u16mf4(qh, 12, 8);
3066        temp = __riscv_vand_vx_u16mf4(temp, 7, 8);
3067        vint32mf2_t ls = __riscv_vreinterpret_v_u32mf2_i32mf2(__riscv_vwmulu_vx_u32mf2(temp, 2, 8));
3068        ls = __riscv_vadd_vx_i32mf2(ls, 1, 8);
3069
3070        // Calculate delta.
3071        vbool64_t mask = __riscv_vmseq_vx_u16mf4_b64(__riscv_vand_vx_u16mf4(qh, 0x8000, 8), 0, 8);
3072        vint32mf2_t delta_neg = __riscv_vmv_v_x_i32mf2(-1, 8);
3073        vint32mf2_t delta_pos = __riscv_vmv_v_x_i32mf2(1, 8);
3074        vint32mf2_t delta = __riscv_vmerge_vvm_i32mf2(delta_neg, delta_pos, mask, 8);
3075
3076        // Load qs.
3077        vuint8mf2_t qs = __riscv_vle8_v_u8mf2(x[i].qs, 32);
3078
3079        // Prepare the indices.
3080        const uint64_t shift = 0x0009000600030000;
3081        vuint16m1_t qh_shift = __riscv_vreinterpret_v_u64m1_u16m1(__riscv_vmv_v_x_u64m1(shift, 8));
3082        vuint16m1_t qh_gather_index = __riscv_vreinterpret_v_i16m1_u16m1(
3083            __riscv_vdiv_vx_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vid_v_u16m1(32)), 4, 32));
3084        vuint16m1_t qh_ext = __riscv_vlmul_ext_v_u16mf2_u16m1(__riscv_vlmul_ext_v_u16mf4_u16mf2(qh));
3085        vuint16m1_t qh_index = __riscv_vrgather_vv_u16m1(qh_ext, qh_gather_index, 32);
3086        qh_index = __riscv_vsrl_vv_u16m1(qh_index, qh_shift, 32);
3087        qh_index = __riscv_vand_vx_u16m1(qh_index, 7, 32);
3088        qh_index = __riscv_vsll_vx_u16m1(qh_index, 8, 32);
3089        qh_index = __riscv_vor_vv_u16m1(qh_index, __riscv_vzext_vf2_u16m1(qs, 32), 32);
3090        vuint16mf2_t index = __riscv_vlmul_trunc_v_u16m1_u16mf2(__riscv_vsll_vx_u16m1(qh_index, 3, 32));
3091
3092        // Final lsums.
3093        int32_t lsums_s[8];
3094        vint32m1_t one_scalar = __riscv_vmv_v_x_i32m1(0, 1);
3095
3096        // Sub-blocks 1-8
3097        {
3098            vint8m2_t grid0 = __riscv_vreinterpret_v_i64m2_i8m2(__riscv_vluxei16_v_i64m2((const int64_t*)iq1s_grid, index, 32));
3099            vint8m2_t q80 = __riscv_vle8_v_i8m2(y[i].qs, 256);
3100            vint16m4_t lsum0 = __riscv_vwmul_vv_i16m4(grid0, q80, 256);
3101
3102            // Reduce.
3103            lsums_s[0] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(          __riscv_vget_v_i16m4_i16m1(lsum0, 0), one_scalar, 32));
3104            lsums_s[1] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(l_mask, __riscv_vget_v_i16m4_i16m1(lsum0, 0), one_scalar, 64));
3105            lsums_s[2] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(          __riscv_vget_v_i16m4_i16m1(lsum0, 1), one_scalar, 32));
3106            lsums_s[3] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(l_mask, __riscv_vget_v_i16m4_i16m1(lsum0, 1), one_scalar, 64));
3107            lsums_s[4] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(          __riscv_vget_v_i16m4_i16m1(lsum0, 2), one_scalar, 32));
3108            lsums_s[5] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(l_mask, __riscv_vget_v_i16m4_i16m1(lsum0, 2), one_scalar, 64));
3109            lsums_s[6] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(          __riscv_vget_v_i16m4_i16m1(lsum0, 3), one_scalar, 32));
3110            lsums_s[7] = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(l_mask, __riscv_vget_v_i16m4_i16m1(lsum0, 3), one_scalar, 64));
3111        }
3112        __asm__ __volatile__("" ::: "memory");
3113        vint32mf2_t lsums = __riscv_vle32_v_i32mf2(&lsums_s[0], 8);
3114
3115        // Calculate the bsums.
3116        vint16mf2_t bsums_0 = __riscv_vle16_v_i16mf2(y[i].bsums, 16);
3117        const vuint32mf2_t bsums_i32 = __riscv_vreinterpret_v_u16mf2_u32mf2(__riscv_vreinterpret_v_i16mf2_u16mf2(bsums_0));
3118        const vint16mf4_t bsums_i32_0 = __riscv_vreinterpret_v_u16mf4_i16mf4(__riscv_vnsrl_wx_u16mf4(bsums_i32, 0, 8));
3119        const vint16mf4_t bsums_i32_1 = __riscv_vreinterpret_v_u16mf4_i16mf4(__riscv_vnsrl_wx_u16mf4(bsums_i32, 16, 8));
3120        const vint32mf2_t bsums = __riscv_vwadd_vv_i32mf2(bsums_i32_0, bsums_i32_1, 8);
3121
3122        // Accumulation.
3123        vint32mf2_t sumi_v = __riscv_vmul_vv_i32mf2(ls, lsums, 8);
3124        vint32mf2_t sumi1_v = __riscv_vmul_vv_i32mf2(__riscv_vmul_vv_i32mf2(ls, delta, 8), bsums, 8);
3125
3126        // Update sumf.
3127        int sumi = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32mf2_i32m1(sumi_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
3128        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32mf2_i32m1(sumi1_v, __riscv_vmv_v_x_i32m1(0.0f, 1), 8));
3129        sumf += GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d * (sumi + IQ1S_DELTA * sumi1);
3130    }
3131
3132    *s = sumf;
3133}
3134#endif
3135
3136void ggml_vec_dot_iq1_s_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3137#if defined __riscv_v
3138    switch (__riscv_vlenb() * 8) {
3139        case 128:
3140            ggml_vec_dot_iq1_s_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
3141            break;
3142        case 256:
3143            ggml_vec_dot_iq1_s_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
3144            break;
3145        case 512:
3146            ggml_vec_dot_iq1_s_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
3147            break;
3148        case 1024:
3149            ggml_vec_dot_iq1_s_q8_K_vl1024(n, s, bs, vx, bx, vy, by, nrc);
3150            break;
3151        default:
3152            ggml_vec_dot_iq1_s_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
3153            break;
3154    }
3155#else
3156    ggml_vec_dot_iq1_s_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
3157#endif
3158}
3159
3160#if defined __riscv_v
3161static NOINLINE void ggml_vec_dot_iq1_m_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3162    assert(n % QK_K == 0);
3163    assert(nrc == 1);
3164    UNUSED(nrc);
3165    UNUSED(bx);
3166    UNUSED(by);
3167    UNUSED(bs);
3168
3169    const block_iq1_m * GGML_RESTRICT x = vx;
3170    const block_q8_K  * GGML_RESTRICT y = vy;
3171
3172    const int nb = n / QK_K;
3173
3174    iq1m_scale_t scale;
3175    float sumf = 0.0f;
3176    for (int i = 0; i < nb; ++i) {
3177        const int8_t   * q8 = y[i].qs;
3178        const uint8_t  * qs = x[i].qs;
3179        const uint8_t  * qh = x[i].qh;
3180        const uint16_t * sc = (const uint16_t *)x[i].scales;
3181
3182        scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000);
3183
3184        // Accumulators.
3185        vint32m4_t acc1 = __riscv_vmv_v_x_i32m4(0, 16);
3186        vint32m4_t acc2 = __riscv_vmv_v_x_i32m4(0, 16);
3187
3188        // We process 8 16-element sub-blocks together.
3189        #pragma GCC unroll 1
3190        for (int ib = 0; ib < QK_K/128; ib++) {
3191            // Load qh for 8 sub-blocks.
3192            const vuint8mf2_t qh_8 = __riscv_vle8_v_u8mf2(qh, 8);
3193            const vuint16m1_t qh_16_lo = __riscv_vzext_vf2_u16m1(qh_8, 8);
3194            const vuint16m1_t qh_16_hi = __riscv_vsll_vx_u16m1(qh_16_lo, 8, 8);
3195            const vuint16m2_t qhb = __riscv_vzext_vf2_u16m2(
3196                __riscv_vreinterpret_v_u16m1_u8m1(__riscv_vor_vv_u16m1(qh_16_lo, qh_16_hi, 8)), 16);
3197            qh += 8;
3198
3199            // Prepare grid indices.
3200            const vuint16m2_t qsb = __riscv_vzext_vf2_u16m2(__riscv_vle8_v_u8m1(&qs[0], 16), 16);
3201            const vuint16m2_t shift = __riscv_vreinterpret_v_u32m2_u16m2(__riscv_vmv_v_x_u32m2(0x00040008, 8));
3202            vuint16m2_t index = __riscv_vor_vv_u16m2(qsb, __riscv_vand_vx_u16m2(__riscv_vsll_vv_u16m2(qhb, shift, 16), 0x700, 16), 16);
3203            index = __riscv_vsll_vx_u16m2(index, 3, 16);
3204            qs += 16;
3205
3206            // Prepare the deltas.
3207            const vbool8_t mask = __riscv_vmsgtu_vx_u16m2_b8(
3208                __riscv_vand_vv_u16m2(qhb, __riscv_vreinterpret_v_u32m2_u16m2(__riscv_vmv_v_x_u32m2(0x00800008, 8)), 16), 0, 16);
3209            const vint64m8_t delta_pos = __riscv_vmv_v_x_i64m8(0x0101010101010101, 16);
3210            const vint8m8_t delta = __riscv_vreinterpret_v_i64m8_i8m8(
3211                __riscv_vmerge_vxm_i64m8(delta_pos, 0xffffffffffffffff, mask, 16));
3212
3213            // Sub-blocks 0-3
3214            {
3215                // Load the grid.
3216                const vint8m4_t iq1b = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vreinterpret_v_u64m4_i64m4(
3217                    __riscv_vluxei16_v_u64m4(iq1s_grid, __riscv_vget_v_u16m2_u16m1(index, 0), 8)));
3218
3219                // Calculate the lsums.
3220                //
3221                // Sub-block 0, 1
3222                {
3223                    // Load q8 for each sub-block.
3224                    const vint8m2_t q8b = __riscv_vle8_v_i8m2(q8, 32);
3225                    q8 += 32;
3226
3227                    // Calculate the lsums.
3228                    const vint16m4_t lsum1 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m4_i8m2(iq1b, 0), q8b, 32);
3229                    const vint16m4_t lsum2 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m8_i8m2(delta, 0), q8b, 32);
3230
3231                    // Prepare the scales.
3232                    const int16_t ls_0 = 2*((sc[0] >> 0) & 0x7) + 1;
3233                    const int16_t ls_1 = 2*((sc[0] >> 3) & 0x7) + 1;
3234
3235                    // Accumulate in acc0 and acc1 for each sub-block.
3236                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_0, __riscv_vget_v_i16m4_i16m2(lsum1, 0), 16);
3237                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_1, __riscv_vget_v_i16m4_i16m2(lsum1, 1), 16);
3238                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_0, __riscv_vget_v_i16m4_i16m2(lsum2, 0), 16);
3239                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_1, __riscv_vget_v_i16m4_i16m2(lsum2, 1), 16);
3240                }
3241                __asm__ __volatile__("" ::: "memory");
3242                // Sub-block 2, 3
3243                {
3244                    // Load q8 for each sub-block.
3245                    const vint8m2_t q8b = __riscv_vle8_v_i8m2(q8, 32);
3246                    q8 += 32;
3247
3248                    // Calculate the lsums.
3249                    const vint16m4_t lsum1 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m4_i8m2(iq1b, 1), q8b, 32);
3250                    const vint16m4_t lsum2 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m8_i8m2(delta, 1), q8b, 32);
3251
3252                    // Prepare the scales.
3253                    const int16_t ls_0 = 2*((sc[0] >> 6) & 0x7) + 1;
3254                    const int16_t ls_1 = 2*((sc[0] >> 9) & 0x7) + 1;
3255
3256                    // Accumulate in acc0 and acc1 for each sub-block.
3257                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_0, __riscv_vget_v_i16m4_i16m2(lsum1, 0), 16);
3258                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_1, __riscv_vget_v_i16m4_i16m2(lsum1, 1), 16);
3259                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_0, __riscv_vget_v_i16m4_i16m2(lsum2, 0), 16);
3260                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_1, __riscv_vget_v_i16m4_i16m2(lsum2, 1), 16);
3261                }
3262                sc += 1;
3263            }
3264            __asm__ __volatile__("" ::: "memory");
3265            // Sub-blocks 4-7
3266            {
3267                // Load the grid.
3268                const vint8m4_t iq1b = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vreinterpret_v_u64m4_i64m4(
3269                    __riscv_vluxei16_v_u64m4(iq1s_grid, __riscv_vget_v_u16m2_u16m1(index, 1), 8)));
3270
3271                // Calculate the lsums.
3272                //
3273                // Sub-block 4, 5
3274                {
3275                    // Load q8 for each sub-block.
3276                    const vint8m2_t q8b = __riscv_vle8_v_i8m2(q8, 32);
3277                    q8 += 32;
3278
3279                    // Calculate the lsums.
3280                    const vint16m4_t lsum1 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m4_i8m2(iq1b, 0), q8b, 32);
3281                    const vint16m4_t lsum2 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m8_i8m2(delta, 2), q8b, 32);
3282
3283                    // Prepare the scales.
3284                    const int16_t ls_0 = 2*((sc[0] >> 0) & 0x7) + 1;
3285                    const int16_t ls_1 = 2*((sc[0] >> 3) & 0x7) + 1;
3286
3287                    // Accumulate in acc0 and acc1 for each sub-block.
3288                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_0, __riscv_vget_v_i16m4_i16m2(lsum1, 0), 16);
3289                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_1, __riscv_vget_v_i16m4_i16m2(lsum1, 1), 16);
3290                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_0, __riscv_vget_v_i16m4_i16m2(lsum2, 0), 16);
3291                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_1, __riscv_vget_v_i16m4_i16m2(lsum2, 1), 16);
3292                }
3293                __asm__ __volatile__("" ::: "memory");
3294                // Sub-block 6, 7
3295                {
3296                    // Load q8 for each sub-block.
3297                    const vint8m2_t q8b = __riscv_vle8_v_i8m2(q8, 32);
3298                    q8 += 32;
3299
3300                    // Calculate the lsums.
3301                    const vint16m4_t lsum1 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m4_i8m2(iq1b, 1), q8b, 32);
3302                    const vint16m4_t lsum2 = __riscv_vwmul_vv_i16m4(__riscv_vget_v_i8m8_i8m2(delta, 3), q8b, 32);
3303
3304                    // Prepare the scales.
3305                    const int16_t ls_0 = 2*((sc[0] >> 6) & 0x7) + 1;
3306                    const int16_t ls_1 = 2*((sc[0] >> 9) & 0x7) + 1;
3307
3308                    // Accumulate in acc0 and acc1 for each sub-block.
3309                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_0, __riscv_vget_v_i16m4_i16m2(lsum1, 0), 16);
3310                    acc1 = __riscv_vwmacc_vx_i32m4(acc1, ls_1, __riscv_vget_v_i16m4_i16m2(lsum1, 1), 16);
3311                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_0, __riscv_vget_v_i16m4_i16m2(lsum2, 0), 16);
3312                    acc2 = __riscv_vwmacc_vx_i32m4(acc2, ls_1, __riscv_vget_v_i16m4_i16m2(lsum2, 1), 16);
3313                }
3314                sc += 1;
3315            }
3316        }
3317
3318        // Reduce and accumulate in `sumf`.
3319        vint32m1_t one = __riscv_vmv_v_x_i32m1(0, 1);
3320        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m4_i32m1(acc1, one, 16));
3321        int sumi2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m4_i32m1(acc2, one, 16));
3322        sumf += y[i].d * GGML_CPU_FP16_TO_FP32(scale.f16) * (sumi1 + IQ1M_DELTA * sumi2);
3323    }
3324
3325    *s = sumf;
3326}
3327
3328static NOINLINE void ggml_vec_dot_iq1_m_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3329    assert(n % QK_K == 0);
3330    assert(nrc == 1);
3331    UNUSED(nrc);
3332    UNUSED(bx);
3333    UNUSED(by);
3334    UNUSED(bs);
3335
3336    const block_iq1_m * GGML_RESTRICT x = vx;
3337    const block_q8_K  * GGML_RESTRICT y = vy;
3338
3339    const int nb = n / QK_K;
3340
3341    iq1m_scale_t scale;
3342    float sumf = 0.0f;
3343    for (int i = 0; i < nb; ++i) {
3344        const int8_t   * q8 = y[i].qs;
3345        const uint8_t  * qs = x[i].qs;
3346        const uint8_t  * qh = x[i].qh;
3347        const uint16_t * sc = (const uint16_t *)x[i].scales;
3348
3349        scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000);
3350
3351        // Accumulators.
3352        vint32m2_t acc1 = __riscv_vmv_v_x_i32m2(0, 16);
3353        vint32m2_t acc2 = __riscv_vmv_v_x_i32m2(0, 16);
3354
3355        // We process 8 16-element sub-blocks together.
3356        #pragma GCC unroll 1
3357        for (int ib = 0; ib < QK_K/128; ib++) {
3358            // Load qh for 8 sub-blocks.
3359            const vuint8mf4_t qh_8 = __riscv_vle8_v_u8mf4(qh, 8);
3360            const vuint16mf2_t qh_16_lo = __riscv_vzext_vf2_u16mf2(qh_8, 8);
3361            const vuint16mf2_t qh_16_hi = __riscv_vsll_vx_u16mf2(qh_16_lo, 8, 8);
3362            const vuint16m1_t qhb = __riscv_vzext_vf2_u16m1(
3363                __riscv_vreinterpret_v_u16mf2_u8mf2(__riscv_vor_vv_u16mf2(qh_16_lo, qh_16_hi, 8)), 16);
3364            qh += 8;
3365
3366            __asm__ __volatile__("" ::: "memory");
3367
3368            // Prepare grid indices.
3369            const vuint16m1_t qsb = __riscv_vzext_vf2_u16m1(__riscv_vle8_v_u8mf2(&qs[0], 16), 16);
3370            const vuint16m1_t shift = __riscv_vreinterpret_v_u32m1_u16m1(__riscv_vmv_v_x_u32m1(0x00040008, 8));
3371            vuint16m1_t index = __riscv_vor_vv_u16m1(qsb, __riscv_vand_vx_u16m1(__riscv_vsll_vv_u16m1(qhb, shift, 16), 0x700, 16), 16);
3372            index = __riscv_vsll_vx_u16m1(index, 3, 16);
3373            qs += 16;
3374
3375            __asm__ __volatile__("" ::: "memory");
3376
3377            // Load the grid.
3378            const vint8m4_t iq1b = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vreinterpret_v_u64m4_i64m4(
3379                __riscv_vluxei16_v_u64m4(iq1s_grid, index, 16)));
3380
3381            // Prepare the deltas.
3382            const vbool16_t mask = __riscv_vmsgtu_vx_u16m1_b16(
3383                __riscv_vand_vv_u16m1(qhb, __riscv_vreinterpret_v_u32m1_u16m1(__riscv_vmv_v_x_u32m1(0x00800008, 8)), 16), 0, 16);
3384            const vint64m4_t delta_pos = __riscv_vmv_v_x_i64m4(0x0101010101010101, 16);
3385            const vint8m4_t delta = __riscv_vreinterpret_v_i64m4_i8m4(
3386                __riscv_vmerge_vxm_i64m4(delta_pos, 0xffffffffffffffff, mask, 16));
3387
3388            // Load q8 for sub-blocks.
3389            const vint8m4_t q8b = __riscv_vle8_v_i8m4(q8, 128);
3390            q8 += 128;
3391
3392            // Calculate the lsums.
3393            const vint16m8_t lsum1 = __riscv_vwmul_vv_i16m8(iq1b, q8b, 128);
3394            const vint16m8_t lsum2 = __riscv_vwmul_vv_i16m8(delta, q8b, 128);
3395
3396            // Prepare the scales.
3397            const int16_t ls_0_0 = 2*((sc[0] >> 0) & 0x7) + 1;
3398            const int16_t ls_0_1 = 2*((sc[0] >> 3) & 0x7) + 1;
3399            const int16_t ls_1_0 = 2*((sc[0] >> 6) & 0x7) + 1;
3400            const int16_t ls_1_1 = 2*((sc[0] >> 9) & 0x7) + 1;
3401            const int16_t ls_2_0 = 2*((sc[1] >> 0) & 0x7) + 1;
3402            const int16_t ls_2_1 = 2*((sc[1] >> 3) & 0x7) + 1;
3403            const int16_t ls_3_0 = 2*((sc[1] >> 6) & 0x7) + 1;
3404            const int16_t ls_3_1 = 2*((sc[1] >> 9) & 0x7) + 1;
3405            sc += 2;
3406
3407            // Accumulate in acc0 and acc1 for each sub-block.
3408            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_0_0, __riscv_vget_v_i16m8_i16m1(lsum1, 0), 16);
3409            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_0_1, __riscv_vget_v_i16m8_i16m1(lsum1, 1), 16);
3410            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_0_0, __riscv_vget_v_i16m8_i16m1(lsum2, 0), 16);
3411            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_0_1, __riscv_vget_v_i16m8_i16m1(lsum2, 1), 16);
3412            //
3413            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_1_0, __riscv_vget_v_i16m8_i16m1(lsum1, 2), 16);
3414            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_1_1, __riscv_vget_v_i16m8_i16m1(lsum1, 3), 16);
3415            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_1_0, __riscv_vget_v_i16m8_i16m1(lsum2, 2), 16);
3416            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_1_1, __riscv_vget_v_i16m8_i16m1(lsum2, 3), 16);
3417            //
3418            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_2_0, __riscv_vget_v_i16m8_i16m1(lsum1, 4), 16);
3419            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_2_1, __riscv_vget_v_i16m8_i16m1(lsum1, 5), 16);
3420            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_2_0, __riscv_vget_v_i16m8_i16m1(lsum2, 4), 16);
3421            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_2_1, __riscv_vget_v_i16m8_i16m1(lsum2, 5), 16);
3422            //
3423            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_3_0, __riscv_vget_v_i16m8_i16m1(lsum1, 6), 16);
3424            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_3_1, __riscv_vget_v_i16m8_i16m1(lsum1, 7), 16);
3425            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_3_0, __riscv_vget_v_i16m8_i16m1(lsum2, 6), 16);
3426            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_3_1, __riscv_vget_v_i16m8_i16m1(lsum2, 7), 16);
3427
3428            __asm__ __volatile__("" ::: "memory");
3429        }
3430
3431        // Reduce and accumulate in `sumf`.
3432        vint32m1_t one = __riscv_vmv_v_x_i32m1(0, 1);
3433        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(acc1, one, 16));
3434        int sumi2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(acc2, one, 16));
3435        sumf += y[i].d * GGML_CPU_FP16_TO_FP32(scale.f16) * (sumi1 + IQ1M_DELTA * sumi2);
3436    }
3437
3438    *s = sumf;
3439}
3440
3441static NOINLINE void ggml_vec_dot_iq1_m_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3442    assert(n % QK_K == 0);
3443    assert(nrc == 1);
3444    UNUSED(nrc);
3445    UNUSED(bx);
3446    UNUSED(by);
3447    UNUSED(bs);
3448
3449    const block_iq1_m * GGML_RESTRICT x = vx;
3450    const block_q8_K  * GGML_RESTRICT y = vy;
3451
3452    const int nb = n / QK_K;
3453
3454    iq1m_scale_t scale;
3455
3456    // Mask for processing 16 elements per lsum register.
3457    const vuint16m1_t l_index = __riscv_vid_v_u16m1(32);
3458    const vbool16_t l_mask = __riscv_vmsgtu_vx_u16m1_b16(l_index, 15, 32);
3459
3460    float sumf = 0.0f;
3461    for (int i = 0; i < nb; ++i) {
3462        const int8_t   * q8 = y[i].qs;
3463        const uint8_t  * qs = x[i].qs;
3464        const uint8_t  * qh = x[i].qh;
3465        const uint16_t * sc = (const uint16_t *)x[i].scales;
3466
3467        scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000);
3468
3469        // Accumulators.
3470        vint32m2_t acc1 = __riscv_vmv_v_x_i32m2(0, 32);
3471        vint32m2_t acc2 = __riscv_vmv_v_x_i32m2(0, 32);
3472
3473        // We process all the sub-blocks together.
3474        #pragma GCC unroll 1
3475        for (int ib = 0; ib < QK_K/256; ib++) {
3476            // Load qh for all 16 sub-blocks.
3477            const vuint8mf4_t qh_8 = __riscv_vle8_v_u8mf4(qh, 16);
3478            const vuint16mf2_t qh_16_lo = __riscv_vzext_vf2_u16mf2(qh_8, 16);
3479            const vuint16mf2_t qh_16_hi = __riscv_vsll_vx_u16mf2(qh_16_lo, 8, 16);
3480            const vuint16m1_t qhb = __riscv_vzext_vf2_u16m1(
3481                __riscv_vreinterpret_v_u16mf2_u8mf2(__riscv_vor_vv_u16mf2(qh_16_lo, qh_16_hi, 16)), 32);
3482            __asm__ __volatile__("" ::: "memory");
3483
3484            // Prepare grid indices.
3485            const vuint16m1_t qsb = __riscv_vzext_vf2_u16m1(__riscv_vle8_v_u8mf2(&qs[0], 32), 32);
3486            const vuint16m1_t shift = __riscv_vreinterpret_v_u32m1_u16m1(__riscv_vmv_v_x_u32m1(0x00040008, 16));
3487            vuint16m1_t index = __riscv_vor_vv_u16m1(qsb, __riscv_vand_vx_u16m1(__riscv_vsll_vv_u16m1(qhb, shift, 32), 0x700, 32), 32);
3488            index = __riscv_vsll_vx_u16m1(index, 3, 32);
3489            __asm__ __volatile__("" ::: "memory");
3490
3491            // Load the grid.
3492            const vint8m4_t iq1b = __riscv_vreinterpret_v_i64m4_i8m4(__riscv_vreinterpret_v_u64m4_i64m4(
3493                __riscv_vluxei16_v_u64m4(iq1s_grid, index, 32)));
3494
3495            // Prepare the deltas.
3496            const vbool16_t mask = __riscv_vmsgtu_vx_u16m1_b16(
3497                __riscv_vand_vv_u16m1(qhb, __riscv_vreinterpret_v_u32m1_u16m1(__riscv_vmv_v_x_u32m1(0x00800008, 16)), 32), 0, 32);
3498            const vint64m4_t delta_pos = __riscv_vmv_v_x_i64m4(0x0101010101010101, 32);
3499            const vint8m4_t delta = __riscv_vreinterpret_v_i64m4_i8m4(
3500                __riscv_vmerge_vxm_i64m4(delta_pos, 0xffffffffffffffff, mask, 32));
3501
3502            // Load q8 for sub-blocks.
3503            const vint8m4_t q8b = __riscv_vle8_v_i8m4(q8, 256);
3504
3505            // Calculate the lsums.
3506            const vint16m8_t lsum1 = __riscv_vwmul_vv_i16m8(iq1b, q8b, 256);
3507            const vint16m8_t lsum2 = __riscv_vwmul_vv_i16m8(delta, q8b, 256);
3508
3509            // Prepare the scales.
3510            const int16_t ls_0 = 2*((sc[0] >> 0) & 0x7) + 1;
3511            const int16_t ls_1 = 2*((sc[0] >> 3) & 0x7) + 1;
3512            const int16_t ls_2 = 2*((sc[0] >> 6) & 0x7) + 1;
3513            const int16_t ls_3 = 2*((sc[0] >> 9) & 0x7) + 1;
3514            const int16_t ls_4 = 2*((sc[1] >> 0) & 0x7) + 1;
3515            const int16_t ls_5 = 2*((sc[1] >> 3) & 0x7) + 1;
3516            const int16_t ls_6 = 2*((sc[1] >> 6) & 0x7) + 1;
3517            const int16_t ls_7 = 2*((sc[1] >> 9) & 0x7) + 1;
3518            const int16_t ls_8 = 2*((sc[2] >> 0) & 0x7) + 1;
3519            const int16_t ls_9 = 2*((sc[2] >> 3) & 0x7) + 1;
3520            const int16_t ls_10 = 2*((sc[2] >> 6) & 0x7) + 1;
3521            const int16_t ls_11 = 2*((sc[2] >> 9) & 0x7) + 1;
3522            const int16_t ls_12 = 2*((sc[3] >> 0) & 0x7) + 1;
3523            const int16_t ls_13 = 2*((sc[3] >> 3) & 0x7) + 1;
3524            const int16_t ls_14 = 2*((sc[3] >> 6) & 0x7) + 1;
3525            const int16_t ls_15 = 2*((sc[3] >> 9) & 0x7) + 1;
3526
3527            // Accumulate in acc0 and acc1 for each sub-block.
3528            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_0, __riscv_vget_v_i16m8_i16m1(lsum1, 0), 16);
3529            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_1, __riscv_vget_v_i16m8_i16m1(lsum1, 0), 32);
3530            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_0, __riscv_vget_v_i16m8_i16m1(lsum2, 0), 16);
3531            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_1, __riscv_vget_v_i16m8_i16m1(lsum2, 0), 32);
3532            //
3533            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_2, __riscv_vget_v_i16m8_i16m1(lsum1, 1), 16);
3534            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_3, __riscv_vget_v_i16m8_i16m1(lsum1, 1), 32);
3535            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_2, __riscv_vget_v_i16m8_i16m1(lsum2, 1), 16);
3536            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_3, __riscv_vget_v_i16m8_i16m1(lsum2, 1), 32);
3537            //
3538            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_4, __riscv_vget_v_i16m8_i16m1(lsum1, 2), 16);
3539            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_5, __riscv_vget_v_i16m8_i16m1(lsum1, 2), 32);
3540            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_4, __riscv_vget_v_i16m8_i16m1(lsum2, 2), 16);
3541            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_5, __riscv_vget_v_i16m8_i16m1(lsum2, 2), 32);
3542            //
3543            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_6, __riscv_vget_v_i16m8_i16m1(lsum1, 3), 16);
3544            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_7, __riscv_vget_v_i16m8_i16m1(lsum1, 3), 32);
3545            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_6, __riscv_vget_v_i16m8_i16m1(lsum2, 3), 16);
3546            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_7, __riscv_vget_v_i16m8_i16m1(lsum2, 3), 32);
3547            //
3548            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_8, __riscv_vget_v_i16m8_i16m1(lsum1, 4), 16);
3549            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_9, __riscv_vget_v_i16m8_i16m1(lsum1, 4), 32);
3550            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_8, __riscv_vget_v_i16m8_i16m1(lsum2, 4), 16);
3551            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_9, __riscv_vget_v_i16m8_i16m1(lsum2, 4), 32);
3552            //
3553            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_10, __riscv_vget_v_i16m8_i16m1(lsum1, 5), 16);
3554            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_11, __riscv_vget_v_i16m8_i16m1(lsum1, 5), 32);
3555            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_10, __riscv_vget_v_i16m8_i16m1(lsum2, 5), 16);
3556            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_11, __riscv_vget_v_i16m8_i16m1(lsum2, 5), 32);
3557            //
3558            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_12, __riscv_vget_v_i16m8_i16m1(lsum1, 6), 16);
3559            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_13, __riscv_vget_v_i16m8_i16m1(lsum1, 6), 32);
3560            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_12, __riscv_vget_v_i16m8_i16m1(lsum2, 6), 16);
3561            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_13, __riscv_vget_v_i16m8_i16m1(lsum2, 6), 32);
3562            //
3563            acc1 = __riscv_vwmacc_vx_i32m2(          acc1, ls_14, __riscv_vget_v_i16m8_i16m1(lsum1, 7), 16);
3564            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc1, ls_15, __riscv_vget_v_i16m8_i16m1(lsum1, 7), 32);
3565            acc2 = __riscv_vwmacc_vx_i32m2(          acc2, ls_14, __riscv_vget_v_i16m8_i16m1(lsum2, 7), 16);
3566            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask, acc2, ls_15, __riscv_vget_v_i16m8_i16m1(lsum2, 7), 32);
3567
3568            __asm__ __volatile__("" ::: "memory");
3569        }
3570
3571        // Reduce and accumulate in `sumf`.
3572        vint32m1_t one = __riscv_vmv_v_x_i32m1(0, 1);
3573        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(acc1, one, 32));
3574        int sumi2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(acc2, one, 32));
3575        sumf += y[i].d * GGML_CPU_FP16_TO_FP32(scale.f16) * (sumi1 + IQ1M_DELTA * sumi2);
3576    }
3577
3578    *s = sumf;
3579}
3580
3581static NOINLINE void ggml_vec_dot_iq1_m_q8_K_vl1024(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3582    assert(n % QK_K == 0);
3583    assert(nrc == 1);
3584    UNUSED(nrc);
3585    UNUSED(bx);
3586    UNUSED(by);
3587    UNUSED(bs);
3588
3589    const block_iq1_m * GGML_RESTRICT x = vx;
3590    const block_q8_K  * GGML_RESTRICT y = vy;
3591
3592    const int nb = n / QK_K;
3593
3594    iq1m_scale_t scale;
3595    float sumf = 0.0f;
3596    for (int i = 0; i < nb; ++i) {
3597        const int8_t   * q8 = y[i].qs;
3598        const uint8_t  * qs = x[i].qs;
3599        const uint8_t  * qh = x[i].qh;
3600        const uint16_t * sc = (const uint16_t *)x[i].scales;
3601
3602        scale.u16 = (sc[0] >> 12) | ((sc[1] >> 8) & 0x00f0) | ((sc[2] >> 4) & 0x0f00) | (sc[3] & 0xf000);
3603
3604        // Accumulators.
3605        vint32m2_t acc1 = __riscv_vmv_v_x_i32m2(0, 64);
3606        vint32m2_t acc2 = __riscv_vmv_v_x_i32m2(0, 64);
3607
3608        // We process all the sub-blocks together.
3609        #pragma GCC unroll 1
3610        for (int ib = 0; ib < QK_K/256; ib++) {
3611            // Load qh for all 16 sub-blocks.
3612            const vuint8mf8_t qh_8 = __riscv_vle8_v_u8mf8(qh, 16);
3613            const vuint16mf4_t qh_16_lo = __riscv_vzext_vf2_u16mf4(qh_8, 16);
3614            const vuint16mf4_t qh_16_hi = __riscv_vsll_vx_u16mf4(qh_16_lo, 8, 16);
3615            const vuint16mf2_t qhb = __riscv_vzext_vf2_u16mf2(
3616                __riscv_vreinterpret_v_u16mf4_u8mf4(__riscv_vor_vv_u16mf4(qh_16_lo, qh_16_hi, 16)), 32);
3617            __asm__ __volatile__("" ::: "memory");
3618
3619            // Prepare grid indices.
3620            const vuint16mf2_t qsb = __riscv_vzext_vf2_u16mf2(__riscv_vle8_v_u8mf4(&qs[0], 32), 32);
3621            const vuint16mf2_t shift = __riscv_vreinterpret_v_u32mf2_u16mf2(__riscv_vmv_v_x_u32mf2(0x00040008, 16));
3622            vuint16mf2_t index = __riscv_vor_vv_u16mf2(qsb, __riscv_vand_vx_u16mf2(__riscv_vsll_vv_u16mf2(qhb, shift, 32), 0x700, 32), 32);
3623            index = __riscv_vsll_vx_u16mf2(index, 3, 32);
3624            __asm__ __volatile__("" ::: "memory");
3625
3626            // Load the grid.
3627            const vint8m2_t iq1b = __riscv_vreinterpret_v_i64m2_i8m2(__riscv_vreinterpret_v_u64m2_i64m2(
3628                __riscv_vluxei16_v_u64m2(iq1s_grid, index, 32)));
3629
3630            // Prepare the deltas.
3631            const vbool32_t mask = __riscv_vmsgtu_vx_u16mf2_b32(
3632                __riscv_vand_vv_u16mf2(qhb, __riscv_vreinterpret_v_u32mf2_u16mf2(__riscv_vmv_v_x_u32mf2(0x00800008, 16)), 32), 0, 32);
3633            const vint64m2_t delta_pos = __riscv_vmv_v_x_i64m2(0x0101010101010101, 32);
3634            const vint8m2_t delta = __riscv_vreinterpret_v_i64m2_i8m2(
3635                __riscv_vmerge_vxm_i64m2(delta_pos, 0xffffffffffffffff, mask, 32));
3636
3637            // Load q8 for sub-blocks.
3638            const vint8m2_t q8b = __riscv_vle8_v_i8m2(q8, 256);
3639
3640            // Calculate the lsums.
3641            const vint16m4_t lsum1 = __riscv_vwmul_vv_i16m4(iq1b, q8b, 256);
3642            const vint16m4_t lsum2 = __riscv_vwmul_vv_i16m4(delta, q8b, 256);
3643
3644            // Prepare the scales.
3645            const int16_t ls_0 = 2*((sc[0] >> 0) & 0x7) + 1;
3646            const int16_t ls_1 = 2*((sc[0] >> 3) & 0x7) + 1;
3647            const int16_t ls_2 = 2*((sc[0] >> 6) & 0x7) + 1;
3648            const int16_t ls_3 = 2*((sc[0] >> 9) & 0x7) + 1;
3649            const int16_t ls_4 = 2*((sc[1] >> 0) & 0x7) + 1;
3650            const int16_t ls_5 = 2*((sc[1] >> 3) & 0x7) + 1;
3651            const int16_t ls_6 = 2*((sc[1] >> 6) & 0x7) + 1;
3652            const int16_t ls_7 = 2*((sc[1] >> 9) & 0x7) + 1;
3653            const int16_t ls_8 = 2*((sc[2] >> 0) & 0x7) + 1;
3654            const int16_t ls_9 = 2*((sc[2] >> 3) & 0x7) + 1;
3655            const int16_t ls_10 = 2*((sc[2] >> 6) & 0x7) + 1;
3656            const int16_t ls_11 = 2*((sc[2] >> 9) & 0x7) + 1;
3657            const int16_t ls_12 = 2*((sc[3] >> 0) & 0x7) + 1;
3658            const int16_t ls_13 = 2*((sc[3] >> 3) & 0x7) + 1;
3659            const int16_t ls_14 = 2*((sc[3] >> 6) & 0x7) + 1;
3660            const int16_t ls_15 = 2*((sc[3] >> 9) & 0x7) + 1;
3661
3662            // Mask for processing 16 elements per lsum register.
3663            const vuint16m1_t l_index = __riscv_vid_v_u16m1(64);
3664
3665            // Accumulate in acc1 and acc2 for each sub-block.
3666            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_0,  __riscv_vget_v_i16m4_i16m1(lsum1, 0), 16);
3667            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_0,  __riscv_vget_v_i16m4_i16m1(lsum2, 0), 16);
3668            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_4,  __riscv_vget_v_i16m4_i16m1(lsum1, 1), 16);
3669            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_4,  __riscv_vget_v_i16m4_i16m1(lsum2, 1), 16);
3670            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_8,  __riscv_vget_v_i16m4_i16m1(lsum1, 2), 16);
3671            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_8,  __riscv_vget_v_i16m4_i16m1(lsum2, 2), 16);
3672            acc1 = __riscv_vwmacc_vx_i32m2(acc1, ls_12, __riscv_vget_v_i16m4_i16m1(lsum1, 3), 16);
3673            acc2 = __riscv_vwmacc_vx_i32m2(acc2, ls_12, __riscv_vget_v_i16m4_i16m1(lsum2, 3), 16);
3674            //
3675            const vbool16_t l_mask_16_32 = __riscv_vmsgtu_vx_u16m1_b16(l_index, 15, 64);
3676            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc1, ls_1, __riscv_vget_v_i16m4_i16m1(lsum1, 0), 32);
3677            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc2, ls_1, __riscv_vget_v_i16m4_i16m1(lsum2, 0), 32);
3678            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc1, ls_5, __riscv_vget_v_i16m4_i16m1(lsum1, 1), 32);
3679            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc2, ls_5, __riscv_vget_v_i16m4_i16m1(lsum2, 1), 32);
3680            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc1, ls_9, __riscv_vget_v_i16m4_i16m1(lsum1, 2), 32);
3681            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc2, ls_9, __riscv_vget_v_i16m4_i16m1(lsum2, 2), 32);
3682            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc1, ls_13, __riscv_vget_v_i16m4_i16m1(lsum1, 3), 32);
3683            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_16_32, acc2, ls_13, __riscv_vget_v_i16m4_i16m1(lsum2, 3), 32);
3684            //
3685            const vbool16_t l_mask_32_48 = __riscv_vmsgtu_vx_u16m1_b16(l_index, 31, 64);
3686            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc1, ls_2,  __riscv_vget_v_i16m4_i16m1(lsum1, 0), 48);
3687            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc2, ls_2,  __riscv_vget_v_i16m4_i16m1(lsum2, 0), 48);
3688            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc1, ls_6,  __riscv_vget_v_i16m4_i16m1(lsum1, 1), 48);
3689            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc2, ls_6,  __riscv_vget_v_i16m4_i16m1(lsum2, 1), 48);
3690            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc1, ls_10, __riscv_vget_v_i16m4_i16m1(lsum1, 2), 48);
3691            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc2, ls_10, __riscv_vget_v_i16m4_i16m1(lsum2, 2), 48);
3692            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc1, ls_14, __riscv_vget_v_i16m4_i16m1(lsum1, 3), 48);
3693            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_32_48, acc2, ls_14, __riscv_vget_v_i16m4_i16m1(lsum2, 3), 48);
3694            //
3695            const vbool16_t l_mask_48_64 = __riscv_vmsgtu_vx_u16m1_b16(l_index, 47, 64);
3696            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc1, ls_3,  __riscv_vget_v_i16m4_i16m1(lsum1, 0), 64);
3697            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc2, ls_3,  __riscv_vget_v_i16m4_i16m1(lsum2, 0), 64);
3698            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc1, ls_7,  __riscv_vget_v_i16m4_i16m1(lsum1, 1), 64);
3699            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc2, ls_7,  __riscv_vget_v_i16m4_i16m1(lsum2, 1), 64);
3700            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc1, ls_11, __riscv_vget_v_i16m4_i16m1(lsum1, 2), 64);
3701            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc2, ls_11, __riscv_vget_v_i16m4_i16m1(lsum2, 2), 64);
3702            acc1 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc1, ls_15, __riscv_vget_v_i16m4_i16m1(lsum1, 3), 64);
3703            acc2 = __riscv_vwmacc_vx_i32m2_m(l_mask_48_64, acc2, ls_15, __riscv_vget_v_i16m4_i16m1(lsum2, 3), 64);
3704
3705            __asm__ __volatile__("" ::: "memory");
3706        }
3707
3708        // Reduce and accumulate in `sumf`.
3709        vint32m1_t one = __riscv_vmv_v_x_i32m1(0, 1);
3710        int sumi1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(acc1, one, 64));
3711        int sumi2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m2_i32m1(acc2, one, 64));
3712        sumf += y[i].d * GGML_CPU_FP16_TO_FP32(scale.f16) * (sumi1 + IQ1M_DELTA * sumi2);
3713    }
3714
3715    *s = sumf;
3716}
3717#endif
3718
3719void ggml_vec_dot_iq1_m_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3720#if defined __riscv_v
3721    switch (__riscv_vlenb() * 8) {
3722        case 128:
3723            ggml_vec_dot_iq1_m_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
3724            break;
3725        case 256:
3726            ggml_vec_dot_iq1_m_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
3727            break;
3728        case 512:
3729            ggml_vec_dot_iq1_m_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
3730            break;
3731        case 1024:
3732            ggml_vec_dot_iq1_m_q8_K_vl1024(n, s, bs, vx, bx, vy, by, nrc);
3733            break;
3734        default:
3735            ggml_vec_dot_iq1_m_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
3736            break;
3737    }
3738#else
3739    ggml_vec_dot_iq1_m_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
3740#endif
3741}
3742
3743#if defined __riscv_v
3744static const uint8_t sign_gather_indices_arr[64] = {
3745    0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,
3746    4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7
3747};
3748
3749static const uint8_t sign_bit_masks_arr[64] = {
3750    1,2,4,8,16,32,64,128, 1,2,4,8,16,32,64,128, 1,2,4,8,16,32,64,128, 1,2,4,8,16,32,64,128,
3751    1,2,4,8,16,32,64,128, 1,2,4,8,16,32,64,128, 1,2,4,8,16,32,64,128, 1,2,4,8,16,32,64,128
3752};
3753
3754static NOINLINE void ggml_vec_dot_iq2_s_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3755    assert(n % QK_K == 0);
3756    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
3757
3758    const block_iq2_s * GGML_RESTRICT x = vx;
3759    const block_q8_K  * GGML_RESTRICT y = vy;
3760
3761    const int nb = n / QK_K;
3762    const uint64_t * grid64 = (const uint64_t *)iq2s_grid;
3763
3764    // Pre-load Constants
3765    vuint8m2_t v_ids = __riscv_vid_v_u8m2(32);
3766    vuint8m2_t v_sign_gather_indices = __riscv_vsrl_vx_u8m2(v_ids, 3, 32);
3767    vuint8m2_t v_ones = __riscv_vmv_v_x_u8m2(1, 32);
3768    vuint8m2_t v_shift_amts = __riscv_vand_vx_u8m2(v_ids, 7, 32);
3769    vuint8m2_t v_sign_masks = __riscv_vsll_vv_u8m2(v_ones, v_shift_amts, 32);
3770    uint16_t shift_qh_arr[4] = {11, 9, 7, 5};
3771    vuint16mf2_t v_shift_qh = __riscv_vle16_v_u16mf2(shift_qh_arr, 4);
3772
3773    float sumf = 0.0f;
3774
3775    for (int i = 0; i < nb; ++i) {
3776        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
3777
3778        const uint8_t * GGML_RESTRICT qs = x[i].qs;
3779        const uint8_t * GGML_RESTRICT qh = x[i].qh;
3780        const uint8_t * GGML_RESTRICT scales = x[i].scales;
3781        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
3782
3783        const uint8_t * signs_ptr = qs + 32;
3784        float sum_block = 0.0f;
3785
3786        for (int ib = 0; ib < 8; ++ib) {
3787
3788            // Load Low Bits [4 bytes]
3789            vuint8mf4_t v_qs_u8 = __riscv_vle8_v_u8mf4(qs, 4);
3790            qs += 4;
3791
3792            // Load 1 byte. It contains bits for 4 mini-blocks.
3793            uint8_t qh_val = *qh++;
3794
3795            // Combine Low + High bits of 10bit indices
3796            vuint8mf4_t v_qh_raw = __riscv_vmv_v_x_u8mf4(qh_val, 4);
3797            vuint16mf2_t v_qh_u16 = __riscv_vwcvtu_x_x_v_u16mf2(v_qh_raw, 4);
3798            vuint16mf2_t v_qh_mf2 = __riscv_vsll_vv_u16mf2(v_qh_u16, v_shift_qh, 4);
3799            v_qh_mf2 = __riscv_vand_vx_u16mf2(v_qh_mf2, 0x1800, 4);
3800            vuint16mf2_t v_qs_u16_mf2 = __riscv_vwcvtu_x_x_v_u16mf2(v_qs_u8, 4);
3801            vuint16mf2_t v_qs_u16 = __riscv_vsll_vx_u16mf2(v_qs_u16_mf2, 3, 4);
3802            vuint16mf2_t v_grid_offsets = __riscv_vor_vv_u16mf2(v_qs_u16, v_qh_mf2, 4);
3803
3804            // Lookup Grid
3805            vint8m2_t v_grid_i8 = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vreinterpret_v_u64m2_u8m2(__riscv_vluxei16_v_u64m2(grid64, v_grid_offsets, 4)));
3806
3807            vuint8mf4_t v_signs_raw = __riscv_vle8_v_u8mf4(signs_ptr, 4);
3808            signs_ptr += 4;
3809            vuint8m2_t v_signs_source = __riscv_vlmul_ext_v_u8mf4_u8m2(v_signs_raw);
3810            vuint8m2_t v_signs_bcast = __riscv_vrgather_vv_u8m2(v_signs_source, v_sign_gather_indices, 32);
3811
3812            // generating sign mask
3813            vuint8m2_t v_sign_bits = __riscv_vand_vv_u8m2(v_signs_bcast, v_sign_masks, 32);
3814            vbool4_t m_negative = __riscv_vmsne_vx_u8m2_b4(v_sign_bits, 0, 32);
3815
3816            vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 32);
3817            q8 += 32;
3818
3819            // apply signs
3820            vint8m2_t v_q8_signed = __riscv_vrsub_vx_i8m2_mu(m_negative,v_q8, v_q8, 0, 32);
3821            vint16m4_t v_dot = __riscv_vwmul_vv_i16m4(v_grid_i8, v_q8_signed, 32);
3822
3823            // Reduction
3824            vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
3825
3826            // Reduce 0-15 (First Half)
3827            int32_t s0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(
3828                __riscv_vget_v_i16m4_i16m2(v_dot, 0), v_zero, 16));
3829
3830            // Reduce 16-31 (Second Half)
3831            int32_t s1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(
3832                __riscv_vget_v_i16m4_i16m2(v_dot, 1), v_zero, 16));
3833
3834            // Apply sub Scales
3835            uint8_t sc = *scales++;
3836
3837            sum_block += s0 * (2 * (sc & 0xF) + 1);
3838            sum_block += s1 * (2 * (sc >> 4)  + 1);
3839        }
3840        sumf += sum_block * combined_scale;
3841    }
3842    *s = 0.125f * sumf;
3843}
3844
3845static NOINLINE void ggml_vec_dot_iq2_s_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3846    assert(n % QK_K == 0);
3847    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
3848
3849    const block_iq2_s * GGML_RESTRICT x = vx;
3850    const block_q8_K  * GGML_RESTRICT y = vy;
3851
3852    const int nb = n / QK_K;
3853    const uint64_t * grid64 = (const uint64_t *)iq2s_grid;
3854
3855    // --- Pre-load Constants ---
3856    uint16_t gather_qh_arr[8] = {0, 0, 0, 0, 1, 1, 1, 1};
3857    vuint16mf2_t v_gather_qh = __riscv_vle16_v_u16mf2(gather_qh_arr, 8);
3858    uint16_t shift_qh_arr[8] = {11, 9, 7, 5, 11, 9, 7, 5};
3859    vuint16mf2_t v_shift_qh = __riscv_vle16_v_u16mf2(shift_qh_arr, 8);
3860
3861    // Constants for sign extraction
3862    vuint8m2_t v_sign_gather_indices = __riscv_vle8_v_u8m2(sign_gather_indices_arr, 64);
3863    vuint8m2_t v_sign_masks = __riscv_vle8_v_u8m2(sign_bit_masks_arr, 64);
3864
3865    float sumf = 0.0f;
3866
3867    for (int i = 0; i < nb; ++i) {
3868        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
3869
3870        const uint8_t * GGML_RESTRICT qs = x[i].qs;
3871        const uint8_t * GGML_RESTRICT qh = x[i].qh;
3872        const uint8_t * GGML_RESTRICT scales = x[i].scales;
3873        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
3874
3875        const uint8_t * signs_ptr = qs + 32;
3876
3877        float sum_block = 0.0f;
3878
3879        for (int ib = 0; ib < 4; ++ib) {
3880            // Combine low + high bits
3881            vuint8mf4_t v_qs_u8 = __riscv_vle8_v_u8mf4(qs, 8);
3882            qs += 8;
3883            uint16_t qh_val;
3884            memcpy(&qh_val, qh, 2);
3885            qh += 2;
3886            vuint8mf8_t v_qh_raw = __riscv_vle8_v_u8mf8((const uint8_t*)&qh_val, 2);
3887            vuint16mf4_t v_qh_u16 = __riscv_vwcvtu_x_x_v_u16mf4(v_qh_raw, 2);
3888            vuint16mf2_t v_qh_u16_ext = __riscv_vlmul_ext_v_u16mf4_u16mf2(v_qh_u16);
3889            vuint16mf2_t v_qh_expanded = __riscv_vrgather_vv_u16mf2(v_qh_u16_ext, v_gather_qh, 8);
3890            v_qh_expanded = __riscv_vsll_vv_u16mf2(v_qh_expanded, v_shift_qh, 8);
3891
3892            // Mask: We want bits 11-12. 0x1800 = 0001 1000 0000 0000
3893            v_qh_expanded = __riscv_vand_vx_u16mf2(v_qh_expanded, 0x1800, 8);
3894            vuint16mf2_t v_qs_u16 = __riscv_vwcvtu_x_x_v_u16mf2(v_qs_u8, 8);
3895
3896            // Multiply by 8 to get byte offset, instead of element offset
3897            v_qs_u16 = __riscv_vsll_vx_u16mf2(v_qs_u16, 3, 8);
3898            vuint16mf2_t v_grid_offsets = __riscv_vor_vv_u16mf2(v_qs_u16, v_qh_expanded, 8);
3899
3900            // Lookup Grid using Byte Offsets
3901            vuint64m2_t v_grid_vals = __riscv_vluxei16_v_u64m2(grid64, v_grid_offsets, 8);
3902
3903            vuint8m2_t v_grid_u8 = __riscv_vreinterpret_v_u64m2_u8m2(v_grid_vals);
3904            vint8m2_t v_grid_i8 = __riscv_vreinterpret_v_u8m2_i8m2(v_grid_u8);
3905
3906            // Load signs and generate sign mask
3907            vuint8mf4_t v_signs_raw = __riscv_vle8_v_u8mf4(signs_ptr, 8);
3908            signs_ptr += 8;
3909
3910            vuint8m2_t v_signs_source = __riscv_vlmul_ext_v_u8mf4_u8m2(v_signs_raw);
3911            vuint8m2_t v_signs_bcast = __riscv_vrgather_vv_u8m2(v_signs_source, v_sign_gather_indices, 64);
3912
3913            vuint8m2_t v_sign_bits = __riscv_vand_vv_u8m2(v_signs_bcast, v_sign_masks, 64);
3914            vbool4_t m_negative = __riscv_vmsne_vx_u8m2_b4(v_sign_bits, 0, 64);
3915
3916            vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 64);
3917            q8 += 64;
3918
3919            vint8m2_t v_q8_signed = __riscv_vrsub_vx_i8m2_mu(m_negative, v_q8, v_q8, 0, 64);
3920            vint16m4_t v_dot = __riscv_vwmul_vv_i16m4(v_grid_i8, v_q8_signed, 64);
3921
3922            vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
3923
3924            int32_t s0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
3925                __riscv_vget_v_i16m4_i16m1(v_dot, 0), v_zero, 16));
3926            int32_t s1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
3927                __riscv_vget_v_i16m4_i16m1(v_dot, 1), v_zero, 16));
3928            int32_t s2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
3929                __riscv_vget_v_i16m4_i16m1(v_dot, 2), v_zero, 16));
3930            int32_t s3 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
3931                __riscv_vget_v_i16m4_i16m1(v_dot, 3), v_zero, 16));
3932
3933            uint8_t sc0 = scales[0];
3934            uint8_t sc1 = scales[1];
3935            scales += 2;
3936
3937            sum_block += s0 * (2 * (sc0 & 0xF) + 1);
3938            sum_block += s1 * (2 * (sc0 >> 4)  + 1);
3939            sum_block += s2 * (2 * (sc1 & 0xF) + 1);
3940            sum_block += s3 * (2 * (sc1 >> 4)  + 1);
3941        }
3942        sumf += sum_block * combined_scale;
3943    }
3944    *s = 0.125f * sumf;
3945}
3946
3947static NOINLINE void ggml_vec_dot_iq2_s_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
3948    assert(n % QK_K == 0);
3949    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
3950
3951    const block_iq2_s * GGML_RESTRICT x = vx;
3952    const block_q8_K  * GGML_RESTRICT y = vy;
3953
3954    const int nb = n / QK_K;
3955    const uint64_t * grid64 = (const uint64_t *)iq2s_grid;
3956
3957    vuint8m2_t v_ids = __riscv_vid_v_u8m2(128);
3958    vuint8m2_t v_sign_gather_indices = __riscv_vsrl_vx_u8m2(v_ids, 3, 128);
3959
3960    vuint8m2_t v_ones = __riscv_vmv_v_x_u8m2(1, 128);
3961    vuint8m2_t v_shift_amts = __riscv_vand_vx_u8m2(v_ids, 7, 128);
3962    vuint8m2_t v_sign_masks = __riscv_vsll_vv_u8m2(v_ones, v_shift_amts, 128);
3963
3964    uint16_t gather_qh_arr[16] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3};
3965    vuint16mf2_t v_gather_qh = __riscv_vle16_v_u16mf2(gather_qh_arr, 16);
3966
3967    uint16_t shift_qh_arr[16] = {11, 9, 7, 5, 11, 9, 7, 5, 11, 9, 7, 5, 11, 9, 7, 5};
3968    vuint16mf2_t v_shift_qh = __riscv_vle16_v_u16mf2(shift_qh_arr, 16);
3969
3970    // Masks for selecting lower/upper 16 lanes within a 32-lane i16m1 register
3971    vuint16m1_t v_ids16 = __riscv_vid_v_u16m1(32);
3972    vbool16_t m_hi16 = __riscv_vmsgeu_vx_u16m1_b16(v_ids16, 16, 32);
3973    float sumf = 0.0f;
3974
3975    for (int i = 0; i < nb; ++i) {
3976        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
3977
3978        const uint8_t * GGML_RESTRICT qs = x[i].qs;
3979        const uint8_t * GGML_RESTRICT qh = x[i].qh;
3980        const uint8_t * GGML_RESTRICT scales = x[i].scales;
3981        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
3982
3983        const uint8_t * signs_ptr = qs + 32;
3984
3985        float sum_block = 0.0f;
3986
3987        for (int ib = 0; ib < 2; ++ib) {
3988            vuint8mf4_t v_qs_u8 = __riscv_vle8_v_u8mf4(qs, 16);
3989            qs += 16;
3990
3991            vuint8mf8_t v_qh_raw = __riscv_vle8_v_u8mf8(qh, 4);
3992            qh += 4;
3993
3994            vuint16mf4_t v_qh_u16 = __riscv_vwcvtu_x_x_v_u16mf4(v_qh_raw, 4);
3995            vuint16mf2_t v_qh_u16_ext = __riscv_vlmul_ext_v_u16mf4_u16mf2(v_qh_u16);
3996            vuint16mf2_t v_qh_expanded = __riscv_vrgather_vv_u16mf2(v_qh_u16_ext, v_gather_qh, 16);
3997            v_qh_expanded = __riscv_vsll_vv_u16mf2(v_qh_expanded, v_shift_qh, 16);
3998            v_qh_expanded = __riscv_vand_vx_u16mf2(v_qh_expanded, 0x1800, 16);
3999
4000            vuint16mf2_t v_qs_u16 = __riscv_vwcvtu_x_x_v_u16mf2(v_qs_u8, 16);
4001            v_qs_u16 = __riscv_vsll_vx_u16mf2(v_qs_u16, 3, 16);
4002
4003            vuint16mf2_t v_grid_offsets = __riscv_vor_vv_u16mf2(v_qs_u16, v_qh_expanded, 16);
4004            vuint64m2_t v_grid_vals = __riscv_vluxei16_v_u64m2(grid64, v_grid_offsets, 16);
4005            vuint8m2_t v_grid_u8 = __riscv_vreinterpret_v_u64m2_u8m2(v_grid_vals);
4006            vint8m2_t v_grid_i8 = __riscv_vreinterpret_v_u8m2_i8m2(v_grid_u8);
4007
4008            vuint8mf4_t v_signs_raw = __riscv_vle8_v_u8mf4(signs_ptr, 16);
4009            signs_ptr += 16;
4010
4011            vuint8m2_t v_signs_source = __riscv_vlmul_ext_v_u8mf4_u8m2(v_signs_raw);
4012            vuint8m2_t v_signs_bcast = __riscv_vrgather_vv_u8m2(v_signs_source, v_sign_gather_indices, 128);
4013            vuint8m2_t v_sign_bits = __riscv_vand_vv_u8m2(v_signs_bcast, v_sign_masks, 128);
4014            vbool4_t m_negative = __riscv_vmsne_vx_u8m2_b4(v_sign_bits, 0, 128);
4015            vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 128);
4016            q8 += 128;
4017
4018            vint8m2_t v_q8_signed = __riscv_vrsub_vx_i8m2_mu(m_negative, v_q8, v_q8, 0, 128);
4019            vint16m4_t v_dot = __riscv_vwmul_vv_i16m4(v_grid_i8, v_q8_signed, 128);
4020
4021            vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
4022            vint16m1_t v0 = __riscv_vget_v_i16m4_i16m1(v_dot, 0);
4023            vint16m1_t v1 = __riscv_vget_v_i16m4_i16m1(v_dot, 1);
4024            vint16m1_t v2 = __riscv_vget_v_i16m4_i16m1(v_dot, 2);
4025            vint16m1_t v3 = __riscv_vget_v_i16m4_i16m1(v_dot, 3);
4026
4027            int32_t s0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(v0, v_zero, 16));
4028            int32_t s1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(m_hi16, v0, v_zero, 32));
4029            int32_t s2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(v1, v_zero, 16));
4030            int32_t s3 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(m_hi16, v1, v_zero, 32));
4031            int32_t s4 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(v2, v_zero, 16));
4032            int32_t s5 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(m_hi16, v2, v_zero, 32));
4033            int32_t s6 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1( v3, v_zero, 16));
4034            int32_t s7 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(m_hi16, v3, v_zero, 32));
4035
4036            uint8_t sc0 = scales[0];
4037            uint8_t sc1 = scales[1];
4038            uint8_t sc2 = scales[2];
4039            uint8_t sc3 = scales[3];
4040            scales += 4;
4041
4042            sum_block += s0 * (2 * (sc0 & 0xF) + 1);
4043            sum_block += s1 * (2 * (sc0 >> 4)  + 1);
4044            sum_block += s2 * (2 * (sc1 & 0xF) + 1);
4045            sum_block += s3 * (2 * (sc1 >> 4)  + 1);
4046            sum_block += s4 * (2 * (sc2 & 0xF) + 1);
4047            sum_block += s5 * (2 * (sc2 >> 4)  + 1);
4048            sum_block += s6 * (2 * (sc3 & 0xF) + 1);
4049            sum_block += s7 * (2 * (sc3 >> 4)  + 1);
4050        }
4051
4052        sumf += sum_block * combined_scale;
4053    }
4054    *s = 0.125f * sumf;
4055}
4056
4057static NOINLINE void ggml_vec_dot_iq2_s_q8_K_vl1024(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4058    assert(n % QK_K == 0);
4059    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
4060
4061    const block_iq2_s * GGML_RESTRICT x = vx;
4062    const block_q8_K  * GGML_RESTRICT y = vy;
4063
4064    const int nb = n / QK_K;
4065    const uint64_t * grid64 = (const uint64_t *)iq2s_grid;
4066    vuint8m2_t v_ids = __riscv_vid_v_u8m2(256);
4067    vuint8m2_t v_sign_gather_indices = __riscv_vsrl_vx_u8m2(v_ids, 3, 256);
4068
4069    vuint8m2_t v_ones = __riscv_vmv_v_x_u8m2(1, 256);
4070    vuint8m2_t v_shift_amts = __riscv_vand_vx_u8m2(v_ids, 7, 256);
4071    vuint8m2_t v_sign_masks = __riscv_vsll_vv_u8m2(v_ones, v_shift_amts, 256);
4072
4073    uint16_t gather_qh_arr[32] = {
4074        0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
4075        4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7
4076    };
4077    vuint16mf2_t v_gather_qh = __riscv_vle16_v_u16mf2(gather_qh_arr, 32);
4078
4079    uint16_t shift_qh_arr[32] = {
4080        11, 9, 7, 5, 11, 9, 7, 5, 11, 9, 7, 5, 11, 9, 7, 5,
4081        11, 9, 7, 5, 11, 9, 7, 5, 11, 9, 7, 5, 11, 9, 7, 5
4082    };
4083    vuint16mf2_t v_shift_qh = __riscv_vle16_v_u16mf2(shift_qh_arr, 32);
4084
4085    // Masks for 4 groups of 16 lanes within a 64-lane i16m4 chunk
4086    vuint16m4_t v_ids64 = __riscv_vid_v_u16m4(64);
4087    vbool4_t m_g0 = __riscv_vmsltu_vx_u16m4_b4(v_ids64, 16, 64);
4088    vbool4_t m_g1 = __riscv_vmand_mm_b4(
4089        __riscv_vmsgeu_vx_u16m4_b4(v_ids64, 16, 64),
4090        __riscv_vmsltu_vx_u16m4_b4(v_ids64, 32, 64), 64);
4091    vbool4_t m_g2 = __riscv_vmand_mm_b4(
4092        __riscv_vmsgeu_vx_u16m4_b4(v_ids64, 32, 64),
4093        __riscv_vmsltu_vx_u16m4_b4(v_ids64, 48, 64), 64);
4094    vbool4_t m_g3 = __riscv_vmsgeu_vx_u16m4_b4(v_ids64, 48, 64);
4095
4096    float sumf = 0.0f;
4097
4098    for (int i = 0; i < nb; ++i) {
4099        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
4100
4101        const uint8_t * GGML_RESTRICT qs = x[i].qs;
4102        const uint8_t * GGML_RESTRICT qh = x[i].qh;
4103        const uint8_t * GGML_RESTRICT scales = x[i].scales;
4104        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
4105
4106        const uint8_t * signs_ptr = qs + 32;
4107
4108        float sum_block = 0.0f;
4109
4110        vuint8mf4_t v_qs_u8 = __riscv_vle8_v_u8mf4(qs, 32);
4111        qs += 32;
4112
4113        vuint8mf8_t v_qh_raw = __riscv_vle8_v_u8mf8(qh, 8);
4114        qh += 8;
4115
4116        vuint16mf4_t v_qh_u16 = __riscv_vwcvtu_x_x_v_u16mf4(v_qh_raw, 8);
4117        vuint16mf2_t v_qh_u16_ext = __riscv_vlmul_ext_v_u16mf4_u16mf2(v_qh_u16);
4118        vuint16mf2_t v_qh_expanded = __riscv_vrgather_vv_u16mf2(v_qh_u16_ext, v_gather_qh, 32);
4119        v_qh_expanded = __riscv_vsll_vv_u16mf2(v_qh_expanded, v_shift_qh, 32);
4120        v_qh_expanded = __riscv_vand_vx_u16mf2(v_qh_expanded, 0x1800, 32);
4121
4122        vuint16mf2_t v_qs_u16 = __riscv_vwcvtu_x_x_v_u16mf2(v_qs_u8, 32);
4123        v_qs_u16 = __riscv_vsll_vx_u16mf2(v_qs_u16, 3, 32);
4124
4125        vuint16mf2_t v_grid_offsets = __riscv_vor_vv_u16mf2(v_qs_u16, v_qh_expanded, 32);
4126        vuint64m2_t v_grid_vals = __riscv_vluxei16_v_u64m2(grid64, v_grid_offsets, 32);
4127        vuint8m2_t v_grid_u8 = __riscv_vreinterpret_v_u64m2_u8m2(v_grid_vals);
4128        vint8m2_t v_grid_i8 = __riscv_vreinterpret_v_u8m2_i8m2(v_grid_u8);
4129
4130        //loading signs
4131        vuint8mf2_t v_signs_raw = __riscv_vle8_v_u8mf2(signs_ptr, 32);
4132        signs_ptr += 32;
4133
4134        vuint8m2_t v_signs_source = __riscv_vlmul_ext_v_u8mf2_u8m2(v_signs_raw);
4135        vuint8m2_t v_signs_bcast = __riscv_vrgather_vv_u8m2(v_signs_source, v_sign_gather_indices, 256);
4136        vuint8m2_t v_sign_bits = __riscv_vand_vv_u8m2(v_signs_bcast, v_sign_masks, 256);
4137        vbool4_t m_negative = __riscv_vmsne_vx_u8m2_b4(v_sign_bits, 0, 256);
4138
4139        vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 256);
4140        q8 += 256;
4141
4142        vint8m2_t v_q8_signed = __riscv_vrsub_vx_i8m2_mu(m_negative, v_q8, v_q8, 0, 256);
4143        vint16m4_t v_dot = __riscv_vwmul_vv_i16m4(v_grid_i8, v_q8_signed, 256);
4144
4145        vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
4146
4147        vint16m4_t c = v_dot;
4148
4149        int32_t s0  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g0, c, v_zero, 64));
4150        int32_t s1  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g1, c, v_zero, 64));
4151        int32_t s2  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g2, c, v_zero, 64));
4152        int32_t s3  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g3, c, v_zero, 64));
4153
4154        c = __riscv_vslidedown_vx_i16m4(c, 64, 256);
4155        int32_t s4  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g0, c, v_zero, 64));
4156        int32_t s5  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g1, c, v_zero, 64));
4157        int32_t s6  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g2, c, v_zero, 64));
4158        int32_t s7  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g3, c, v_zero, 64));
4159
4160        c = __riscv_vslidedown_vx_i16m4(c, 64, 256);
4161        int32_t s8  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g0, c, v_zero, 64));
4162        int32_t s9  = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g1, c, v_zero, 64));
4163        int32_t s10 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g2, c, v_zero, 64));
4164        int32_t s11 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g3, c, v_zero, 64));
4165
4166        c = __riscv_vslidedown_vx_i16m4(c, 64, 256);
4167        int32_t s12 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g0, c, v_zero, 64));
4168        int32_t s13 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g1, c, v_zero, 64));
4169        int32_t s14 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g2, c, v_zero, 64));
4170        int32_t s15 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1_m(m_g3, c, v_zero, 64));
4171
4172        int32_t sums_arr[16] = { s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15 };
4173
4174        // Load 8 scale bytes and split into 16 nibbles
4175        vuint8mf2_t v_sc8 = __riscv_vle8_v_u8mf2(scales, 8);
4176        scales += 8;
4177
4178        vuint8mf2_t v_lo8 = __riscv_vand_vx_u8mf2(v_sc8, 0x0F, 8);
4179        vuint8mf2_t v_hi8 = __riscv_vsrl_vx_u8mf2(v_sc8, 4, 8);
4180
4181        vuint8m1_t v_idx16 = __riscv_vid_v_u8m1(16);
4182        vuint8m1_t v_half = __riscv_vsrl_vx_u8m1(v_idx16, 1, 16);
4183        vbool8_t m_even = __riscv_vmseq_vx_u8m1_b8(__riscv_vand_vx_u8m1(v_idx16, 1, 16), 0, 16);
4184
4185        vuint8m1_t v_lo_ext = __riscv_vlmul_ext_v_u8mf2_u8m1(v_lo8);
4186        vuint8m1_t v_hi_ext = __riscv_vlmul_ext_v_u8mf2_u8m1(v_hi8);
4187        vuint8m1_t v_lo_g = __riscv_vrgather_vv_u8m1(v_lo_ext, v_half, 16);
4188        vuint8m1_t v_hi_g = __riscv_vrgather_vv_u8m1(v_hi_ext, v_half, 16);
4189        vuint8m1_t v_nib = __riscv_vmerge_vvm_u8m1(v_lo_g, v_hi_g, m_even, 16);
4190
4191        static const uint8_t iq2s_scale_lut_16_local[16] = {
4192            1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31
4193        };
4194        vuint8m1_t v_lut = __riscv_vle8_v_u8m1(iq2s_scale_lut_16_local, 16);
4195        vuint8m1_t v_sc8v = __riscv_vrgather_vv_u8m1(v_lut, v_nib, 16);
4196
4197        vint32m4_t v_sums = __riscv_vle32_v_i32m4(sums_arr, 16);
4198        vuint16m2_t v_sc16 = __riscv_vwcvtu_x_x_v_u16m2(v_sc8v, 16);
4199        vuint32m4_t v_sc32u = __riscv_vwcvtu_x_x_v_u32m4(v_sc16, 16);
4200        vint32m4_t v_sc32 = __riscv_vreinterpret_v_u32m4_i32m4(v_sc32u);
4201        vint32m4_t v_prod = __riscv_vmul_vv_i32m4(v_sums, v_sc32, 16);
4202
4203        vint32m1_t v_zero32 = __riscv_vmv_v_x_i32m1(0, 1);
4204        int32_t sum_part = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m4_i32m1(v_prod, v_zero32, 16));
4205        sum_block += sum_part;
4206
4207        sumf += sum_block * combined_scale;
4208    }
4209    *s = 0.125f * sumf;
4210}
4211#endif
4212
4213void ggml_vec_dot_iq2_s_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4214#if defined __riscv_v
4215    switch (__riscv_vlenb() * 8) {
4216        case 128:
4217            ggml_vec_dot_iq2_s_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
4218            break;
4219        case 256:
4220            ggml_vec_dot_iq2_s_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
4221            break;
4222        case 512:
4223            ggml_vec_dot_iq2_s_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
4224            break;
4225        default:
4226            ggml_vec_dot_iq2_s_q8_K_vl1024(n, s, bs, vx, bx, vy, by, nrc);
4227            break;
4228    }
4229#else
4230    ggml_vec_dot_iq2_s_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
4231#endif
4232}
4233
4234#if defined __riscv_v
4235static const int8_t keven_signs_q2xs[1024] = {
4236     1,  1,  1,  1,  1,  1,  1,  1, -1,  1,  1,  1,  1,  1,  1, -1,  1, -1,  1,  1,  1,  1,  1, -1, -1, -1,  1,  1,  1,  1,  1,  1,
4237     1,  1, -1,  1,  1,  1,  1, -1, -1,  1, -1,  1,  1,  1,  1,  1,  1, -1, -1,  1,  1,  1,  1,  1, -1, -1, -1,  1,  1,  1,  1, -1,
4238     1,  1,  1, -1,  1,  1,  1, -1, -1,  1,  1, -1,  1,  1,  1,  1,  1, -1,  1, -1,  1,  1,  1,  1, -1, -1,  1, -1,  1,  1,  1, -1,
4239     1,  1, -1, -1,  1,  1,  1,  1, -1,  1, -1, -1,  1,  1,  1, -1,  1, -1, -1, -1,  1,  1,  1, -1, -1, -1, -1, -1,  1,  1,  1,  1,
4240     1,  1,  1,  1, -1,  1,  1, -1, -1,  1,  1,  1, -1,  1,  1,  1,  1, -1,  1,  1, -1,  1,  1,  1, -1, -1,  1,  1, -1,  1,  1, -1,
4241     1,  1, -1,  1, -1,  1,  1,  1, -1,  1, -1,  1, -1,  1,  1, -1,  1, -1, -1,  1, -1,  1,  1, -1, -1, -1, -1,  1, -1,  1,  1,  1,
4242     1,  1,  1, -1, -1,  1,  1,  1, -1,  1,  1, -1, -1,  1,  1, -1,  1, -1,  1, -1, -1,  1,  1, -1, -1, -1,  1, -1, -1,  1,  1,  1,
4243     1,  1, -1, -1, -1,  1,  1, -1, -1,  1, -1, -1, -1,  1,  1,  1,  1, -1, -1, -1, -1,  1,  1,  1, -1, -1, -1, -1, -1,  1,  1, -1,
4244     1,  1,  1,  1,  1, -1,  1, -1, -1,  1,  1,  1,  1, -1,  1,  1,  1, -1,  1,  1,  1, -1,  1,  1, -1, -1,  1,  1,  1, -1,  1, -1,
4245     1,  1, -1,  1,  1, -1,  1,  1, -1,  1, -1,  1,  1, -1,  1, -1,  1, -1, -1,  1,  1, -1,  1, -1, -1, -1, -1,  1,  1, -1,  1,  1,
4246     1,  1,  1, -1,  1, -1,  1,  1, -1,  1,  1, -1,  1, -1,  1, -1,  1, -1,  1, -1,  1, -1,  1, -1, -1, -1,  1, -1,  1, -1,  1,  1,
4247     1,  1, -1, -1,  1, -1,  1, -1, -1,  1, -1, -1,  1, -1,  1,  1,  1, -1, -1, -1,  1, -1,  1,  1, -1, -1, -1, -1,  1, -1,  1, -1,
4248     1,  1,  1,  1, -1, -1,  1,  1, -1,  1,  1,  1, -1, -1,  1, -1,  1, -1,  1,  1, -1, -1,  1, -1, -1, -1,  1,  1, -1, -1,  1,  1,
4249     1,  1, -1,  1, -1, -1,  1, -1, -1,  1, -1,  1, -1, -1,  1,  1,  1, -1, -1,  1, -1, -1,  1,  1, -1, -1, -1,  1, -1, -1,  1, -1,
4250     1,  1,  1, -1, -1, -1,  1, -1, -1,  1,  1, -1, -1, -1,  1,  1,  1, -1,  1, -1, -1, -1,  1,  1, -1, -1,  1, -1, -1, -1,  1, -1,
4251     1,  1, -1, -1, -1, -1,  1,  1, -1,  1, -1, -1, -1, -1,  1, -1,  1, -1, -1, -1, -1, -1,  1, -1, -1, -1, -1, -1, -1, -1,  1,  1,
4252     1,  1,  1,  1,  1,  1, -1, -1, -1,  1,  1,  1,  1,  1, -1,  1,  1, -1,  1,  1,  1,  1, -1,  1, -1, -1,  1,  1,  1,  1, -1, -1,
4253     1,  1, -1,  1,  1,  1, -1,  1, -1,  1, -1,  1,  1,  1, -1, -1,  1, -1, -1,  1,  1,  1, -1, -1, -1, -1, -1,  1,  1,  1, -1,  1,
4254     1,  1,  1, -1,  1,  1, -1,  1, -1,  1,  1, -1,  1,  1, -1, -1,  1, -1,  1, -1,  1,  1, -1, -1, -1, -1,  1, -1,  1,  1, -1,  1,
4255     1,  1, -1, -1,  1,  1, -1, -1, -1,  1, -1, -1,  1,  1, -1,  1,  1, -1, -1, -1,  1,  1, -1,  1, -1, -1, -1, -1,  1,  1, -1, -1,
4256     1,  1,  1,  1, -1,  1, -1,  1, -1,  1,  1,  1, -1,  1, -1, -1,  1, -1,  1,  1, -1,  1, -1, -1, -1, -1,  1,  1, -1,  1, -1,  1,
4257     1,  1, -1,  1, -1,  1, -1, -1, -1,  1, -1,  1, -1,  1, -1,  1,  1, -1, -1,  1, -1,  1, -1,  1, -1, -1, -1,  1, -1,  1, -1, -1,
4258     1,  1,  1, -1, -1,  1, -1, -1, -1,  1,  1, -1, -1,  1, -1,  1,  1, -1,  1, -1, -1,  1, -1,  1, -1, -1,  1, -1, -1,  1, -1, -1,
4259     1,  1, -1, -1, -1,  1, -1,  1, -1,  1, -1, -1, -1,  1, -1, -1,  1, -1, -1, -1, -1,  1, -1, -1, -1, -1, -1, -1, -1,  1, -1,  1,
4260     1,  1,  1,  1,  1, -1, -1,  1, -1,  1,  1,  1,  1, -1, -1, -1,  1, -1,  1,  1,  1, -1, -1, -1, -1, -1,  1,  1,  1, -1, -1,  1,
4261     1,  1, -1,  1,  1, -1, -1, -1, -1,  1, -1,  1,  1, -1, -1,  1,  1, -1, -1,  1,  1, -1, -1,  1, -1, -1, -1,  1,  1, -1, -1, -1,
4262     1,  1,  1, -1,  1, -1, -1, -1, -1,  1,  1, -1,  1, -1, -1,  1,  1, -1,  1, -1,  1, -1, -1,  1, -1, -1,  1, -1,  1, -1, -1, -1,
4263     1,  1, -1, -1,  1, -1, -1,  1, -1,  1, -1, -1,  1, -1, -1, -1,  1, -1, -1, -1,  1, -1, -1, -1, -1, -1, -1, -1,  1, -1, -1,  1,
4264     1,  1,  1,  1, -1, -1, -1, -1, -1,  1,  1,  1, -1, -1, -1,  1,  1, -1,  1,  1, -1, -1, -1,  1, -1, -1,  1,  1, -1, -1, -1, -1,
4265     1,  1, -1,  1, -1, -1, -1,  1, -1,  1, -1,  1, -1, -1, -1, -1,  1, -1, -1,  1, -1, -1, -1, -1, -1, -1, -1,  1, -1, -1, -1,  1,
4266     1,  1,  1, -1, -1, -1, -1,  1, -1,  1,  1, -1, -1, -1, -1, -1,  1, -1,  1, -1, -1, -1, -1, -1, -1, -1,  1, -1, -1, -1, -1,  1,
4267     1,  1, -1, -1, -1, -1, -1, -1, -1,  1, -1, -1, -1, -1, -1,  1,  1, -1, -1, -1, -1, -1, -1,  1, -1, -1, -1, -1, -1, -1, -1, -1,
4268};
4269
4270static NOINLINE void ggml_vec_dot_iq2_xs_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4271    assert(n % QK_K == 0);
4272    assert(nrc == 1);
4273    UNUSED(nrc);
4274    UNUSED(bx);
4275    UNUSED(by);
4276    UNUSED(bs);
4277
4278    const block_iq2_xs * GGML_RESTRICT x = vx;
4279    const block_q8_K   * GGML_RESTRICT y = vy;
4280
4281    const int nb = n / QK_K;
4282    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
4283    const uint64_t * grid64  = (const uint64_t *)iq2xs_grid;
4284
4285    float sumf = 0.0f;
4286#pragma GCC unroll 1
4287    for (int i = 0; i < nb; ++i) {
4288        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
4289        const uint16_t * GGML_RESTRICT qs = x[i].qs;
4290        const int8_t   * GGML_RESTRICT q8 = y[i].qs;
4291        const uint8_t  * GGML_RESTRICT scales = x[i].scales;
4292
4293        int32_t sum_int = 0;
4294
4295        // Loop over 4 subblocks of 64 elements
4296        for (int ib64 = 0; ib64 < QK_K / 64; ++ib64) {
4297
4298            // Load indices.
4299            vuint16m1_t v_qs = __riscv_vle16_v_u16m1(qs, 8);
4300            qs += 8;
4301
4302            // Prepare offsets
4303            vuint16m1_t vidx_grid = __riscv_vsll_vx_u16m1(__riscv_vand_vx_u16m1(v_qs, 511, 8), 3, 8);
4304            vuint16m1_t vidx_sign = __riscv_vsll_vx_u16m1(__riscv_vsrl_vx_u16m1(v_qs, 9, 8), 3, 8);
4305
4306            // load values and signs from the lookup tables
4307            vuint64m4_t vq2_64 = __riscv_vluxei16_v_u64m4(grid64, vidx_grid, 8);
4308            vuint64m4_t vs2_64 = __riscv_vluxei16_v_u64m4(signs64, vidx_sign, 8);
4309            vint8m4_t q2u = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vq2_64));
4310            vint8m4_t q2s = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vs2_64));
4311            vint8m4_t q2_final = __riscv_vmul_vv_i8m4(q2u, q2s, 64);
4312            asm volatile("" ::: "memory");
4313            vint8m4_t q8v = __riscv_vle8_v_i8m4(q8, 64);
4314            q8 += 64;
4315
4316            vint16m8_t prod = __riscv_vwmul_vv_i16m8(q2_final, q8v, 64);
4317            asm volatile("" ::: "memory");
4318            vint32m1_t zero_vec = __riscv_vmv_v_x_i32m1(0, 1);
4319
4320            int32_t sum0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(
4321                           __riscv_vget_v_i16m8_i16m2(prod, 0), zero_vec, 16));
4322
4323            int32_t sum1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(
4324                           __riscv_vget_v_i16m8_i16m2(prod, 1), zero_vec, 16));
4325
4326            int32_t sum2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(
4327                           __riscv_vget_v_i16m8_i16m2(prod, 2), zero_vec, 16));
4328
4329            int32_t sum3 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(
4330                           __riscv_vget_v_i16m8_i16m2(prod, 3), zero_vec, 16));
4331
4332            const uint8_t scale_byte_1 = scales[0];
4333            const uint8_t scale_byte_2 = scales[1];
4334            scales += 2;
4335
4336            sum_int += sum0 * ((scale_byte_1 & 0x0F) * 2 + 1);
4337            sum_int += sum1 * ((scale_byte_1 >> 4)   * 2 + 1);
4338            sum_int += sum2 * ((scale_byte_2 & 0x0F) * 2 + 1);
4339            sum_int += sum3 * ((scale_byte_2 >> 4)   * 2 + 1);
4340        }
4341
4342        sumf += d * sum_int;
4343    }
4344    *s = 0.125f * sumf;
4345}
4346
4347static NOINLINE void ggml_vec_dot_iq2_xs_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4348    assert(n % QK_K == 0);
4349    assert(nrc == 1);
4350    UNUSED(nrc);
4351    UNUSED(bx);
4352    UNUSED(by);
4353    UNUSED(bs);
4354
4355    const block_iq2_xs * GGML_RESTRICT x = vx;
4356    const block_q8_K   * GGML_RESTRICT y = vy;
4357
4358    const int nb = n / QK_K;
4359    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
4360    const uint64_t * grid64  = (const uint64_t *)iq2xs_grid;
4361
4362    float sumf = 0.0f;
4363
4364    for (int i = 0; i < nb; ++i) {
4365        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
4366        const uint16_t * GGML_RESTRICT qs = x[i].qs;
4367        const int8_t   * GGML_RESTRICT q8 = y[i].qs;
4368        const uint8_t  * GGML_RESTRICT scales = x[i].scales;
4369
4370        int32_t sum_int = 0;
4371
4372        for (int ib128 = 0; ib128 < 2; ++ib128) {
4373
4374            vuint16m1_t v_qs = __riscv_vle16_v_u16m1(qs, 16);
4375            qs += 16;
4376
4377            // Prepare offsets for grid and signs
4378            vuint16m1_t vidx_grid = __riscv_vsll_vx_u16m1(__riscv_vand_vx_u16m1(v_qs, 511, 16), 3, 16);
4379            vuint16m1_t vidx_sign = __riscv_vsll_vx_u16m1(__riscv_vsrl_vx_u16m1(v_qs, 9, 16), 3, 16);
4380
4381            // Indexed load 128 weights (16 x 8-byte chunks)
4382            vuint64m4_t vq2_64 = __riscv_vluxei16_v_u64m4(grid64, vidx_grid, 16);
4383            vuint64m4_t vs2_64 = __riscv_vluxei16_v_u64m4(signs64, vidx_sign, 16);
4384
4385            vint8m4_t q2u = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vq2_64));
4386            vint8m4_t q2s = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vs2_64));
4387
4388            // Apply signs to get dequantized IQ2 values
4389            vint8m4_t q2_final = __riscv_vmul_vv_i8m4(q2u, q2s, 128);
4390            asm volatile("" ::: "memory");
4391
4392            // Load corresponding Q8 weights
4393            vint8m4_t q8v = __riscv_vle8_v_i8m4(q8, 128);
4394            q8 += 128;
4395
4396            vint16m8_t prod = __riscv_vwmul_vv_i16m8(q2_final, q8v, 128);
4397            asm volatile("" ::: "memory");
4398
4399            uint8_t sc0 = scales[0];
4400            uint8_t sc1 = scales[1];
4401            uint8_t sc2 = scales[2];
4402            uint8_t sc3 = scales[3];
4403            scales += 4;
4404
4405            vint32m1_t zero_vec = __riscv_vmv_v_x_i32m1(0, 1);
4406
4407            // 9. Reduce each 16-element chunk and apply corresponding nibble scale
4408
4409            int32_t s0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 0), zero_vec, 16));
4410            sum_int += s0 * ((sc0 & 0x0F) * 2 + 1);
4411
4412            int32_t s1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 1), zero_vec, 16));
4413            sum_int += s1 * ((sc0 >> 4) * 2 + 1);
4414
4415            int32_t s2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 2), zero_vec, 16));
4416            sum_int += s2 * ((sc1 & 0x0F) * 2 + 1);
4417
4418            int32_t s3 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 3), zero_vec, 16));
4419            sum_int += s3 * ((sc1 >> 4) * 2 + 1);
4420
4421            int32_t s4 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 4), zero_vec, 16));
4422            sum_int += s4 * ((sc2 & 0x0F) * 2 + 1);
4423
4424            int32_t s5 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 5), zero_vec, 16));
4425            sum_int += s5 * ((sc2 >> 4) * 2 + 1);
4426
4427            int32_t s6 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 6), zero_vec, 16));
4428            sum_int += s6 * ((sc3 & 0x0F) * 2 + 1);
4429
4430            int32_t s7 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 7), zero_vec, 16));
4431            sum_int += s7 * ((sc3 >> 4) * 2 + 1);
4432        }
4433
4434        sumf += d * (float)sum_int;
4435    }
4436    *s = 0.125f * sumf;
4437}
4438
4439static NOINLINE void ggml_vec_dot_iq2_xs_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4440    assert(n % QK_K == 0);
4441    assert(nrc == 1);
4442    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
4443
4444    const block_iq2_xs * GGML_RESTRICT x = vx;
4445    const block_q8_K   * GGML_RESTRICT y = vy;
4446
4447    const int nb = n / QK_K;
4448    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
4449    const uint64_t * grid64  = (const uint64_t *)iq2xs_grid;
4450
4451    float sumf = 0.0f;
4452     for (int i = 0; i < nb; ++i) {
4453        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
4454
4455        const uint16_t * GGML_RESTRICT qs = x[i].qs;
4456        const uint8_t  * GGML_RESTRICT scales = x[i].scales;
4457        const int8_t   * GGML_RESTRICT q8 = y[i].qs;
4458
4459        vint8m4_t q8_all = __riscv_vle8_v_i8m4(q8, 256);
4460
4461        // Load indices ---
4462        vuint16m1_t v_qs = __riscv_vle16_v_u16m1(qs, 32);
4463
4464        // Extract low 9 bits and multiply by 8 (shift left 3) for byte offset into uint64 table
4465        vuint16m1_t vidx_grid = __riscv_vsll_vx_u16m1(__riscv_vand_vx_u16m1(v_qs, 511, 32), 3, 32);
4466
4467        // Extract high 7 bits (shift right 9) and multiply by 8 (shift left 3) for byte offset
4468        vuint16m1_t vidx_sign = __riscv_vsll_vx_u16m1(__riscv_vsrl_vx_u16m1(v_qs, 9, 32), 3, 32);
4469
4470        vuint64m4_t vq2_64 = __riscv_vluxei16_v_u64m4(grid64, vidx_grid, 32);
4471        vuint64m4_t vs2_64 = __riscv_vluxei16_v_u64m4(signs64, vidx_sign, 32);
4472
4473        vint8m4_t q2_all = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vq2_64));
4474        vint8m4_t s2_all = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vs2_64));
4475
4476        vint8m4_t q2_signed = __riscv_vmul_vv_i8m4(q2_all, s2_all, 256);
4477        vint16m8_t dot_all = __riscv_vwmul_vv_i16m8(q2_signed, q8_all, 256);
4478        float sum = 0.0f;
4479        vint32m1_t zero_vec = __riscv_vmv_v_x_i32m1(0, 1);
4480
4481#pragma GCC unroll 1
4482        for (int j = 0; j < 8; ++j) {
4483            uint8_t sc = scales[j];
4484            int16_t sc_lo = 2 * (sc & 0x0F) + 1;
4485            int16_t sc_hi = 2 * (sc >> 4)   + 1;
4486
4487            vint32m1_t sum_v0 = __riscv_vwredsum_vs_i16m8_i32m1(
4488                __riscv_vslidedown_vx_i16m8(dot_all, j * 32, 16), zero_vec, 16);
4489            int32_t isum0 = __riscv_vmv_x_s_i32m1_i32(sum_v0);
4490
4491            vint32m1_t sum_v1 = __riscv_vwredsum_vs_i16m8_i32m1(
4492                __riscv_vslidedown_vx_i16m8(dot_all, j * 32 + 16, 16), zero_vec, 16);
4493            int32_t isum1 = __riscv_vmv_x_s_i32m1_i32(sum_v1);
4494
4495            sum += (float)isum0 * sc_lo + (float)isum1 * sc_hi;
4496        }
4497
4498        sumf += sum * combined_scale;
4499    }
4500    *s = 0.125f * sumf;
4501}
4502#endif
4503
4504void ggml_vec_dot_iq2_xs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4505#if defined __riscv_v
4506      switch (__riscv_vlenb() * 8) {
4507          case 128:
4508              ggml_vec_dot_iq2_xs_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
4509              break;
4510          case 256:
4511              ggml_vec_dot_iq2_xs_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
4512              break;
4513          default: // 512 and above
4514              ggml_vec_dot_iq2_xs_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
4515              break;
4516      }
4517#else
4518    ggml_vec_dot_iq2_xs_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
4519#endif
4520}
4521
4522#if defined __riscv_v
4523static NOINLINE void ggml_vec_dot_iq2_xxs_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4524    assert(n % QK_K == 0);
4525    assert(nrc == 1);
4526    UNUSED(nrc);
4527    UNUSED(bx);
4528    UNUSED(by);
4529    UNUSED(bs);
4530
4531    const block_iq2_xxs * GGML_RESTRICT x = vx;
4532    const block_q8_K    * GGML_RESTRICT y = vy;
4533
4534    const int nb = n / QK_K;
4535    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
4536    const uint64_t * grid64  = (const uint64_t *)iq2xxs_grid;
4537
4538    uint32_t shift_constants[4] = {0, 7, 14, 21};
4539    vuint32m1_t v_shifts = __riscv_vle32_v_u32m1(shift_constants, 4);
4540
4541    float sumf = 0.0f;
4542    for (int i = 0; i < nb; ++i) {
4543        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
4544
4545        const uint8_t  * GGML_RESTRICT q2_ptr = (const uint8_t *) x[i].qs;
4546        const int8_t   * GGML_RESTRICT q8 = y[i].qs;
4547
4548        float sum = 0.0f;
4549
4550        #pragma GCC unroll 1
4551        for (int ib32 = 0; ib32 < QK_K / 32; ib32 += 2) {
4552            vint8m2_t q8_1 = __riscv_vle8_v_i8m2(q8, 32); q8 += 32;
4553            vint8m2_t q8_2 = __riscv_vle8_v_i8m2(q8, 32); q8 += 32;
4554
4555            vuint8mf4_t v_raw_q2_1 = __riscv_vle8_v_u8mf4(q2_ptr, 4);
4556            vuint8mf4_t v_raw_q2_2 = __riscv_vle8_v_u8mf4(q2_ptr + 8, 4);
4557
4558            vuint16mf2_t vidx_q2_1 = __riscv_vwcvtu_x_x_v_u16mf2(v_raw_q2_1, 4);
4559            vuint16mf2_t vidx_q2_2 = __riscv_vwcvtu_x_x_v_u16mf2(v_raw_q2_2, 4);
4560
4561            vidx_q2_1 = __riscv_vsll_vx_u16mf2(vidx_q2_1, 3, 4);
4562            vidx_q2_2 = __riscv_vsll_vx_u16mf2(vidx_q2_2, 3, 4);
4563
4564            uint32_t s_packed_1, s_packed_2;
4565            memcpy(&s_packed_1, q2_ptr + 4, 4);
4566            memcpy(&s_packed_2, q2_ptr + 12, 4);
4567
4568            vuint32m1_t v_s_1 = __riscv_vmv_v_x_u32m1(s_packed_1, 4);
4569            vuint32m1_t v_s_2 = __riscv_vmv_v_x_u32m1(s_packed_2, 4);
4570            v_s_1 = __riscv_vsrl_vv_u32m1(v_s_1, v_shifts, 4);
4571            v_s_2 = __riscv_vsrl_vv_u32m1(v_s_2, v_shifts, 4);
4572
4573            v_s_1 = __riscv_vand_vx_u32m1(v_s_1, 127, 4);
4574            v_s_2 = __riscv_vand_vx_u32m1(v_s_2, 127, 4);
4575
4576            vuint16mf2_t vidx_s2_1 = __riscv_vsll_vx_u16mf2(__riscv_vncvt_x_x_w_u16mf2(v_s_1, 4), 3, 4);
4577            vuint16mf2_t vidx_s2_2 = __riscv_vsll_vx_u16mf2(__riscv_vncvt_x_x_w_u16mf2(v_s_2, 4), 3, 4);
4578
4579            vuint64m2_t vq2_64_1 = __riscv_vluxei16_v_u64m2(grid64, vidx_q2_1, 4);
4580            vuint64m2_t vq2_64_2 = __riscv_vluxei16_v_u64m2(grid64, vidx_q2_2, 4);
4581
4582            vint8m2_t q2_1 = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vreinterpret_v_u64m2_u8m2(vq2_64_1));
4583            vint8m2_t q2_2 = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vreinterpret_v_u64m2_u8m2(vq2_64_2));
4584
4585            vuint64m2_t vs2_64_1 = __riscv_vluxei16_v_u64m2(signs64, vidx_s2_1, 4);
4586            vuint64m2_t vs2_64_2 = __riscv_vluxei16_v_u64m2(signs64, vidx_s2_2, 4);
4587            vint8m2_t s2_1 = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vreinterpret_v_u64m2_u8m2(vs2_64_1));
4588            vint8m2_t s2_2 = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vreinterpret_v_u64m2_u8m2(vs2_64_2));
4589
4590            vint8m2_t q8s_1 = __riscv_vmul_vv_i8m2(q8_1, s2_1, 32);
4591            vint8m2_t q8s_2 = __riscv_vmul_vv_i8m2(q8_2, s2_2, 32);
4592
4593            vint16m4_t dot1 = __riscv_vwmul_vv_i16m4(q8s_1, q2_1, 32);
4594            vint16m4_t dot2 = __riscv_vwmul_vv_i16m4(q8s_2, q2_2, 32);
4595
4596            vint32m1_t zero_vec = __riscv_vmv_v_x_i32m1(0, 1);
4597            vint32m1_t sumv1 = __riscv_vwredsum_vs_i16m4_i32m1(dot1, zero_vec, 32);
4598            vint32m1_t sumv2 = __riscv_vwredsum_vs_i16m4_i32m1(dot2, zero_vec, 32);
4599
4600            int32_t scalar_sum1 = __riscv_vmv_x_s_i32m1_i32(sumv1);
4601            int32_t scalar_sum2 = __riscv_vmv_x_s_i32m1_i32(sumv2);
4602
4603            int16_t scale1 = 2 * ((s_packed_1 >> 28) & 0xF) + 1;
4604            int16_t scale2 = 2 * ((s_packed_2 >> 28) & 0xF) + 1;
4605
4606            sum += scalar_sum1 * scale1 + scalar_sum2 * scale2;
4607            q2_ptr += 16;
4608        }
4609        sumf += sum * combined_scale;
4610    }
4611    *s = 0.125f * sumf;
4612}
4613
4614static NOINLINE void ggml_vec_dot_iq2_xxs_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4615    assert(n % QK_K == 0);
4616    assert(nrc == 1);
4617    UNUSED(nrc);
4618    UNUSED(bx);
4619    UNUSED(by);
4620    UNUSED(bs);
4621
4622    const block_iq2_xxs * GGML_RESTRICT x = vx;
4623    const block_q8_K    * GGML_RESTRICT y = vy;
4624
4625    const int nb = n / QK_K;
4626    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
4627    const uint64_t * grid64  = (const uint64_t *)iq2xxs_grid;
4628
4629    uint32_t shift_constants[4] = {0, 7, 14, 21};
4630    vuint32mf2_t v_shifts = __riscv_vle32_v_u32mf2(shift_constants, 4);
4631
4632    float sumf = 0.0f;
4633
4634    for (int i = 0; i < nb; ++i) {
4635        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
4636
4637        const uint8_t  * GGML_RESTRICT q2_ptr = (const uint8_t *) x[i].qs;
4638        const int8_t   * GGML_RESTRICT q8 = y[i].qs;
4639
4640        float sum = 0.0f;
4641
4642        for (int ib32 = 0; ib32 < QK_K / 32; ib32 += 2) {
4643            vint8m1_t q8_1 = __riscv_vle8_v_i8m1(q8, 32); q8 += 32;
4644            vint8m1_t q8_2 = __riscv_vle8_v_i8m1(q8, 32); q8 += 32;
4645
4646            vuint8mf8_t v_raw_q2_1 = __riscv_vle8_v_u8mf8(q2_ptr, 4);
4647            vuint8mf8_t v_raw_q2_2 = __riscv_vle8_v_u8mf8(q2_ptr + 8, 4);
4648
4649            vuint16mf4_t vidx_q2_1 = __riscv_vwcvtu_x_x_v_u16mf4(v_raw_q2_1, 4);
4650            vuint16mf4_t vidx_q2_2 = __riscv_vwcvtu_x_x_v_u16mf4(v_raw_q2_2, 4);
4651
4652            vidx_q2_1 = __riscv_vsll_vx_u16mf4(vidx_q2_1, 3, 4);
4653            vidx_q2_2 = __riscv_vsll_vx_u16mf4(vidx_q2_2, 3, 4);
4654
4655            uint32_t s_packed_1, s_packed_2;
4656            memcpy(&s_packed_1, q2_ptr + 4, 4);
4657            memcpy(&s_packed_2, q2_ptr + 12, 4);
4658
4659            vuint32mf2_t v_s_1 = __riscv_vmv_v_x_u32mf2(s_packed_1, 4);
4660            vuint32mf2_t v_s_2 = __riscv_vmv_v_x_u32mf2(s_packed_2, 4);
4661
4662            v_s_1 = __riscv_vsrl_vv_u32mf2(v_s_1, v_shifts, 4);
4663            v_s_2 = __riscv_vsrl_vv_u32mf2(v_s_2, v_shifts, 4);
4664
4665            v_s_1 = __riscv_vand_vx_u32mf2(v_s_1, 127, 4);
4666            v_s_2 = __riscv_vand_vx_u32mf2(v_s_2, 127, 4);
4667
4668            // Narrow u32 -> u16 (vncvt) and Scale by 8 to get byte offsets
4669            vuint16mf4_t vidx_s2_1 = __riscv_vsll_vx_u16mf4(__riscv_vncvt_x_x_w_u16mf4(v_s_1, 4), 3, 4);
4670            vuint16mf4_t vidx_s2_2 = __riscv_vsll_vx_u16mf4(__riscv_vncvt_x_x_w_u16mf4(v_s_2, 4), 3, 4);
4671
4672            // Load q2 values from lookup grid
4673            vuint64m1_t vq2_64_1 = __riscv_vluxei16_v_u64m1(grid64, vidx_q2_1, 4);
4674            vuint64m1_t vq2_64_2 = __riscv_vluxei16_v_u64m1(grid64, vidx_q2_2, 4);
4675            vint8m1_t q2_1 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vreinterpret_v_u64m1_u8m1(vq2_64_1));
4676            vint8m1_t q2_2 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vreinterpret_v_u64m1_u8m1(vq2_64_2));
4677
4678            // Load sign values
4679            vuint64m1_t vs2_64_1 = __riscv_vluxei16_v_u64m1(signs64, vidx_s2_1, 4);
4680            vuint64m1_t vs2_64_2 = __riscv_vluxei16_v_u64m1(signs64, vidx_s2_2, 4);
4681            vint8m1_t s2_1 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vreinterpret_v_u64m1_u8m1(vs2_64_1));
4682            vint8m1_t s2_2 = __riscv_vreinterpret_v_u8m1_i8m1(__riscv_vreinterpret_v_u64m1_u8m1(vs2_64_2));
4683
4684            // Apply signs to q8
4685            vint8m1_t q8s_1 = __riscv_vmul_vv_i8m1(q8_1, s2_1, 32);
4686            vint8m1_t q8s_2 = __riscv_vmul_vv_i8m1(q8_2, s2_2, 32);
4687
4688            // multiplying q2 with q8
4689            vint16m2_t dot1 = __riscv_vwmul_vv_i16m2(q8s_1, q2_1, 32);
4690            vint16m2_t dot2 = __riscv_vwmul_vv_i16m2(q8s_2, q2_2, 32);
4691
4692            vint32m1_t zero_vec = __riscv_vmv_v_x_i32m1(0, 1);
4693            vint32m1_t sumv1 = __riscv_vwredsum_vs_i16m2_i32m1(dot1, zero_vec, 32);
4694            vint32m1_t sumv2 = __riscv_vwredsum_vs_i16m2_i32m1(dot2, zero_vec, 32);
4695            int32_t scalar_sum1 = __riscv_vmv_x_s_i32m1_i32(sumv1);
4696            int32_t scalar_sum2 = __riscv_vmv_x_s_i32m1_i32(sumv2);
4697            int16_t scale1 = 2 * ((s_packed_1 >> 28) & 0xF) + 1;
4698            int16_t scale2 = 2 * ((s_packed_2 >> 28) & 0xF) + 1;
4699
4700            sum += scalar_sum1 * scale1 + scalar_sum2 * scale2;
4701            q2_ptr += 16;
4702        }
4703        sumf += sum * combined_scale;
4704    }
4705    *s = 0.125f * sumf;
4706}
4707
4708static NOINLINE void ggml_vec_dot_iq2_xxs_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4709    assert(n % QK_K == 0);
4710    assert(nrc == 1);
4711    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
4712
4713    const block_iq2_xxs * GGML_RESTRICT x = vx;
4714    const block_q8_K    * GGML_RESTRICT y = vy;
4715
4716    const int nb = n / QK_K;
4717    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
4718    const uint64_t * grid64  = (const uint64_t *)iq2xxs_grid;
4719    // Shift pattern {0,7,14,21} repeated 8 times for all 8 sub-blocks
4720    uint8_t shift_arr[32] = {
4721        0, 7, 14, 21, 0, 7, 14, 21, 0, 7, 14, 21, 0, 7, 14, 21,
4722        0, 7, 14, 21, 0, 7, 14, 21, 0, 7, 14, 21, 0, 7, 14, 21
4723    };
4724    vuint8mf2_t v_shifts = __riscv_vle8_v_u8mf2(shift_arr, 32);
4725
4726    // Gather pattern to broadcast the 8 sub-block scales across the 32 lookup slots
4727    uint8_t gather_arr[32] = {
4728        0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3,
4729        4,4,4,4, 5,5,5,5, 6,6,6,6, 7,7,7,7
4730    };
4731    vuint8mf2_t v_sign_gather_idx = __riscv_vle8_v_u8mf2(gather_arr, 32);
4732
4733    float sumf = 0.0f;
4734    for (int i = 0; i < nb; ++i) {
4735        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
4736
4737        const uint8_t  * GGML_RESTRICT q2_ptr = (const uint8_t *) x[i].qs;
4738        const int8_t   * GGML_RESTRICT q8 = y[i].qs;
4739        vint8m4_t q8_all = __riscv_vle8_v_i8m4(q8, 256);
4740
4741        // De-interleave all 8 Index/Scale pairs for the 8x32-element sub-blocks
4742        vuint32mf2x2_t tuple = __riscv_vlseg2e32_v_u32mf2x2((const uint32_t*)q2_ptr, 8);
4743        vuint32mf2_t v_ind32 = __riscv_vget_v_u32mf2x2_u32mf2(tuple, 0);
4744        vuint32mf2_t v_sc32  = __riscv_vget_v_u32mf2x2_u32mf2(tuple, 1);
4745
4746        vuint8mf2_t v_raw_q2 = __riscv_vreinterpret_v_u32mf2_u8mf2(v_ind32);
4747        vuint16m1_t vidx_q2 = __riscv_vwcvtu_x_x_v_u16m1(v_raw_q2, 32);
4748        vidx_q2 = __riscv_vsll_vx_u16m1(vidx_q2, 3, 32);
4749
4750        vuint32m2_t v_s = __riscv_vrgatherei16_vv_u32m2(__riscv_vlmul_ext_v_u32mf2_u32m2(v_sc32), __riscv_vwcvtu_x_x_v_u16m1(v_sign_gather_idx,32), 32);
4751        v_s = __riscv_vsrl_vv_u32m2(v_s, __riscv_vwcvtu_x_x_v_u32m2(__riscv_vwcvtu_x_x_v_u16m1(v_shifts,32),32), 32);
4752        v_s = __riscv_vand_vx_u32m2(v_s, 127, 32);
4753        vuint16m1_t vidx_s2 = __riscv_vsll_vx_u16m1(__riscv_vncvt_x_x_w_u16m1(v_s, 32), 3, 32);
4754
4755        vuint64m4_t vq2_64 = __riscv_vluxei16_v_u64m4(grid64, vidx_q2, 32);
4756        vuint64m4_t vs2_64 = __riscv_vluxei16_v_u64m4(signs64, vidx_s2, 32);
4757        vint8m4_t q2_all = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vq2_64));
4758        vint8m4_t s2_all = __riscv_vreinterpret_v_u8m4_i8m4(__riscv_vreinterpret_v_u64m4_u8m4(vs2_64));
4759
4760        vint8m4_t q8s_all = __riscv_vmul_vv_i8m4(q8_all, s2_all, 256);
4761        vint16m8_t dot_all = __riscv_vwmul_vv_i16m8(q8s_all, q2_all, 256);
4762
4763        float sum = 0.0f;
4764        vint32m1_t zero_vec = __riscv_vmv_v_x_i32m1(0, 1);
4765
4766        for (int j = 0; j < 8; ++j) {
4767            uint32_t s_p = __riscv_vmv_x_s_u32mf2_u32(__riscv_vslidedown_vx_u32mf2(v_sc32, j, 8));
4768            int16_t sc = 2 * ((s_p >> 28) & 0xF) + 1;
4769            dot_all=__riscv_vslidedown_vx_i16m8(dot_all,j*32,32);
4770            vint32m1_t sum_v = __riscv_vwredsum_vs_i16m8_i32m1(dot_all, zero_vec, 32);
4771            int32_t isum = __riscv_vmv_x_s_i32m1_i32(sum_v);
4772            sum += (float)isum * sc;
4773        }
4774
4775        sumf += sum * combined_scale;
4776    }
4777    *s = 0.125f * sumf;
4778}
4779#endif
4780
4781void ggml_vec_dot_iq2_xxs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4782#if defined __riscv_v
4783    switch (__riscv_vlenb() * 8) {
4784        case 128:
4785            ggml_vec_dot_iq2_xxs_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
4786            break;
4787        case 256:
4788            ggml_vec_dot_iq2_xxs_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
4789            break;
4790        default: // 512 and above
4791            ggml_vec_dot_iq2_xxs_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
4792            break;
4793    }
4794#else
4795    ggml_vec_dot_iq2_xxs_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
4796#endif
4797}
4798
4799#if defined __riscv_v
4800static NOINLINE void ggml_vec_dot_iq3_s_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4801    assert(n % QK_K == 0);
4802    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
4803    const block_iq3_s * GGML_RESTRICT x = vx;
4804    const block_q8_K  * GGML_RESTRICT y = vy;
4805
4806    const int nb = n / QK_K;
4807    const uint32_t * grid32 = (const uint32_t *)iq3s_grid;
4808
4809    vuint8mf2_t v_id_8  = __riscv_vid_v_u8mf2(8);
4810    vuint8m2_t  v_id_32 = __riscv_vid_v_u8m2(32);
4811
4812    // Keeping these in a tight scope to hint they're only needed for the mask computation.
4813    vuint8m2_t v_sign_gather_indices, v_sign_masks;
4814    {
4815        vuint8m2_t v_shifts  = __riscv_vand_vx_u8m2(v_id_32, 7, 32);
4816        vuint8m2_t v_one_32  = __riscv_vmv_v_x_u8m2(1, 32);
4817        v_sign_gather_indices = __riscv_vsrl_vx_u8m2(v_id_32, 3, 32);
4818        v_sign_masks          = __riscv_vsll_vv_u8m2(v_one_32, v_shifts, 32);
4819    }
4820
4821    float sumf = 0.0f;
4822
4823    for (int i = 0; i < nb; ++i) {
4824        const float d              = GGML_CPU_FP16_TO_FP32(x[i].d);
4825        const float combined_scale = d * y[i].d;
4826
4827        const uint8_t * GGML_RESTRICT qs     = x[i].qs;
4828        const uint8_t * GGML_RESTRICT qh     = x[i].qh;
4829        const uint8_t * GGML_RESTRICT scales = x[i].scales;
4830        const uint8_t * GGML_RESTRICT signs  = x[i].signs;
4831        const int8_t  * GGML_RESTRICT q8     = y[i].qs;
4832
4833        float sum_block = 0.0f;
4834
4835        for (int ib = 0; ib < 8; ++ib) {
4836
4837            // Grid lookup
4838            vuint8m2_t v_grid_u8;
4839            {
4840                vuint8mf2_t v_qs_u8 = __riscv_vle8_v_u8mf2(qs, 8);
4841                qs += 8;
4842
4843                uint8_t     qh_val   = *qh++;
4844                vuint8mf2_t v_qh_val = __riscv_vmv_v_x_u8mf2(qh_val, 8);
4845                v_qh_val = __riscv_vsrl_vv_u8mf2(v_qh_val, v_id_8, 8);
4846                v_qh_val = __riscv_vand_vx_u8mf2(v_qh_val, 1, 8);
4847
4848                vuint16m1_t v_qs_u16 = __riscv_vwcvtu_x_x_v_u16m1(v_qs_u8, 8);
4849                v_qs_u16 = __riscv_vsll_vx_u16m1(v_qs_u16, 2, 8);
4850
4851                vuint16m1_t v_qh_u16 = __riscv_vwcvtu_x_x_v_u16m1(v_qh_val, 8);
4852                v_qh_u16 = __riscv_vsll_vx_u16m1(v_qh_u16, 10, 8);
4853
4854                vuint16m1_t v_grid_offsets = __riscv_vor_vv_u16m1(v_qs_u16, v_qh_u16, 8);
4855
4856                vuint32m2_t v_grid_packed = __riscv_vluxei16_v_u32m2(grid32, v_grid_offsets, 8);
4857                v_grid_u8 = __riscv_vreinterpret_v_u32m2_u8m2(v_grid_packed);
4858            }
4859            __asm__ volatile ("" ::: "memory");
4860
4861            //Sign application and dot product
4862            int32_t s_val;
4863            {
4864                vuint8mf4_t v_signs_raw  = __riscv_vle8_v_u8mf4(signs, 4);
4865                signs += 4;
4866
4867                vuint8m2_t v_signs_source = __riscv_vlmul_ext_v_u8mf4_u8m2(v_signs_raw);
4868                vuint8m2_t v_signs_bcast  = __riscv_vrgather_vv_u8m2(v_signs_source, v_sign_gather_indices, 32);
4869                vuint8m2_t v_sign_bits    = __riscv_vand_vv_u8m2(v_signs_bcast, v_sign_masks, 32);
4870                vbool4_t   m_negative     = __riscv_vmsne_vx_u8m2_b4(v_sign_bits, 0, 32);
4871
4872                vint8m2_t v_q8        = __riscv_vle8_v_i8m2(q8, 32);
4873                q8 += 32;
4874
4875                vint8m2_t  v_q8_signed = __riscv_vrsub_vx_i8m2_mu(m_negative, v_q8, v_q8, 0, 32);
4876                vint16m4_t v_dot       = __riscv_vwmulsu_vv_i16m4(v_q8_signed, v_grid_u8, 32);
4877
4878                vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
4879                s_val = __riscv_vmv_x_s_i32m1_i32(
4880                    __riscv_vwredsum_vs_i16m4_i32m1(v_dot, v_zero, 32));
4881            }
4882            __asm__ volatile ("" ::: "memory");
4883            {
4884                uint8_t sc_byte = scales[ib >> 1];
4885                int sc_val = (ib & 1) ? (sc_byte >> 4) : (sc_byte & 0xF);
4886                sc_val = sc_val * 2 + 1;
4887                sum_block += (float)(s_val * sc_val);
4888            }
4889        }
4890        sumf += sum_block * combined_scale;
4891    }
4892    *s = sumf;
4893}
4894
4895static NOINLINE void ggml_vec_dot_iq3_s_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4896    assert(n % QK_K == 0);
4897    UNUSED(nrc);
4898    UNUSED(bx);
4899    UNUSED(by);
4900    UNUSED(bs);
4901
4902    const block_iq3_s * GGML_RESTRICT x = vx;
4903    const block_q8_K  * GGML_RESTRICT y = vy;
4904
4905    const int nb = n / QK_K;
4906
4907    const uint64_t * grid64 = (const uint64_t *)iq3s_grid;
4908
4909    // --- Pre-load Constants ---
4910    const uint16_t qh_bit_shifts_arr[16] = {
4911        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
4912    };
4913    vuint8m2_t v_sign_gather_indices = __riscv_vle8_v_u8m2(sign_gather_indices_arr, 64);
4914    vuint8m2_t v_sign_masks = __riscv_vle8_v_u8m2(sign_bit_masks_arr, 64);
4915    vuint16m1_t v_qh_shifts = __riscv_vle16_v_u16m1(qh_bit_shifts_arr, 16);
4916
4917    float sumf = 0.0f;
4918
4919    for (int i = 0; i < nb; ++i) {
4920        const float d = GGML_CPU_FP16_TO_FP32(x[i].d);
4921        const float combined_scale = d * y[i].d;
4922
4923        const uint8_t * GGML_RESTRICT qs = x[i].qs;
4924        const uint8_t * GGML_RESTRICT qh = x[i].qh;
4925        const uint8_t * GGML_RESTRICT scales = x[i].scales;
4926        const uint8_t * GGML_RESTRICT signs = x[i].signs;
4927        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
4928
4929        float sum_block = 0.0f;
4930
4931        // Loop: Process 64 weights (16 mini-blocks of 4) per iteration
4932        for (int ib = 0; ib < 4; ++ib) {
4933
4934            vuint8mf2_t v_qs_u8 = __riscv_vle8_v_u8mf2(qs, 16);
4935            qs += 16;
4936
4937            uint16_t qh_val;
4938            memcpy(&qh_val, qh, 2);
4939            qh += 2;
4940
4941            vuint16m1_t v_qh_val = __riscv_vmv_v_x_u16m1(qh_val, 16);
4942            // Extract bits: (qh >> i) & 1
4943            v_qh_val = __riscv_vsrl_vv_u16m1(v_qh_val, v_qh_shifts, 16);
4944            v_qh_val = __riscv_vand_vx_u16m1(v_qh_val, 1, 16);
4945
4946            vuint16m1_t v_qs_u16 = __riscv_vwcvtu_x_x_v_u16m1(v_qs_u8, 16);
4947            v_qs_u16 = __riscv_vsll_vx_u16m1(v_qs_u16, 2, 16);
4948            v_qh_val = __riscv_vsll_vx_u16m1(v_qh_val, 10, 16);
4949            vuint16m1_t v_grid_offsets = __riscv_vor_vv_u16m1(v_qs_u16, v_qh_val, 16);
4950
4951            // Grid value is 4xuint8
4952            vuint32m2_t v_grid_packed = __riscv_vluxei16_v_u32m2((const uint32_t *)grid64, v_grid_offsets, 16);
4953            vuint8m2_t v_grid_u8 = __riscv_vreinterpret_v_u32m2_u8m2(v_grid_packed);
4954            vuint8mf4_t v_signs_raw = __riscv_vle8_v_u8mf4(signs, 8);
4955            signs += 8;
4956
4957            // Generate sign mask
4958            vuint8m2_t v_signs_source = __riscv_vlmul_ext_v_u8mf4_u8m2(v_signs_raw);
4959            vuint8m2_t v_signs_bcast = __riscv_vrgather_vv_u8m2(v_signs_source, v_sign_gather_indices, 64);
4960            vuint8m2_t v_sign_bits = __riscv_vand_vv_u8m2(v_signs_bcast, v_sign_masks, 64);
4961            vbool4_t m_negative = __riscv_vmsne_vx_u8m2_b4(v_sign_bits, 0, 64);
4962
4963            vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 64);
4964            q8 += 64;
4965
4966            // Apply Signs
4967            vint8m2_t v_q8_signed = __riscv_vrsub_vx_i8m2_mu(m_negative, v_q8, v_q8, 0, 64);
4968            vint16m4_t v_dot = __riscv_vwmulsu_vv_i16m4(v_q8_signed, v_grid_u8, 64);
4969
4970            // Reduction
4971            vint16m2_t v_dot_lo = __riscv_vget_v_i16m4_i16m2(v_dot, 0);
4972            vint16m2_t v_dot_hi = __riscv_vget_v_i16m4_i16m2(v_dot, 1);
4973            vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
4974
4975            int32_t s_lo = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(v_dot_lo, v_zero, 32));
4976            int32_t s_hi = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(v_dot_hi, v_zero, 32));
4977
4978            // Apply sub-scales
4979            uint8_t sc_byte = *scales++;
4980            int sc_lo = (sc_byte & 0xF) * 2 + 1;
4981            int sc_hi = (sc_byte >> 4)  * 2 + 1;
4982
4983            sum_block += s_lo * sc_lo + s_hi * sc_hi;
4984        }
4985        sumf += sum_block * combined_scale;
4986    }
4987    *s = sumf;
4988}
4989
4990static NOINLINE void ggml_vec_dot_iq3_s_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
4991    assert(n % QK_K == 0);
4992    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
4993    const block_iq3_s * GGML_RESTRICT x = vx;
4994    const block_q8_K  * GGML_RESTRICT y = vy;
4995
4996    const int nb = n / QK_K;
4997    const uint32_t * grid32 = (const uint32_t *)iq3s_grid;
4998
4999    // Generate Constants
5000    vuint8mf2_t v_id_32 = __riscv_vid_v_u8mf2(32);
5001    vuint8mf2_t v_qh_gather = __riscv_vsrl_vx_u8mf2(v_id_32, 3, 32);
5002    vuint8mf2_t v_qh_shifts = __riscv_vand_vx_u8mf2(v_id_32, 7, 32);
5003    vuint8m2_t v_id_128 = __riscv_vid_v_u8m2(128);
5004    vuint8m2_t v_sign_gather = __riscv_vsrl_vx_u8m2(v_id_128, 3, 128); // byte index
5005    vuint8m2_t v_sign_shift_amts = __riscv_vand_vx_u8m2(v_id_128, 7, 128); // bit shift
5006    vuint8m2_t v_one_128 = __riscv_vmv_v_x_u8m2(1, 128);
5007    vuint8m2_t v_sign_masks = __riscv_vsll_vv_u8m2(v_one_128, v_sign_shift_amts, 128);
5008    vuint8m2_t v_scale_indices = __riscv_vsrl_vx_u8m2(v_id_128, 5, 128);
5009
5010    float sumf = 0.0f;
5011
5012    for (int i = 0; i < nb; ++i) {
5013        const float combined_scale = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
5014
5015        const uint8_t * GGML_RESTRICT qs = x[i].qs;
5016        const uint8_t * GGML_RESTRICT qh = x[i].qh;
5017        const uint8_t * GGML_RESTRICT scales = x[i].scales;
5018        const uint8_t * GGML_RESTRICT signs = x[i].signs;
5019        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
5020
5021        float sum_block = 0.0f;
5022        for (int ib = 0; ib < 2; ++ib) {
5023            vuint8mf2_t v_qs_u8 = __riscv_vle8_v_u8mf2(qs, 32);
5024            qs += 32;
5025            vuint8mf2_t v_qh_loaded = __riscv_vle8_v_u8mf2(qh, 4);
5026            qh += 4;
5027            vuint8mf2_t v_qh_expanded = __riscv_vrgather_vv_u8mf2(v_qh_loaded, v_qh_gather, 32);
5028            v_qh_expanded = __riscv_vsrl_vv_u8mf2(v_qh_expanded, v_qh_shifts, 32);
5029            v_qh_expanded = __riscv_vand_vx_u8mf2(v_qh_expanded, 1, 32);
5030            vuint16m1_t v_qs_u16 = __riscv_vwcvtu_x_x_v_u16m1(v_qs_u8, 32);
5031            v_qs_u16 = __riscv_vsll_vx_u16m1(v_qs_u16, 2, 32); // * 4
5032
5033            vuint16m1_t v_qh_u16 = __riscv_vwcvtu_x_x_v_u16m1(v_qh_expanded, 32);
5034            v_qh_u16 = __riscv_vsll_vx_u16m1(v_qh_u16, 10, 32); // * 256 * 4
5035
5036            vuint16m1_t v_grid_offsets = __riscv_vor_vv_u16m1(v_qs_u16, v_qh_u16, 32);
5037            vuint32m2_t v_grid_packed = __riscv_vluxei16_v_u32m2(grid32, v_grid_offsets, 32);
5038            vuint8m2_t v_grid_u8 = __riscv_vreinterpret_v_u32m2_u8m2(v_grid_packed);
5039            vuint8mf2_t v_signs_raw = __riscv_vle8_v_u8mf2(signs, 16);
5040            signs += 16;
5041
5042            vuint8m2_t v_signs_source = __riscv_vlmul_ext_v_u8mf2_u8m2(v_signs_raw);
5043            vuint8m2_t v_signs_bcast = __riscv_vrgather_vv_u8m2(v_signs_source, v_sign_gather, 128);
5044            vuint8m2_t v_sign_bits = __riscv_vand_vv_u8m2(v_signs_bcast, v_sign_masks, 128);
5045            vbool4_t m_negative = __riscv_vmsne_vx_u8m2_b4(v_sign_bits, 0, 128);
5046
5047            vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 128);
5048            q8 += 128;
5049
5050            vint8m2_t v_q8_signed = __riscv_vrsub_vx_i8m2_mu(m_negative, v_q8, v_q8, 0, 128);
5051            vint16m4_t v_dot = __riscv_vwmulsu_vv_i16m4(v_q8_signed, v_grid_u8, 128);
5052            uint16_t sc_raw;
5053            memcpy(&sc_raw, scales, 2);
5054            scales += 2; // Advance 2 bytes
5055
5056            uint8_t sc_unpacked[4];
5057            sc_unpacked[0] = (sc_raw & 0xF);
5058            sc_unpacked[1] = (sc_raw >> 4) & 0xF;
5059            sc_unpacked[2] = (sc_raw >> 8) & 0xF;
5060            sc_unpacked[3] = (sc_raw >> 12) & 0xF;
5061
5062            vuint8mf2_t v_sc_4 = __riscv_vle8_v_u8mf2(sc_unpacked, 4);
5063            v_sc_4 = __riscv_vmul_vx_u8mf2(v_sc_4, 2, 4);
5064            v_sc_4 = __riscv_vadd_vx_u8mf2(v_sc_4, 1, 4);
5065            vuint8m2_t v_sc_4_expanded = __riscv_vlmul_ext_v_u8mf2_u8m2(v_sc_4);
5066            vuint8m2_t v_scales_bcast = __riscv_vrgather_vv_u8m2(v_sc_4_expanded, v_scale_indices, 128);
5067            vint16m4_t v_scales_i16 = __riscv_vreinterpret_v_u16m4_i16m4(__riscv_vwcvtu_x_x_v_u16m4(v_scales_bcast, 128));
5068            vint32m8_t v_weighted_sum = __riscv_vwmul_vv_i32m8(v_dot, v_scales_i16, 128);
5069            vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
5070            int32_t s_val = __riscv_vmv_x_s_i32m1_i32(__riscv_vredsum_vs_i32m8_i32m1(v_weighted_sum, v_zero, 128));
5071
5072            sum_block += s_val;
5073        }
5074        sumf += sum_block * combined_scale;
5075    }
5076    *s = sumf;
5077}
5078#endif
5079
5080void ggml_vec_dot_iq3_s_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5081#if defined __riscv_v
5082    switch (__riscv_vlenb() * 8) {
5083        case 128:
5084            ggml_vec_dot_iq3_s_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
5085            break;
5086        case 256:
5087            ggml_vec_dot_iq3_s_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
5088            break;
5089        default: // 512 and above
5090            ggml_vec_dot_iq3_s_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
5091            break;
5092    }
5093#else
5094    ggml_vec_dot_iq3_s_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
5095#endif
5096}
5097
5098#if defined __riscv_v
5099static NOINLINE void ggml_vec_dot_iq3_xxs_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5100    assert(n % QK_K == 0);
5101    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
5102
5103    const block_iq3_xxs * GGML_RESTRICT x = vx;
5104    const block_q8_K    * GGML_RESTRICT y = vy;
5105    const int nb = n / QK_K;
5106
5107    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
5108    const uint32_t * grid32  = (const uint32_t *)iq3xxs_grid;
5109
5110    // constants for unpacking logic
5111    const uint32_t shifts_val[8] = {0, 7, 14, 21, 0, 7, 14, 21};
5112    vuint32m2_t v_shifts = __riscv_vle32_v_u32m2(shifts_val, 8);
5113
5114    const uint32_t gather_idx_val[8] = {0, 0, 0, 0, 1, 1, 1, 1};
5115    vuint32m2_t v_gather_idx = __riscv_vle32_v_u32m2(gather_idx_val, 8);
5116
5117    uint32_t aux32[2];
5118    float sumf = 0.0f;
5119
5120    for (int i = 0; i < nb; ++i) {
5121        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
5122
5123        const uint8_t * GGML_RESTRICT q3_indices = x[i].qs;
5124        const uint8_t * GGML_RESTRICT metadata   = x[i].qs + QK_K/4;
5125        const int8_t  * GGML_RESTRICT q8         = y[i].qs;
5126
5127        float block_sum = 0.0f;
5128
5129        // Process 64 weights per loop
5130        for (int ib = 0; ib < QK_K / 64; ++ib) {
5131
5132            // load of metadata via memcpy
5133            memcpy(aux32, metadata, 2 * sizeof(uint32_t));
5134            metadata += 2 * sizeof(uint32_t);
5135
5136            vuint8m1_t v_q3_idx_u8 = __riscv_vle8_v_u8m1(q3_indices, 16);
5137            q3_indices += 16;
5138
5139            vuint16m2_t v_q3_idx_u16 = __riscv_vwmulu_vx_u16m2(v_q3_idx_u8, 4, 16);
5140
5141            vuint32m4_t v_q3_magnitudes_u32 = __riscv_vluxei16_v_u32m4(grid32, v_q3_idx_u16, 16);
5142
5143            vint8m4_t v_q3_magnitudes = __riscv_vreinterpret_v_u8m4_i8m4(
5144                                        __riscv_vreinterpret_v_u32m4_u8m4(v_q3_magnitudes_u32));
5145
5146            vuint32m2_t v_aux = __riscv_vle32_v_u32m2(aux32, 2);
5147
5148            vuint32m2_t v_aux_expanded = __riscv_vrgather_vv_u32m2(v_aux, v_gather_idx, 8);
5149
5150            vuint32m2_t v_s_vals_raw = __riscv_vand_vx_u32m2(
5151                                       __riscv_vsrl_vv_u32m2(v_aux_expanded, v_shifts, 8), 127, 8);
5152
5153            vuint16m1_t sign_indices_byte_offset = __riscv_vsll_vx_u16m1(
5154                                                   __riscv_vncvt_x_x_w_u16m1(v_s_vals_raw, 8), 3, 8);
5155
5156            vuint64m4_t v_s_vals_u64 = __riscv_vluxei16_v_u64m4(signs64, sign_indices_byte_offset, 8);
5157
5158            vint8m4_t v_s_vals = __riscv_vreinterpret_v_u8m4_i8m4(
5159                                 __riscv_vreinterpret_v_u64m4_u8m4(v_s_vals_u64));
5160
5161            vint8m4_t v_q3_signed = __riscv_vmul_vv_i8m4(v_q3_magnitudes, v_s_vals, 64);
5162            asm volatile("" ::: "memory");
5163            vint8m4_t v_q8 = __riscv_vle8_v_i8m4(q8, 64);
5164            q8 += 64;
5165
5166            vint16m8_t v_dot = __riscv_vwmul_vv_i16m8(v_q8, v_q3_signed, 64);
5167
5168            asm volatile("" ::: "memory");
5169
5170            vint16m4_t v_dot_1 = __riscv_vget_v_i16m8_i16m4(v_dot, 0);
5171            vint16m4_t v_dot_2 = __riscv_vget_v_i16m8_i16m4(v_dot, 1);
5172
5173            vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
5174
5175            vint32m1_t v_sum_1 = __riscv_vwredsum_vs_i16m4_i32m1(v_dot_1, v_zero, 32);
5176            vint32m1_t v_sum_2 = __riscv_vwredsum_vs_i16m4_i32m1(v_dot_2, v_zero, 32);
5177
5178            int32_t sum1_i = __riscv_vmv_x_s_i32m1_i32(v_sum_1);
5179            int32_t sum2_i = __riscv_vmv_x_s_i32m1_i32(v_sum_2);
5180
5181            const float scale1_f = (float)(2 * (aux32[0] >> 28) + 1);
5182            const float scale2_f = (float)(2 * (aux32[1] >> 28) + 1);
5183
5184            block_sum += sum1_i * scale1_f + sum2_i * scale2_f;
5185        }
5186
5187        sumf += d * block_sum;
5188    }
5189    *s = 0.25f * sumf;
5190}
5191
5192static NOINLINE void ggml_vec_dot_iq3_xxs_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5193    assert(n % QK_K == 0);
5194    assert(nrc == 1);
5195    UNUSED(nrc);
5196    UNUSED(bx);
5197    UNUSED(by);
5198    UNUSED(bs);
5199
5200    const block_iq3_xxs * GGML_RESTRICT x = vx;
5201    const block_q8_K    * GGML_RESTRICT y = vy;
5202    const int nb = n / QK_K;
5203
5204    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
5205    const uint32_t * grid32  = (const uint32_t *)iq3xxs_grid;
5206
5207    // constants for unpacking logic
5208    const uint32_t shifts_val[8] = {0, 7, 14, 21, 0, 7, 14, 21};
5209    vuint32m1_t v_shifts = __riscv_vle32_v_u32m1(shifts_val, 8);
5210
5211    const uint32_t gather_idx_val[8] = {0, 0, 0, 0, 1, 1, 1, 1};
5212    vuint32m1_t v_gather_idx = __riscv_vle32_v_u32m1(gather_idx_val, 8);
5213
5214    uint32_t aux32[2];
5215    float sumf = 0.0f;
5216
5217    for (int i = 0; i < nb; ++i) {
5218        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
5219
5220        const uint8_t * GGML_RESTRICT q3_indices = x[i].qs;
5221        const uint8_t * GGML_RESTRICT metadata   = x[i].qs + QK_K/4;
5222        const int8_t  * GGML_RESTRICT q8         = y[i].qs;
5223
5224        float block_sum = 0.0f;
5225
5226        for (int ib = 0; ib < QK_K / 64; ++ib) {
5227            // Load q8 (64 bytes)
5228            vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 64);
5229            q8 += 64;
5230
5231            // load of metadata via memcpy
5232            memcpy(aux32, metadata, 2 * sizeof(uint32_t));
5233            metadata += 2 * sizeof(uint32_t);
5234
5235            // Load q3 indices and gather magnitudes
5236            vuint8mf2_t v_q3_idx_u8 = __riscv_vle8_v_u8mf2(q3_indices, 16);
5237            q3_indices += 16;
5238
5239            vuint16m1_t v_q3_idx_u16 = __riscv_vwmulu_vx_u16m1(v_q3_idx_u8, 4, 16);
5240            vuint32m2_t v_q3_magnitudes_u32 = __riscv_vluxei16_v_u32m2(grid32, v_q3_idx_u16, 16);
5241            vint8m2_t v_q3_magnitudes = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vreinterpret_v_u32m2_u8m2(v_q3_magnitudes_u32));
5242
5243            // --- Unpacking of Sign Indices ---
5244
5245            // 1. Load the 2 auxiliary 32-bit integers into a vector
5246            vuint32m1_t v_aux = __riscv_vle32_v_u32m1(aux32, 2);
5247
5248            // 2. Broadcast/Gather: replicate aux[0] to first 4 lanes, aux[1] to next 4 lanes
5249            vuint32m1_t v_aux_expanded = __riscv_vrgather_vv_u32m1(v_aux, v_gather_idx, 8);
5250
5251            // 3. Apply Shifts and Mask: ((val >> shift) & 127)
5252            vuint32m1_t v_s_vals_raw = __riscv_vand_vx_u32m1(__riscv_vsrl_vv_u32m1(v_aux_expanded, v_shifts, 8), 127, 8);
5253
5254            // 4. Narrow to u16 (required for vluxei index) and multiply by 8 (byte offset for u64 table)
5255            vuint16mf2_t sign_indices_byte_offset = __riscv_vsll_vx_u16mf2(__riscv_vncvt_x_x_w_u16mf2(v_s_vals_raw, 8), 3, 8);
5256
5257            // 5. Gather Signs
5258            vuint64m2_t v_s_vals_u64 = __riscv_vluxei16_v_u64m2(signs64, sign_indices_byte_offset, 8);
5259            vint8m2_t v_s_vals = __riscv_vreinterpret_v_u8m2_i8m2(__riscv_vreinterpret_v_u64m2_u8m2(v_s_vals_u64));
5260
5261            vint8m2_t v_q3_signed = __riscv_vmul_vv_i8m2(v_q3_magnitudes, v_s_vals, 64);
5262            vint16m4_t v_dot = __riscv_vwmul_vv_i16m4(v_q8, v_q3_signed, 64);
5263
5264            vint16m2_t v_dot_1 = __riscv_vget_v_i16m4_i16m2(v_dot, 0);
5265            vint16m2_t v_dot_2 = __riscv_vget_v_i16m4_i16m2(v_dot, 1);
5266
5267            vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
5268            vint32m1_t v_sum_1 = __riscv_vwredsum_vs_i16m2_i32m1(v_dot_1, v_zero, 32);
5269            vint32m1_t v_sum_2 = __riscv_vwredsum_vs_i16m2_i32m1(v_dot_2, v_zero, 32);
5270
5271            int32_t sum1_i = __riscv_vmv_x_s_i32m1_i32(v_sum_1);
5272            int32_t sum2_i = __riscv_vmv_x_s_i32m1_i32(v_sum_2);
5273
5274            const float scale1_f = (float)(2 * (aux32[0] >> 28) + 1);
5275            const float scale2_f = (float)(2 * (aux32[1] >> 28) + 1);
5276
5277            block_sum += sum1_i * scale1_f + sum2_i * scale2_f;
5278        }
5279
5280        sumf += d * block_sum;
5281    }
5282    *s = 0.25f * sumf;
5283}
5284
5285static NOINLINE void ggml_vec_dot_iq3_xxs_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5286    assert(n % QK_K == 0);
5287    assert(nrc == 1);
5288    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
5289    const block_iq3_xxs * GGML_RESTRICT x = vx;
5290    const block_q8_K    * GGML_RESTRICT y = vy;
5291    const int nb = n / QK_K;
5292
5293    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
5294    const uint32_t * grid32  = (const uint32_t *)iq3xxs_grid;
5295
5296    // generate constants for unpacking metadata words into sign indices
5297    vuint32m1_t v_shifts;
5298    {
5299        vuint32m1_t v_base = __riscv_vid_v_u32m1(16);
5300        vuint32m1_t v_mod4 = __riscv_vand_vx_u32m1(v_base, 3, 16);
5301        v_shifts = __riscv_vmul_vx_u32m1(v_mod4, 7, 16);
5302    }
5303
5304    vuint16mf2_t v_gather_idx;
5305    {
5306        vuint16mf2_t v_idx = __riscv_vid_v_u16mf2(16);
5307        v_gather_idx = __riscv_vsrl_vx_u16mf2(v_idx, 2, 16);
5308    }
5309
5310    float sumf = 0.0f;
5311
5312    for (int i = 0; i < nb; ++i) {
5313        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
5314
5315        const uint8_t * GGML_RESTRICT q3_indices = x[i].qs;
5316        const uint8_t * GGML_RESTRICT metadata   = x[i].qs + QK_K/4;
5317        const int8_t  * GGML_RESTRICT q8         = y[i].qs;
5318
5319        float block_sum = 0.0f;
5320        for (int ib128 = 0; ib128 < 2; ++ib128) {
5321
5322            vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 128);
5323            q8 += 128;
5324            vuint8mf2_t v_q3_idx_u8 = __riscv_vle8_v_u8mf2(q3_indices, 32);
5325            q3_indices += 32;
5326
5327            vuint16m1_t v_q3_idx_u16 = __riscv_vwmulu_vx_u16m1(v_q3_idx_u8, 4, 32);
5328            vuint32m2_t v_q3_mag_u32 = __riscv_vluxei16_v_u32m2(grid32, v_q3_idx_u16, 32);
5329            vint8m2_t v_q3_magnitudes = __riscv_vreinterpret_v_u8m2_i8m2(
5330            __riscv_vreinterpret_v_u32m2_u8m2(v_q3_mag_u32));
5331            vuint32m1_t v_aux = __riscv_vreinterpret_v_u8m1_u32m1(__riscv_vle8_v_u8m1(metadata, 16));
5332            metadata += 4 * sizeof(uint32_t);
5333
5334            vuint32m1_t v_aux_expanded = __riscv_vrgatherei16_vv_u32m1(v_aux, v_gather_idx, 16);
5335
5336            vuint32m1_t v_s_raw = __riscv_vand_vx_u32m1(
5337                __riscv_vsrl_vv_u32m1(v_aux_expanded, v_shifts, 16), 127, 16);
5338            vuint16mf2_t sign_byte_offset = __riscv_vsll_vx_u16mf2(
5339                __riscv_vncvt_x_x_w_u16mf2(v_s_raw, 16), 3, 16);
5340            vuint64m2_t v_s_u64 = __riscv_vluxei16_v_u64m2(signs64, sign_byte_offset, 16);
5341            vint8m2_t v_signs = __riscv_vreinterpret_v_u8m2_i8m2(
5342                __riscv_vreinterpret_v_u64m2_u8m2(v_s_u64));
5343            vint8m2_t v_q3_signed = __riscv_vmul_vv_i8m2(v_q3_magnitudes, v_signs, 128);
5344            vint16m4_t prod = __riscv_vwmul_vv_i16m4(v_q3_signed, v_q8, 128);
5345
5346            vint32m1_t zero_vec = __riscv_vmv_v_x_i32m1(0, 1);
5347            int32_t group0_sum = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
5348                         __riscv_vget_v_i16m4_i16m1(prod, 0), zero_vec, 32));
5349            int32_t group1_sum = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
5350                         __riscv_vget_v_i16m4_i16m1(prod, 1), zero_vec, 32));
5351            int32_t group2_sum = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
5352                         __riscv_vget_v_i16m4_i16m1(prod, 2), zero_vec, 32));
5353            int32_t group3_sum = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(
5354                         __riscv_vget_v_i16m4_i16m1(prod, 3), zero_vec, 32));
5355
5356            vuint32m1_t v_scales_raw = __riscv_vsrl_vx_u32m1(v_aux, 28, 4);
5357            vuint32m1_t v_scales = __riscv_vadd_vx_u32m1(
5358                                        __riscv_vsll_vx_u32m1(v_scales_raw, 1, 4),
5359                                        1, 4);
5360            int32_t scale0 = (int32_t)__riscv_vmv_x_s_u32m1_u32(v_scales);
5361            int32_t scale1 = (int32_t)__riscv_vmv_x_s_u32m1_u32(__riscv_vslidedown_vx_u32m1(v_scales, 1, 4));
5362            int32_t scale2 = (int32_t)__riscv_vmv_x_s_u32m1_u32(__riscv_vslidedown_vx_u32m1(v_scales, 2, 4));
5363            int32_t scale3 = (int32_t)__riscv_vmv_x_s_u32m1_u32(__riscv_vslidedown_vx_u32m1(v_scales, 3, 4));
5364
5365            block_sum += (float)(group0_sum * scale0 + group1_sum * scale1 +
5366                                 group2_sum * scale2 + group3_sum * scale3);
5367        }
5368
5369        sumf += d * block_sum;
5370    }
5371    *s = 0.25f * sumf;
5372}
5373
5374static NOINLINE void ggml_vec_dot_iq3_xxs_q8_K_vl1024(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5375    assert(n % QK_K == 0);
5376    assert(nrc == 1);
5377    UNUSED(nrc); UNUSED(bx); UNUSED(by); UNUSED(bs);
5378
5379    const block_iq3_xxs * GGML_RESTRICT x = vx;
5380    const block_q8_K    * GGML_RESTRICT y = vy;
5381    const int nb = n / QK_K;
5382
5383    const uint64_t * signs64 = (const uint64_t *)keven_signs_q2xs;
5384    const uint32_t * grid32  = (const uint32_t *)iq3xxs_grid;
5385
5386    vuint32m1_t v_shifts;
5387    {
5388        vuint32m1_t v_id   = __riscv_vid_v_u32m1(32);
5389        vuint32m1_t v_mod4 = __riscv_vand_vx_u32m1(v_id, 3, 32);
5390        v_shifts           = __riscv_vmul_vx_u32m1(v_mod4, 7, 32);
5391    }
5392    vuint16mf2_t v_gather_idx;
5393    {
5394        vuint16mf2_t v_id_16 = __riscv_vid_v_u16mf2(32);
5395        v_gather_idx         = __riscv_vsrl_vx_u16mf2(v_id_16, 2, 32);
5396    }
5397
5398    float sumf = 0.0f;
5399    uint32_t aux32[8]; // Buffer for block metadata
5400
5401    for (int i = 0; i < nb; ++i) {
5402        const float d = GGML_CPU_FP16_TO_FP32(x[i].d) * y[i].d;
5403
5404        const uint8_t * GGML_RESTRICT q3_indices = x[i].qs;
5405        const uint8_t * GGML_RESTRICT metadata   = x[i].qs + QK_K/4;
5406        const int8_t  * GGML_RESTRICT q8         = y[i].qs;
5407
5408        vint8m2_t v_q8 = __riscv_vle8_v_i8m2(q8, 256);
5409        vuint8mf2_t v_q3_idx_raw = __riscv_vle8_v_u8mf2(q3_indices, 64);
5410        vuint16m1_t v_q3_idx_u16 = __riscv_vwmulu_vx_u16m1(v_q3_idx_raw, 4, 64);
5411
5412        vuint32m2_t v_q3_grid_vals = __riscv_vluxei16_v_u32m2(grid32, v_q3_idx_u16, 64);
5413
5414        vint8m2_t v_q3_mags = __riscv_vreinterpret_v_u8m2_i8m2(
5415                              __riscv_vreinterpret_v_u32m2_u8m2(v_q3_grid_vals));
5416
5417        memcpy(aux32, metadata, 8 * sizeof(uint32_t));
5418        vuint32m1_t v_aux_8 = __riscv_vle32_v_u32m1(aux32, 8);
5419
5420        vuint32m1_t v_aux_32 = __riscv_vrgatherei16_vv_u32m1(v_aux_8, v_gather_idx, 32);
5421
5422        vuint32m1_t v_sign_idx_raw = __riscv_vand_vx_u32m1(
5423                                     __riscv_vsrl_vv_u32m1(v_aux_32, v_shifts, 32), 127, 32);
5424
5425        vuint16mf2_t v_sign_offsets = __riscv_vsll_vx_u16mf2(
5426                                      __riscv_vncvt_x_x_w_u16mf2(v_sign_idx_raw, 32), 3, 32);
5427
5428        vuint64m2_t v_signs_u64 = __riscv_vluxei16_v_u64m2(signs64, v_sign_offsets, 32);
5429
5430        vint8m2_t v_signs = __riscv_vreinterpret_v_u8m2_i8m2(
5431                            __riscv_vreinterpret_v_u64m2_u8m2(v_signs_u64));
5432
5433        vint8m2_t v_q3_final = __riscv_vmul_vv_i8m2(v_q3_mags, v_signs, 256);
5434
5435        vint16m4_t v_dot = __riscv_vwmul_vv_i16m4(v_q8, v_q3_final, 256);
5436        float block_sum = 0.0f;
5437        vint32m1_t v_zero = __riscv_vmv_v_x_i32m1(0, 1);
5438        vint16m4_t v_accum = v_dot;
5439
5440        for (int j = 0; j < 8; ++j) {
5441            float scale = (float)(2 * (aux32[j] >> 28) + 1);
5442
5443            vint32m1_t v_partial_sum = __riscv_vwredsum_vs_i16m4_i32m1(v_accum, v_zero, 32);
5444
5445            int32_t partial_sum_i = __riscv_vmv_x_s_i32m1_i32(v_partial_sum);
5446            block_sum += partial_sum_i * scale;
5447            v_accum = __riscv_vslidedown_vx_i16m4(v_accum, 32, 32);
5448
5449        }
5450
5451        sumf += d * block_sum;
5452    }
5453    *s = 0.25f * sumf;
5454}
5455#endif
5456
5457void ggml_vec_dot_iq3_xxs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5458#if defined __riscv_v
5459    switch (__riscv_vlenb() * 8) {
5460        case 128:
5461            ggml_vec_dot_iq3_xxs_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
5462            break;
5463        case 256:
5464            ggml_vec_dot_iq3_xxs_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
5465            break;
5466        case 512:
5467            ggml_vec_dot_iq3_xxs_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
5468            break;
5469        default: // 1024 and above
5470            ggml_vec_dot_iq3_xxs_q8_K_vl1024(n, s, bs, vx, bx, vy, by, nrc);
5471            break;
5472    }
5473#else
5474    ggml_vec_dot_iq3_xxs_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
5475#endif
5476}
5477
5478#if defined __riscv_v
5479static NOINLINE void ggml_vec_dot_iq4_nl_q8_0_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5480    assert(nrc == 1);
5481    UNUSED(nrc);
5482    UNUSED(bx);
5483    UNUSED(by);
5484    UNUSED(bs);
5485    assert(n % QK4_NL == 0);
5486    static_assert(QK4_NL == QK8_0, "QK4_NL and QK8_0 must be the same");
5487
5488    const block_iq4_nl * GGML_RESTRICT x = vx;
5489    const block_q8_0   * GGML_RESTRICT y = vy;
5490
5491    const int nb = n / QK4_NL;
5492
5493    int ib = 0;
5494    float sumf = 0;
5495
5496    // Load the lookup table once.
5497    const vint8m2_t values = __riscv_vle8_v_i8m2(kvalues_iq4nl, 16);
5498    int acc1, acc2;
5499
5500    // We process 2 blocks at once.
5501    for (; ib + 1 < nb; ib += 2) {
5502        // Weights and activations.
5503        vuint8m1_t iq4_packed1 = __riscv_vle8_v_u8m1(x[ib + 0].qs, 16);
5504        vint8m2_t q8b1 = __riscv_vle8_v_i8m2(y[ib + 0].qs, 32);
5505        vuint8m1_t iq4_packed2 = __riscv_vle8_v_u8m1(x[ib + 1].qs, 16);
5506        vint8m2_t q8b2 = __riscv_vle8_v_i8m2(y[ib + 1].qs, 32);
5507
5508        // Unpack the weight blocks.
5509        vuint8m2_t iq4bits1 = __riscv_vcreate_v_u8m1_u8m2(
5510            __riscv_vand_vx_u8m1(iq4_packed1, 0xf, 16),
5511            __riscv_vsrl_vx_u8m1(iq4_packed1, 4, 16)
5512        );
5513        vuint8m2_t iq4bits2 = __riscv_vcreate_v_u8m1_u8m2(
5514            __riscv_vand_vx_u8m1(iq4_packed2, 0xf, 16),
5515            __riscv_vsrl_vx_u8m1(iq4_packed2, 4, 16)
5516        );
5517
5518        // Gather values from the lookup table.
5519        vint8m2_t iq4b1 = __riscv_vrgather_vv_i8m2(values, iq4bits1, 32);
5520        vint8m2_t iq4b2 = __riscv_vrgather_vv_i8m2(values, iq4bits2, 32);
5521
5522        // Accumulation.
5523        vint16m4_t sum1 = __riscv_vwmul_vv_i16m4(q8b1, iq4b1, 32);
5524        vint16m4_t sum2 = __riscv_vwmul_vv_i16m4(q8b2, iq4b2, 32);
5525        __riscv_vse32_v_i32m1(&acc1,__riscv_vwredsum_vs_i16m4_i32m1(sum1, __riscv_vmv_v_x_i32m1(0, 1), 32), 1);
5526        __riscv_vse32_v_i32m1(&acc2,__riscv_vwredsum_vs_i16m4_i32m1(sum2, __riscv_vmv_v_x_i32m1(0, 1), 32), 1);
5527        sumf += ((GGML_CPU_FP16_TO_FP32(x[ib + 0].d) * GGML_CPU_FP16_TO_FP32(y[ib + 0].d) * acc1));
5528        sumf += ((GGML_CPU_FP16_TO_FP32(x[ib + 1].d) * GGML_CPU_FP16_TO_FP32(y[ib + 1].d) * acc2));
5529    }
5530
5531    *s = sumf;
5532}
5533
5534static NOINLINE void ggml_vec_dot_iq4_nl_q8_0_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5535    assert(nrc == 1);
5536    UNUSED(nrc);
5537    UNUSED(bx);
5538    UNUSED(by);
5539    UNUSED(bs);
5540    assert(n % QK4_NL == 0);
5541    static_assert(QK4_NL == QK8_0, "QK4_NL and QK8_0 must be the same");
5542
5543    const block_iq4_nl * GGML_RESTRICT x = vx;
5544    const block_q8_0   * GGML_RESTRICT y = vy;
5545
5546    const int nb = n / QK4_NL;
5547
5548    int ib = 0;
5549    float sumf = 0;
5550
5551    // Load the lookup table once.
5552    const vint8mf2_t values = __riscv_vle8_v_i8mf2(kvalues_iq4nl, 16);
5553    int acc1, acc2;
5554
5555    // We process 2 blocks at once.
5556    for (; ib + 1 < nb; ib += 2) {
5557        // Weights and activations.
5558        vuint8mf2_t iq4_packed1 = __riscv_vle8_v_u8mf2(x[ib + 0].qs, 16);
5559        vint8mf2_t q8b_lo1 = __riscv_vle8_v_i8mf2(y[ib + 0].qs, 16);
5560        vint8mf2_t q8b_hi1 = __riscv_vle8_v_i8mf2(y[ib + 0].qs + 16, 16);
5561        vuint8mf2_t iq4_packed2 = __riscv_vle8_v_u8mf2(x[ib + 1].qs, 16);
5562        vint8mf2_t q8b_lo2 = __riscv_vle8_v_i8mf2(y[ib + 1].qs, 16);
5563        vint8mf2_t q8b_hi2 = __riscv_vle8_v_i8mf2(y[ib + 1].qs + 16, 16);
5564
5565        // Unpack the weight blocks.
5566        vuint8mf2_t iq4bits_lo1 = __riscv_vand_vx_u8mf2(iq4_packed1, 0xf, 16);
5567        vuint8mf2_t iq4bits_hi1 = __riscv_vsrl_vx_u8mf2(iq4_packed1, 4, 16);
5568        vuint8mf2_t iq4bits_lo2 = __riscv_vand_vx_u8mf2(iq4_packed2, 0xf, 16);
5569        vuint8mf2_t iq4bits_hi2 = __riscv_vsrl_vx_u8mf2(iq4_packed2, 4, 16);
5570
5571        // Gather values from the lookup table.
5572        vint8mf2_t iq4b_lo1 = __riscv_vrgather_vv_i8mf2(values, iq4bits_lo1, 16);
5573        vint8mf2_t iq4b_hi1 = __riscv_vrgather_vv_i8mf2(values, iq4bits_hi1, 16);
5574        vint8mf2_t iq4b_lo2 = __riscv_vrgather_vv_i8mf2(values, iq4bits_lo2, 16);
5575        vint8mf2_t iq4b_hi2 = __riscv_vrgather_vv_i8mf2(values, iq4bits_hi2, 16);
5576
5577        // Accumulation.
5578        vint16m1_t sum1 = __riscv_vwmul_vv_i16m1(q8b_lo1, iq4b_lo1, 16);
5579        sum1 = __riscv_vwmacc_vv_i16m1(sum1, q8b_hi1, iq4b_hi1, 16);
5580        vint16m1_t sum2 = __riscv_vwmul_vv_i16m1(q8b_lo2, iq4b_lo2, 16);
5581        sum2 = __riscv_vwmacc_vv_i16m1(sum2, q8b_hi2, iq4b_hi2, 16);
5582        __riscv_vse32_v_i32m1(&acc1,__riscv_vwredsum_vs_i16m1_i32m1(sum1, __riscv_vmv_v_x_i32m1(0, 1), 16), 1);
5583        __riscv_vse32_v_i32m1(&acc2,__riscv_vwredsum_vs_i16m1_i32m1(sum2, __riscv_vmv_v_x_i32m1(0, 1), 16), 1);
5584        sumf += ((GGML_CPU_FP16_TO_FP32(x[ib + 0].d) * GGML_CPU_FP16_TO_FP32(y[ib + 0].d) * acc1));
5585        sumf += ((GGML_CPU_FP16_TO_FP32(x[ib + 1].d) * GGML_CPU_FP16_TO_FP32(y[ib + 1].d) * acc2));
5586    }
5587
5588    *s = sumf;
5589}
5590#endif
5591
5592void ggml_vec_dot_iq4_nl_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5593#if defined __riscv_v
5594    switch (__riscv_vlenb() * 8) {
5595        case 128:
5596            ggml_vec_dot_iq4_nl_q8_0_vl128(n, s, bs, vx, bx, vy, by, nrc);
5597            break;
5598        default: // 256 and above
5599            ggml_vec_dot_iq4_nl_q8_0_vl256(n, s, bs, vx, bx, vy, by, nrc);
5600            break;
5601    }
5602#else
5603    ggml_vec_dot_iq4_nl_q8_0_generic(n, s, bs, vx, bx, vy, by, nrc);
5604#endif
5605}
5606
5607#if defined __riscv_v
5608static NOINLINE void ggml_vec_dot_iq4_xs_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5609    assert(nrc == 1);
5610    UNUSED(nrc);
5611    UNUSED(bx);
5612    UNUSED(by);
5613    UNUSED(bs);
5614    assert(n % QK_K == 0);
5615
5616    const block_iq4_xs * GGML_RESTRICT x = vx;
5617    const block_q8_K   * GGML_RESTRICT y = vy;
5618
5619    const int nb = n / QK_K;
5620
5621    const vint8m4_t values = __riscv_vle8_v_i8m4(kvalues_iq4nl, 16);
5622    float sumf = 0;
5623
5624    for (int ibl = 0; ibl < nb; ++ibl) {
5625        const int8_t  * q8 = y[ibl].qs;
5626        const uint8_t * iq4 = x[ibl].qs;
5627        uint16_t h = x[ibl].scales_h;
5628
5629        // We process 2 sub-blocks together.
5630        int sumi1 = 0, sumi2 = 0;
5631        #pragma GCC unroll 1
5632        for (int ib = 0; ib < QK_K / 64; ++ib) {
5633            // Load the packed weights.
5634            const vuint8m2_t iq4_packed = __riscv_vle8_v_u8m2(iq4, 32);
5635            iq4 += 32;
5636
5637            // Unpack the weight blocks.
5638            const vuint8m2_t iq4bits_lo = __riscv_vand_vx_u8m2(iq4_packed, 0xf, 32);
5639            const vuint8m2_t iq4bits_hi = __riscv_vsrl_vx_u8m2(iq4_packed, 4, 32);
5640            const vuint8m4_t iq4bits = __riscv_vcreate_v_u8m2_u8m4(iq4bits_lo, iq4bits_hi);
5641            const vuint8m4_t iq4bits_reorder = __riscv_vcreate_v_u8m1_u8m4(
5642                __riscv_vmv_v_v_u8m1(__riscv_vget_v_u8m4_u8m1(iq4bits, 0), 16),
5643                __riscv_vmv_v_v_u8m1(__riscv_vget_v_u8m4_u8m1(iq4bits, 2), 16),
5644                __riscv_vmv_v_v_u8m1(__riscv_vget_v_u8m4_u8m1(iq4bits, 1), 16),
5645                __riscv_vmv_v_v_u8m1(__riscv_vget_v_u8m4_u8m1(iq4bits, 3), 16)
5646            );
5647            const vint8m4_t iq4b = __riscv_vrgather_vv_i8m4(values, iq4bits_reorder, 64);
5648
5649            // Multiply with activations.
5650            const vint8m4_t q8b = __riscv_vle8_v_i8m4(q8, 64);
5651            q8 += 64;
5652            const vint16m8_t prod = __riscv_vwmul_vv_i16m8(iq4b, q8b, 64);
5653
5654            // Reduce separately.
5655            const int acc0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(prod, 0), __riscv_vmv_v_x_i32m1(0, 1), 32));
5656            const int acc1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m4_i32m1(__riscv_vget_v_i16m8_i16m4(prod, 1), __riscv_vmv_v_x_i32m1(0, 1), 32));
5657
5658            const int ls1 = ((x[ibl].scales_l[ib] & 0xf)  | ((h << 4) & 0x30)) - 32;
5659            const int ls2 = ((x[ibl].scales_l[ib] >>  4)  | ((h << 2) & 0x30)) - 32;
5660            h >>= 4;
5661
5662            sumi1 += acc0 * ls1;
5663            sumi2 += acc1 * ls2;
5664
5665            __asm__ __volatile__("" ::: "memory");
5666        }
5667
5668        sumf += GGML_CPU_FP16_TO_FP32(x[ibl].d) * y[ibl].d * (sumi1 + sumi2);
5669    }
5670
5671    *s = sumf;
5672}
5673
5674static NOINLINE void ggml_vec_dot_iq4_xs_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5675    assert(nrc == 1);
5676    UNUSED(nrc);
5677    UNUSED(bx);
5678    UNUSED(by);
5679    UNUSED(bs);
5680    assert(n % QK_K == 0);
5681
5682    const block_iq4_xs * GGML_RESTRICT x = vx;
5683    const block_q8_K   * GGML_RESTRICT y = vy;
5684
5685    const int nb = n / QK_K;
5686
5687    const vint8m4_t values = __riscv_vle8_v_i8m4(kvalues_iq4nl, 16);
5688    float sumf = 0;
5689
5690    // Indices for re-ordering IQ4 data.
5691    uint16_t index[16] = {
5692        0, 1, 8, 9,
5693        2, 3, 10, 11,
5694        4, 5,12, 13,
5695        6, 7, 14, 15,
5696    };
5697    vuint16m1_t i_vec = __riscv_vle16_v_u16m1(index, 16);
5698
5699    for (int ibl = 0; ibl < nb; ++ibl) {
5700        const int8_t  * q8 = y[ibl].qs;
5701        const uint8_t * iq4 = x[ibl].qs;
5702        uint16_t h = x[ibl].scales_h;
5703
5704        int sumi1 = 0, sumi2 = 0, sumi3 = 0, sumi4 = 0;
5705
5706        #pragma GCC unroll 1
5707        for (int ib = 0; ib < QK_K / 128; ++ib) {
5708            // Weights and activations.
5709            vuint8m2_t iq4_packed = __riscv_vle8_v_u8m2(iq4, 64);
5710            iq4 += 64;
5711
5712            // Unpack the weight blocks.
5713            vuint8m2_t iq4bits_lo = __riscv_vand_vx_u8m2(iq4_packed, 0xf, 64);
5714            vuint8m2_t iq4bits_hi = __riscv_vsrl_vx_u8m2(iq4_packed, 4, 64);
5715            vuint8m4_t iq4bits = __riscv_vcreate_v_u8m2_u8m4(iq4bits_lo, iq4bits_hi);
5716            vuint8m4_t iq4bits_reorder = __riscv_vreinterpret_v_u64m4_u8m4(__riscv_vrgatherei16_vv_u64m4(__riscv_vreinterpret_v_u8m4_u64m4(iq4bits), i_vec, 16));
5717            vint8m4_t iq4b = __riscv_vrgather_vv_i8m4(values, iq4bits_reorder, 128);
5718
5719            __asm__ __volatile__("" ::: "memory");
5720
5721            // Multiply with activations.
5722            vint8m4_t q8b = __riscv_vle8_v_i8m4(q8, 128);
5723            vint16m8_t prod = __riscv_vwmul_vv_i16m8(iq4b, q8b, 128);
5724            q8 += 128;
5725
5726            __asm__ __volatile__("" ::: "memory");
5727
5728            // Reduce separately.
5729            int acc0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(prod, 0), __riscv_vmv_v_x_i32m1(0, 1), 32));
5730            int acc1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(prod, 1), __riscv_vmv_v_x_i32m1(0, 1), 32));
5731            int acc2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(prod, 2), __riscv_vmv_v_x_i32m1(0, 1), 32));
5732            int acc3 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m2_i32m1(__riscv_vget_v_i16m8_i16m2(prod, 3), __riscv_vmv_v_x_i32m1(0, 1), 32));
5733
5734            int ls1 = ((x[ibl].scales_l[ib * 2 + 0] & 0xf)  | ((h << 4) & 0x30)) - 32;
5735            int ls2 = ((x[ibl].scales_l[ib * 2 + 0] >>  4)  | ((h << 2) & 0x30)) - 32;
5736            int ls3 = ((x[ibl].scales_l[ib * 2 + 1] &  0xf) | ((h << 0) & 0x30)) - 32;
5737            int ls4 = ((x[ibl].scales_l[ib * 2 + 1] >>  4)  | ((h >> 2) & 0x30)) - 32;
5738            h >>= 8;
5739
5740            sumi1 += acc0 * ls1;
5741            sumi2 += acc1 * ls2;
5742            sumi3 += acc2 * ls3;
5743            sumi4 += acc3 * ls4;
5744
5745            __asm__ __volatile__("" ::: "memory");
5746        }
5747
5748        sumf += GGML_CPU_FP16_TO_FP32(x[ibl].d) * y[ibl].d * (sumi1 + sumi2 + sumi3 + sumi4);
5749    }
5750
5751    *s = sumf;
5752}
5753
5754static NOINLINE void ggml_vec_dot_iq4_xs_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5755    assert(nrc == 1);
5756    UNUSED(nrc);
5757    UNUSED(bx);
5758    UNUSED(by);
5759    UNUSED(bs);
5760    assert(n % QK_K == 0);
5761
5762    const block_iq4_xs * GGML_RESTRICT x = vx;
5763    const block_q8_K   * GGML_RESTRICT y = vy;
5764
5765    const int nb = n / QK_K;
5766
5767    const vint8m4_t values = __riscv_vle8_v_i8m4(kvalues_iq4nl, 16);
5768    float sumf = 0;
5769
5770    // Indices for re-ordering IQ4 data.
5771    const uint16_t index[32] = {
5772        0, 1, 16, 17,
5773        2, 3, 18, 19,
5774        4, 5,20, 21,
5775        6, 7, 22, 23,
5776        8, 9, 24, 25,
5777        10, 11, 26, 27,
5778        12, 13,28, 29,
5779        14, 15, 30, 31,
5780    };
5781    const vuint16m1_t i_vec = __riscv_vle16_v_u16m1(index, 32);
5782
5783    for (int ibl = 0; ibl < nb; ++ibl) {
5784        const int8_t  * q8 = y[ibl].qs;
5785        const uint8_t * iq4 = x[ibl].qs;
5786        uint16_t h = x[ibl].scales_h;
5787
5788        int sumi = 0;
5789
5790        #pragma GCC unroll 1
5791        // Process the entire super-block together.
5792        for (int ib = 0; ib < QK_K / 256; ++ib) {
5793            // Weights and activations.
5794            const vuint8m2_t iq4_packed = __riscv_vle8_v_u8m2(iq4, 128);
5795            iq4 += 128;
5796
5797            // Unpack the weight blocks.
5798            const vuint8m2_t iq4bits_lo = __riscv_vand_vx_u8m2(iq4_packed, 0xf, 128);
5799            const vuint8m2_t iq4bits_hi = __riscv_vsrl_vx_u8m2(iq4_packed, 4, 128);
5800            const vuint8m4_t iq4bits = __riscv_vcreate_v_u8m2_u8m4(iq4bits_lo, iq4bits_hi);
5801            const vuint8m4_t iq4bits_reorder = __riscv_vreinterpret_v_u64m4_u8m4(__riscv_vrgatherei16_vv_u64m4(__riscv_vreinterpret_v_u8m4_u64m4(iq4bits), i_vec, 32));
5802            const vint8m4_t iq4b = __riscv_vrgather_vv_i8m4(values, iq4bits_reorder, 256);
5803
5804            __asm__ __volatile__("" ::: "memory");
5805
5806            // Multiply with activations.
5807            const vint8m4_t q8b = __riscv_vle8_v_i8m4(q8, 256);
5808            const vint16m8_t prod = __riscv_vwmul_vv_i16m8(iq4b, q8b, 256);
5809            q8 += 256;
5810
5811            // Reduce separately.
5812            const int acc0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 0), __riscv_vmv_v_x_i32m1(0, 1), 32));
5813            const int acc1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 1), __riscv_vmv_v_x_i32m1(0, 1), 32));
5814            const int acc2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 2), __riscv_vmv_v_x_i32m1(0, 1), 32));
5815            const int acc3 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 3), __riscv_vmv_v_x_i32m1(0, 1), 32));
5816            const int acc4 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 4), __riscv_vmv_v_x_i32m1(0, 1), 32));
5817            const int acc5 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 5), __riscv_vmv_v_x_i32m1(0, 1), 32));
5818            const int acc6 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 6), __riscv_vmv_v_x_i32m1(0, 1), 32));
5819            const int acc7 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(__riscv_vget_v_i16m8_i16m1(prod, 7), __riscv_vmv_v_x_i32m1(0, 1), 32));
5820
5821
5822            const int ls0 = ((x[ibl].scales_l[0] & 0xf)  | ((h << 4) & 0x30)) - 32;
5823            const int ls1 = ((x[ibl].scales_l[0] >>  4)  | ((h << 2) & 0x30)) - 32;
5824            const int ls2 = ((x[ibl].scales_l[1] &  0xf) | ((h << 0) & 0x30)) - 32;
5825            const int ls3 = ((x[ibl].scales_l[1] >>  4)  | ((h >> 2) & 0x30)) - 32;
5826            h >>= 8;
5827            const int ls4 = ((x[ibl].scales_l[2] & 0xf)  | ((h << 4) & 0x30)) - 32;
5828            const int ls5 = ((x[ibl].scales_l[2] >>  4)  | ((h << 2) & 0x30)) - 32;
5829            const int ls6 = ((x[ibl].scales_l[3] &  0xf) | ((h << 0) & 0x30)) - 32;
5830            const int ls7 = ((x[ibl].scales_l[3] >>  4)  | ((h >> 2) & 0x30)) - 32;
5831
5832            sumi += acc0 * ls0;
5833            sumi += acc1 * ls1;
5834            sumi += acc2 * ls2;
5835            sumi += acc3 * ls3;
5836            sumi += acc4 * ls4;
5837            sumi += acc5 * ls5;
5838            sumi += acc6 * ls6;
5839            sumi += acc7 * ls7;
5840
5841            __asm__ __volatile__("" ::: "memory");
5842        }
5843
5844        sumf += GGML_CPU_FP16_TO_FP32(x[ibl].d) * y[ibl].d * (sumi);
5845    }
5846
5847    *s = sumf;
5848}
5849
5850static NOINLINE void ggml_vec_dot_iq4_xs_q8_K_vl1024(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5851    assert(nrc == 1);
5852    UNUSED(nrc);
5853    UNUSED(bx);
5854    UNUSED(by);
5855    UNUSED(bs);
5856    assert(n % QK_K == 0);
5857
5858    const block_iq4_xs * GGML_RESTRICT x = vx;
5859    const block_q8_K   * GGML_RESTRICT y = vy;
5860
5861    const int nb = n / QK_K;
5862
5863    const vint8m2_t values = __riscv_vle8_v_i8m2(kvalues_iq4nl, 16);
5864    float sumf = 0;
5865
5866    // Indices for re-ordering IQ4 data.
5867    const uint16_t index[32] = {
5868        0, 1, 16, 17,
5869        2, 3, 18, 19,
5870        4, 5,20, 21,
5871        6, 7, 22, 23,
5872        8, 9, 24, 25,
5873        10, 11, 26, 27,
5874        12, 13,28, 29,
5875        14, 15, 30, 31,
5876    };
5877    const vuint16mf2_t i_vec = __riscv_vle16_v_u16mf2(index, 32);
5878
5879    for (int ibl = 0; ibl < nb; ++ibl) {
5880        const int8_t  * q8 = y[ibl].qs;
5881        const uint8_t * iq4 = x[ibl].qs;
5882        uint16_t h = x[ibl].scales_h;
5883
5884        int sumi = 0;
5885
5886        #pragma GCC unroll 1
5887        // Process the entire super-block together.
5888        for (int ib = 0; ib < QK_K / 256; ++ib) {
5889            // Weights and activations.
5890            const vuint8m1_t iq4_packed = __riscv_vle8_v_u8m1(iq4, 128);
5891            iq4 += 128;
5892
5893            // Unpack the weight blocks.
5894            const vuint8m1_t iq4bits_lo = __riscv_vand_vx_u8m1(iq4_packed, 0xf, 128);
5895            const vuint8m1_t iq4bits_hi = __riscv_vsrl_vx_u8m1(iq4_packed, 4, 128);
5896            const vuint8m2_t iq4bits = __riscv_vcreate_v_u8m1_u8m2(iq4bits_lo, iq4bits_hi);
5897            const vuint8m2_t iq4bits_reorder = __riscv_vreinterpret_v_u64m2_u8m2(__riscv_vrgatherei16_vv_u64m2(__riscv_vreinterpret_v_u8m2_u64m2(iq4bits), i_vec, 32));
5898            const vint8m2_t iq4b = __riscv_vrgather_vv_i8m2(values, iq4bits_reorder, 256);
5899
5900            __asm__ __volatile__("" ::: "memory");
5901
5902            // Multiply with activations.
5903            const vint8m2_t q8b = __riscv_vle8_v_i8m2(q8, 256);
5904            const vint16m4_t prod = __riscv_vwmul_vv_i16m4(iq4b, q8b, 256);
5905            q8 += 256;
5906
5907            // Mask for processing 32 elements per prod register.
5908            const vuint16m1_t p_index = __riscv_vid_v_u16m1(64);
5909            const vbool16_t p_mask = __riscv_vmsgtu_vx_u16m1_b16(p_index, 31, 64);
5910
5911            // Reduce separately.
5912            const int acc0 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(        __riscv_vget_v_i16m4_i16m1(prod, 0), __riscv_vmv_v_x_i32m1(0, 1), 32));
5913            const int acc1 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(p_mask, __riscv_vget_v_i16m4_i16m1(prod, 0), __riscv_vmv_v_x_i32m1(0, 1), 64));
5914            const int acc2 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(        __riscv_vget_v_i16m4_i16m1(prod, 1), __riscv_vmv_v_x_i32m1(0, 1), 32));
5915            const int acc3 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(p_mask, __riscv_vget_v_i16m4_i16m1(prod, 1), __riscv_vmv_v_x_i32m1(0, 1), 64));
5916            const int acc4 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(        __riscv_vget_v_i16m4_i16m1(prod, 2), __riscv_vmv_v_x_i32m1(0, 1), 32));
5917            const int acc5 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(p_mask, __riscv_vget_v_i16m4_i16m1(prod, 2), __riscv_vmv_v_x_i32m1(0, 1), 64));
5918            const int acc6 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1(        __riscv_vget_v_i16m4_i16m1(prod, 3), __riscv_vmv_v_x_i32m1(0, 1), 32));
5919            const int acc7 = __riscv_vmv_x_s_i32m1_i32(__riscv_vwredsum_vs_i16m1_i32m1_m(p_mask, __riscv_vget_v_i16m4_i16m1(prod, 3), __riscv_vmv_v_x_i32m1(0, 1), 64));
5920
5921            const int ls0 = ((x[ibl].scales_l[0] & 0xf)  | ((h << 4) & 0x30)) - 32;
5922            const int ls1 = ((x[ibl].scales_l[0] >>  4)  | ((h << 2) & 0x30)) - 32;
5923            const int ls2 = ((x[ibl].scales_l[1] &  0xf) | ((h << 0) & 0x30)) - 32;
5924            const int ls3 = ((x[ibl].scales_l[1] >>  4)  | ((h >> 2) & 0x30)) - 32;
5925            h >>= 8;
5926            const int ls4 = ((x[ibl].scales_l[2] & 0xf)  | ((h << 4) & 0x30)) - 32;
5927            const int ls5 = ((x[ibl].scales_l[2] >>  4)  | ((h << 2) & 0x30)) - 32;
5928            const int ls6 = ((x[ibl].scales_l[3] &  0xf) | ((h << 0) & 0x30)) - 32;
5929            const int ls7 = ((x[ibl].scales_l[3] >>  4)  | ((h >> 2) & 0x30)) - 32;
5930
5931            sumi += acc0 * ls0;
5932            sumi += acc1 * ls1;
5933            sumi += acc2 * ls2;
5934            sumi += acc3 * ls3;
5935            sumi += acc4 * ls4;
5936            sumi += acc5 * ls5;
5937            sumi += acc6 * ls6;
5938            sumi += acc7 * ls7;
5939
5940            __asm__ __volatile__("" ::: "memory");
5941        }
5942
5943        sumf += GGML_CPU_FP16_TO_FP32(x[ibl].d) * y[ibl].d * (sumi);
5944    }
5945
5946    *s = sumf;
5947}
5948#endif
5949
5950void ggml_vec_dot_iq4_xs_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5951#if defined __riscv_v
5952    switch (__riscv_vlenb() * 8) {
5953        case 128:
5954            ggml_vec_dot_iq4_xs_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
5955            break;
5956        case 256:
5957            ggml_vec_dot_iq4_xs_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
5958            break;
5959        case 512:
5960            ggml_vec_dot_iq4_xs_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
5961            break;
5962        case 1024:
5963            ggml_vec_dot_iq4_xs_q8_K_vl1024(n, s, bs, vx, bx, vy, by, nrc);
5964            break;
5965        default:
5966            ggml_vec_dot_iq4_xs_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
5967            break;
5968    }
5969#else
5970    ggml_vec_dot_iq4_xs_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
5971#endif
5972}
5973
5974#if defined __riscv_v
5975static NOINLINE void ggml_vec_dot_tq1_0_q8_K_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
5976    assert(nrc == 1);
5977    UNUSED(nrc);
5978    UNUSED(bx);
5979    UNUSED(by);
5980    UNUSED(bs);
5981
5982    const block_tq1_0 * GGML_RESTRICT x = vx;
5983    const block_q8_K  * GGML_RESTRICT y = vy;
5984
5985    const int nb = n / QK_K;
5986
5987    float sumf = 0.0f;
5988    uint8_t pow[16] = {1, 1, 1, 1, 3, 3, 3, 3, 9, 9, 9, 9, 27, 27, 27, 27};
5989
5990    for (int i = 0; i < nb; i++) {
5991        const uint8_t * GGML_RESTRICT tq = x[i].qs;
5992        const int8_t  * GGML_RESTRICT q8 = y[i].qs;
5993
5994        // First loop.
5995        vint16m4_t suml1;
5996        {
5997            const int vl = 32;
5998            const vuint8m2_t tqb = __riscv_vle8_v_u8m2(tq, vl);
5999            tq += 32;
6000
6001            {
6002                const vuint16m4_t tq0 = __riscv_vsrl_vx_u16m4(__riscv_vwmulu_vx_u16m4(tqb, 3, vl), 8, vl);
6003                const vint16m4_t q80 = __riscv_vwcvt_x_x_v_i16m4(__riscv_vle8_v_i8m2(q8, vl), vl);
6004                suml1 = __riscv_vmul_vv_i16m4(__riscv_vreinterpret_v_u16m4_i16m4(__riscv_vsub_vx_u16m4(tq0, 1, vl)), q80, vl);
6005                q8 += 32;
6006            }
6007
6008            uint8_t pow3 = 3;
6009            #pragma GCC unroll 1
6010            for (int t = 0; t < 4; t++) {
6011                const vuint16m4_t tqn = __riscv_vsrl_vx_u16m4(__riscv_vwmulu_vx_u16m4(__riscv_vmul_vx_u8m2(tqb, pow3, vl), 3, vl), 8, vl);
6012                const vint16m4_t q8n = __riscv_vwcvt_x_x_v_i16m4(__riscv_vle8_v_i8m2(q8, vl), vl);
6013                suml1 = __riscv_vmacc_vv_i16m4(suml1, __riscv_vreinterpret_v_u16m4_i16m4(__riscv_vsub_vx_u16m4(tqn, 1, vl)), q8n, vl);
6014                pow3 *= 3;
6015                q8 += 32;
6016            }
6017        }
6018
6019        // Second loop.
6020        vint16m2_t suml2;
6021        {
6022            const int vl = 16;
6023            const vuint8m1_t tqb = __riscv_vle8_v_u8m1(tq, vl);
6024
6025            {
6026                const vuint16m2_t tq0 = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(tqb, 3, vl), 8, vl);
6027                const vint16m2_t q80 = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(q8, vl), vl);
6028                suml2 = __riscv_vmul_vv_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tq0, 1, vl)), q80, vl);
6029                q8 += 16;
6030            }
6031
6032            uint8_t pow3 = 3;
6033            #pragma GCC unroll 1
6034            for (int t = 0; t < 4; t++) {
6035                const vuint16m2_t tqn = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(__riscv_vmul_vx_u8m1(tqb, pow3, vl), 3, vl), 8, vl);
6036                const vint16m2_t q8n = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(q8, vl), vl);
6037                suml2 = __riscv_vmacc_vv_i16m2(suml2, __riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tqn, 1, vl)), q8n, vl);
6038                pow3 *= 3;
6039                q8 += 16;
6040            }
6041        }
6042
6043        // Third loop.
6044        vint16m2_t suml3;
6045        {
6046            const int vl = 16;
6047
6048            uint32_t qh;
6049            memcpy(&qh, &x[i].qh[0], 4);
6050            // Prevent fusion with vmv.
6051            __asm__ __volatile__("" : "+r"(qh));
6052            const vuint8m1_t tqb = __riscv_vreinterpret_v_u32m1_u8m1(__riscv_vmv_v_x_u32m1(qh, vl / 4));
6053
6054            const vuint8m1_t p = __riscv_vle8_v_u8m1(pow, vl);
6055
6056            const vuint16m2_t tq0 = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(__riscv_vmul_vv_u8m1(tqb, p, vl), 3, vl), 8, vl);
6057
6058            const vint16m2_t q80 = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(q8, vl), vl);
6059
6060            suml3 = __riscv_vmul_vv_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tq0, 1, vl)), q80, vl);
6061        }
6062
6063        vint16m2_t sumb = __riscv_vadd_vv_i16m2(__riscv_vget_v_i16m4_i16m2(suml1, 0), __riscv_vget_v_i16m4_i16m2(suml1, 1), 16);
6064        sumb = __riscv_vadd_vv_i16m2(sumb, suml2, 16);
6065        sumb = __riscv_vadd_vv_i16m2(sumb, suml3, 16);
6066
6067        vint32m1_t sum = __riscv_vwredsum_vs_i16m2_i32m1(sumb, __riscv_vmv_v_x_i32m1(0, 1), 16);
6068        sumf += __riscv_vmv_x_s_i32m1_i32(sum) * y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
6069    }
6070
6071    *s = sumf;
6072}
6073
6074static NOINLINE void ggml_vec_dot_tq1_0_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6075    assert(nrc == 1);
6076    UNUSED(nrc);
6077    UNUSED(bx);
6078    UNUSED(by);
6079    UNUSED(bs);
6080
6081    const block_tq1_0 * GGML_RESTRICT x = vx;
6082    const block_q8_K  * GGML_RESTRICT y = vy;
6083
6084    const int nb = n / QK_K;
6085
6086    float sumf = 0.0f;
6087    uint8_t pow[16] = {1, 1, 1, 1, 3, 3, 3, 3, 9, 9, 9, 9, 27, 27, 27, 27};
6088
6089    for (int i = 0; i < nb; i++) {
6090        // First loop.
6091        vint16m2_t suml1;
6092        {
6093            const int vl = 32;
6094            vuint8m1_t tq = __riscv_vle8_v_u8m1(x[i].qs, vl);
6095
6096            vuint16m2_t tq0 = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(tq, 3, vl), 8, vl);
6097            vuint16m2_t tq1 = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(__riscv_vmul_vx_u8m1(tq, 3, vl), 3, vl), 8, vl);
6098            vuint16m2_t tq2 = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(__riscv_vmul_vx_u8m1(tq, 9, vl), 3, vl), 8, vl);
6099            vuint16m2_t tq3 = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(__riscv_vmul_vx_u8m1(tq, 27, vl), 3, vl), 8, vl);
6100            vuint16m2_t tq4 = __riscv_vsrl_vx_u16m2(__riscv_vwmulu_vx_u16m2(__riscv_vmul_vx_u8m1(tq, 81, vl), 3, vl), 8, vl);
6101
6102            vint16m2_t q80 = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(y[i].qs + 0, vl), vl);
6103            vint16m2_t q81 = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(y[i].qs + 32, vl), vl);
6104            vint16m2_t q82 = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(y[i].qs + 64, vl), vl);
6105            vint16m2_t q83 = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(y[i].qs + 96, vl), vl);
6106            vint16m2_t q84 = __riscv_vwcvt_x_x_v_i16m2(__riscv_vle8_v_i8m1(y[i].qs + 128, vl), vl);
6107
6108            vint16m2_t sum0 = __riscv_vmul_vv_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tq0, 1, vl)), q80, vl);
6109            vint16m2_t sum1 = __riscv_vmul_vv_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tq1, 1, vl)), q81, vl);
6110            vint16m2_t sum2 = __riscv_vmul_vv_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tq2, 1, vl)), q82, vl);
6111            vint16m2_t sum3 = __riscv_vmul_vv_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tq3, 1, vl)), q83, vl);
6112            vint16m2_t sum4 = __riscv_vmul_vv_i16m2(__riscv_vreinterpret_v_u16m2_i16m2(__riscv_vsub_vx_u16m2(tq4, 1, vl)), q84, vl);
6113
6114            vint16m2_t sumi0 = __riscv_vadd_vv_i16m2(sum0, sum1, vl);
6115            vint16m2_t sumi1 = __riscv_vadd_vv_i16m2(sum2, sum3, vl);
6116            suml1 = __riscv_vadd_vv_i16m2(sum4, __riscv_vadd_vv_i16m2(sumi0, sumi1, vl), vl);
6117        }
6118
6119        // Second loop.
6120        vint16m1_t suml2;
6121        {
6122            const int vl = 16;
6123            vuint8mf2_t tq = __riscv_vle8_v_u8mf2(x[i].qs + 32, vl);
6124
6125            vuint16m1_t tq0 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(tq, 3 * 1, vl), 8, vl);
6126            vuint16m1_t tq1 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 3, vl), 3, vl), 8, vl);
6127            vuint16m1_t tq2 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 9, vl), 3, vl), 8, vl);
6128            vuint16m1_t tq3 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 27, vl), 3, vl), 8, vl);
6129            vuint16m1_t tq4 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 81, vl), 3, vl), 8, vl);
6130
6131            vint16m1_t q80 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 160, vl), vl);
6132            vint16m1_t q81 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 176, vl), vl);
6133            vint16m1_t q82 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 192, vl), vl);
6134            vint16m1_t q83 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 208, vl), vl);
6135            vint16m1_t q84 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 224, vl), vl);
6136
6137            vint16m1_t sum0 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq0, 1, vl)), q80, vl);
6138            vint16m1_t sum1 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq1, 1, vl)), q81, vl);
6139            vint16m1_t sum2 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq2, 1, vl)), q82, vl);
6140            vint16m1_t sum3 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq3, 1, vl)), q83, vl);
6141            vint16m1_t sum4 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq4, 1, vl)), q84, vl);
6142
6143            vint16m1_t sumi0 = __riscv_vadd_vv_i16m1(sum0, sum1, vl);
6144            vint16m1_t sumi1 = __riscv_vadd_vv_i16m1(sum2, sum3, vl);
6145            suml2 = __riscv_vadd_vv_i16m1(sum4, __riscv_vadd_vv_i16m1(sumi0, sumi1, vl), vl);
6146        }
6147
6148        // Third loop.
6149        vint16m1_t suml3;
6150        {
6151            const int vl = 16;
6152
6153            uint32_t qh;
6154            memcpy(&qh, &x[i].qh[0], 4);
6155            // Prevent fusion with vmv.
6156            __asm__ __volatile__("" : "+r"(qh));
6157            vuint8mf2_t tq = __riscv_vreinterpret_v_u32mf2_u8mf2(__riscv_vmv_v_x_u32mf2(qh, vl / 4));
6158
6159            vuint8mf2_t p = __riscv_vle8_v_u8mf2(pow, vl);
6160
6161            vuint16m1_t tq0 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vv_u8mf2(tq, p, vl), 3, vl), 8, vl);
6162
6163            vint16m1_t q80 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 240, vl), vl);
6164
6165            suml3 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq0, 1, vl)), q80, vl);
6166        }
6167
6168        vint16m1_t sumb = __riscv_vadd_vv_i16m1(__riscv_vget_v_i16m2_i16m1(suml1, 0), __riscv_vget_v_i16m2_i16m1(suml1, 1), 16);
6169        sumb = __riscv_vadd_vv_i16m1(sumb, __riscv_vadd_vv_i16m1(suml2, suml3, 16), 16);
6170
6171        vint32m1_t sum = __riscv_vwredsum_vs_i16m1_i32m1(sumb, __riscv_vmv_v_x_i32m1(0, 1), 16);
6172        sumf += __riscv_vmv_x_s_i32m1_i32(sum) * y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
6173    }
6174
6175    *s = sumf;
6176}
6177
6178static NOINLINE void ggml_vec_dot_tq1_0_q8_K_vl512(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6179    assert(nrc == 1);
6180    UNUSED(nrc);
6181    UNUSED(bx);
6182    UNUSED(by);
6183    UNUSED(bs);
6184
6185    const block_tq1_0 * GGML_RESTRICT x = vx;
6186    const block_q8_K  * GGML_RESTRICT y = vy;
6187
6188    const int nb = n / QK_K;
6189
6190    float sumf = 0.0f;
6191    uint8_t pow[16] = {1, 1, 1, 1, 3, 3, 3, 3, 9, 9, 9, 9, 27, 27, 27, 27};
6192
6193    for (int i = 0; i < nb; i++) {
6194        // First loop.
6195        vint16m1_t suml1;
6196        {
6197            const int vl = 32;
6198            vuint8mf2_t tq = __riscv_vle8_v_u8mf2(x[i].qs, vl);
6199
6200            vuint16m1_t tq0 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(tq, 3, vl), 8, vl);
6201            vuint16m1_t tq1 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 3, vl), 3, vl), 8, vl);
6202            vuint16m1_t tq2 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 9, vl), 3, vl), 8, vl);
6203            vuint16m1_t tq3 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 27, vl), 3, vl), 8, vl);
6204            vuint16m1_t tq4 = __riscv_vsrl_vx_u16m1(__riscv_vwmulu_vx_u16m1(__riscv_vmul_vx_u8mf2(tq, 81, vl), 3, vl), 8, vl);
6205
6206            vint16m1_t q80 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 0, vl), vl);
6207            vint16m1_t q81 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 32, vl), vl);
6208            vint16m1_t q82 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 64, vl), vl);
6209            vint16m1_t q83 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 96, vl), vl);
6210            vint16m1_t q84 = __riscv_vwcvt_x_x_v_i16m1(__riscv_vle8_v_i8mf2(y[i].qs + 128, vl), vl);
6211
6212            vint16m1_t sum0 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq0, 1, vl)), q80, vl);
6213            vint16m1_t sum1 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq1, 1, vl)), q81, vl);
6214            vint16m1_t sum2 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq2, 1, vl)), q82, vl);
6215            vint16m1_t sum3 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq3, 1, vl)), q83, vl);
6216            vint16m1_t sum4 = __riscv_vmul_vv_i16m1(__riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vx_u16m1(tq4, 1, vl)), q84, vl);
6217
6218            vint16m1_t sumi0 = __riscv_vadd_vv_i16m1(sum0, sum1, vl);
6219            vint16m1_t sumi1 = __riscv_vadd_vv_i16m1(sum2, sum3, vl);
6220            suml1 = __riscv_vadd_vv_i16m1(sum4, __riscv_vadd_vv_i16m1(sumi0, sumi1, vl), vl);
6221        }
6222
6223        // Second loop.
6224        vint16mf2_t suml2;
6225        {
6226            const int vl = 16;
6227            vuint8mf4_t tq = __riscv_vle8_v_u8mf4(x[i].qs + 32, vl);
6228
6229            vuint16mf2_t tq0 = __riscv_vsrl_vx_u16mf2(__riscv_vwmulu_vx_u16mf2(tq, 3 * 1, vl), 8, vl);
6230            vuint16mf2_t tq1 = __riscv_vsrl_vx_u16mf2(__riscv_vwmulu_vx_u16mf2(__riscv_vmul_vx_u8mf4(tq, 3, vl), 3, vl), 8, vl);
6231            vuint16mf2_t tq2 = __riscv_vsrl_vx_u16mf2(__riscv_vwmulu_vx_u16mf2(__riscv_vmul_vx_u8mf4(tq, 9, vl), 3, vl), 8, vl);
6232            vuint16mf2_t tq3 = __riscv_vsrl_vx_u16mf2(__riscv_vwmulu_vx_u16mf2(__riscv_vmul_vx_u8mf4(tq, 27, vl), 3, vl), 8, vl);
6233            vuint16mf2_t tq4 = __riscv_vsrl_vx_u16mf2(__riscv_vwmulu_vx_u16mf2(__riscv_vmul_vx_u8mf4(tq, 81, vl), 3, vl), 8, vl);
6234
6235            vint16mf2_t q80 = __riscv_vwcvt_x_x_v_i16mf2(__riscv_vle8_v_i8mf4(y[i].qs + 160, vl), vl);
6236            vint16mf2_t q81 = __riscv_vwcvt_x_x_v_i16mf2(__riscv_vle8_v_i8mf4(y[i].qs + 176, vl), vl);
6237            vint16mf2_t q82 = __riscv_vwcvt_x_x_v_i16mf2(__riscv_vle8_v_i8mf4(y[i].qs + 192, vl), vl);
6238            vint16mf2_t q83 = __riscv_vwcvt_x_x_v_i16mf2(__riscv_vle8_v_i8mf4(y[i].qs + 208, vl), vl);
6239            vint16mf2_t q84 = __riscv_vwcvt_x_x_v_i16mf2(__riscv_vle8_v_i8mf4(y[i].qs + 224, vl), vl);
6240
6241            vint16mf2_t sum0 = __riscv_vmul_vv_i16mf2(__riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vsub_vx_u16mf2(tq0, 1, vl)), q80, vl);
6242            vint16mf2_t sum1 = __riscv_vmul_vv_i16mf2(__riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vsub_vx_u16mf2(tq1, 1, vl)), q81, vl);
6243            vint16mf2_t sum2 = __riscv_vmul_vv_i16mf2(__riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vsub_vx_u16mf2(tq2, 1, vl)), q82, vl);
6244            vint16mf2_t sum3 = __riscv_vmul_vv_i16mf2(__riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vsub_vx_u16mf2(tq3, 1, vl)), q83, vl);
6245            vint16mf2_t sum4 = __riscv_vmul_vv_i16mf2(__riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vsub_vx_u16mf2(tq4, 1, vl)), q84, vl);
6246
6247            vint16mf2_t sumi0 = __riscv_vadd_vv_i16mf2(sum0, sum1, vl);
6248            vint16mf2_t sumi1 = __riscv_vadd_vv_i16mf2(sum2, sum3, vl);
6249            suml2 = __riscv_vadd_vv_i16mf2(sum4, __riscv_vadd_vv_i16mf2(sumi0, sumi1, vl), vl);
6250        }
6251
6252        // Third loop.
6253        vint16mf2_t suml3;
6254        {
6255            const int vl = 16;
6256
6257            uint32_t qh;
6258            memcpy(&qh, &x[i].qh[0], 4);
6259            // Prevent fusion with vmv.
6260            __asm__ __volatile__("" : "+r"(qh));
6261            vuint8mf4_t tq = __riscv_vlmul_trunc_v_u8mf2_u8mf4(__riscv_vreinterpret_v_u32mf2_u8mf2(__riscv_vmv_v_x_u32mf2(qh, vl / 4)));
6262
6263            vuint8mf4_t p = __riscv_vle8_v_u8mf4(pow, vl);
6264
6265            vuint16mf2_t tq0 = __riscv_vsrl_vx_u16mf2(__riscv_vwmulu_vx_u16mf2(__riscv_vmul_vv_u8mf4(tq, p, vl), 3, vl), 8, vl);
6266
6267            vint16mf2_t q80 = __riscv_vwcvt_x_x_v_i16mf2(__riscv_vle8_v_i8mf4(y[i].qs + 240, vl), vl);
6268
6269            suml3 = __riscv_vmul_vv_i16mf2(__riscv_vreinterpret_v_u16mf2_i16mf2(__riscv_vsub_vx_u16mf2(tq0, 1, vl)), q80, vl);
6270        }
6271
6272        vint32m1_t sum = __riscv_vwredsum_vs_i16m1_i32m1(suml1, __riscv_vmv_v_x_i32m1(0, 1), 32);
6273        sum = __riscv_vwredsum_vs_i16mf2_i32m1(__riscv_vadd_vv_i16mf2(suml2, suml3, 16), sum, 16);
6274        sumf += __riscv_vmv_x_s_i32m1_i32(sum) * y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
6275    }
6276
6277    *s = sumf;
6278}
6279#endif
6280
6281void ggml_vec_dot_tq1_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6282#if defined __riscv_v
6283    switch (__riscv_vlenb() * 8) {
6284        case 128:
6285            ggml_vec_dot_tq1_0_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
6286            break;
6287        case 256:
6288            ggml_vec_dot_tq1_0_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
6289            break;
6290        default: // 512 and above
6291            ggml_vec_dot_tq1_0_q8_K_vl512(n, s, bs, vx, bx, vy, by, nrc);
6292            break;
6293    }
6294#else
6295    ggml_vec_dot_tq1_0_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
6296#endif
6297}
6298
6299#if defined __riscv_v
6300static NOINLINE void ggml_vec_dot_tq2_0_q8_K_vl128(const int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6301    assert(n % QK_K == 0);
6302    assert(nrc == 1);
6303    UNUSED(nrc);
6304    UNUSED(bx);
6305    UNUSED(by);
6306    UNUSED(bs);
6307
6308    const block_tq2_0 * GGML_RESTRICT x = vx;
6309    const block_q8_K  * GGML_RESTRICT y = vy;
6310
6311    const int nb = n / QK_K;
6312    float sumf = 0.0f;
6313    for (int i = 0; i < nb; ++i) {
6314        int32_t sumi = 0;
6315
6316        for (size_t j = 0; j < sizeof(x[0].qs); j += 32) {
6317            const int8_t * py0 = &y[i].qs[j * 4 + 0 * 32];
6318            const int8_t * py1 = &y[i].qs[j * 4 + 1 * 32];
6319            const int8_t * py2 = &y[i].qs[j * 4 + 2 * 32];
6320            const int8_t * py3 = &y[i].qs[j * 4 + 3 * 32];
6321            const uint8_t* px  = &x[i].qs[j];
6322
6323            size_t vl = __riscv_vsetvl_e16m4(32);
6324            vint16m4_t vacc16 = __riscv_vmv_v_x_i16m4(0, vl);
6325
6326            // Load Raw Packed elements
6327            vl = __riscv_vsetvl_e8m2(32);
6328            vuint8m2_t vx_u8 = __riscv_vle8_v_u8m2(px, vl);
6329
6330            // Process bits 1:0
6331            {
6332                // Unpack
6333                vuint8m2_t t0 = __riscv_vand_vx_u8m2(vx_u8, 0x03, vl);
6334                vint8m2_t vq = __riscv_vsub_vx_i8m2(__riscv_vreinterpret_v_u8m2_i8m2(t0), 1, vl);
6335                vint8m2_t vy = __riscv_vle8_v_i8m2(py0, vl);
6336                // Accumulate
6337                vacc16 = __riscv_vwmacc_vv_i16m4(vacc16, vq, vy, vl);
6338            }
6339            __asm__ volatile("" ::: "memory");
6340            // Process bits 3:2
6341            {
6342                vuint8m2_t t1 = __riscv_vsrl_vx_u8m2(vx_u8, 2, vl);
6343                t1 = __riscv_vand_vx_u8m2(t1, 0x03, vl);
6344                vint8m2_t vq = __riscv_vsub_vx_i8m2(__riscv_vreinterpret_v_u8m2_i8m2(t1), 1, vl);
6345
6346                vint8m2_t vy = __riscv_vle8_v_i8m2(py1, vl);
6347                vacc16 = __riscv_vwmacc_vv_i16m4(vacc16, vq, vy, vl);
6348            }
6349            __asm__ volatile("" ::: "memory");
6350            // Process bits 5:4
6351            {
6352                vuint8m2_t t2 = __riscv_vsrl_vx_u8m2(vx_u8, 4, vl);
6353                t2 = __riscv_vand_vx_u8m2(t2, 0x03, vl);
6354                vint8m2_t vq = __riscv_vsub_vx_i8m2(__riscv_vreinterpret_v_u8m2_i8m2(t2), 1, vl);
6355
6356                vint8m2_t vy = __riscv_vle8_v_i8m2(py2, vl);
6357                vacc16 = __riscv_vwmacc_vv_i16m4(vacc16, vq, vy, vl);
6358            }
6359            __asm__ volatile("" ::: "memory");
6360            // Process bits 7:6
6361            {
6362                vuint8m2_t t3 = __riscv_vsrl_vx_u8m2(vx_u8, 6, vl);
6363                vint8m2_t vq = __riscv_vsub_vx_i8m2(__riscv_vreinterpret_v_u8m2_i8m2(t3), 1, vl);
6364
6365                vint8m2_t vy = __riscv_vle8_v_i8m2(py3, vl);
6366                vacc16 = __riscv_vwmacc_vv_i16m4(vacc16, vq, vy, vl);
6367            }
6368            __asm__ volatile("" ::: "memory");
6369            vl = __riscv_vsetvl_e16m4(32);
6370            vint32m1_t vzero32 = __riscv_vmv_v_x_i32m1(0, 1);
6371            vint32m1_t vred32 = __riscv_vwredsum_vs_i16m4_i32m1(vacc16, vzero32, vl);
6372            sumi += __riscv_vmv_x_s_i32m1_i32(vred32);
6373        }
6374
6375        const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
6376        sumf += (float)sumi * d;
6377    }
6378
6379    *s = sumf;
6380}
6381
6382static NOINLINE void ggml_vec_dot_tq2_0_q8_K_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6383    assert(n % QK_K == 0);
6384    assert(nrc == 1);
6385    UNUSED(nrc);
6386    UNUSED(bx);
6387    UNUSED(by);
6388    UNUSED(bs);
6389
6390    const block_tq2_0 * GGML_RESTRICT x = vx;
6391    const block_q8_K  * GGML_RESTRICT y = vy;
6392
6393    const int nb = n / QK_K;
6394
6395    float sumf = 0.0f;
6396    for (int i = 0; i < nb; ++i) {
6397        int32_t sumi = 0;
6398
6399        for (size_t j = 0; j < sizeof(x[0].qs); j += 32) {
6400            const int8_t * py0 = &y[i].qs[j * 4 + 0 * 32];
6401            const int8_t * py1 = &y[i].qs[j * 4 + 1 * 32];
6402            const int8_t * py2 = &y[i].qs[j * 4 + 2 * 32];
6403            const int8_t * py3 = &y[i].qs[j * 4 + 3 * 32];
6404            const uint8_t* px  = &x[i].qs[j];
6405
6406            size_t vlmax_16m2 = __riscv_vsetvl_e16m2(32);
6407            vint16m2_t vacc16 = __riscv_vmv_v_x_i16m2(0, vlmax_16m2);
6408
6409            size_t vl = __riscv_vsetvl_e8m1(32);
6410
6411            vuint8m1_t vx_u8 = __riscv_vle8_v_u8m1(px, vl);
6412
6413            vint8m1_t vy0 = __riscv_vle8_v_i8m1(py0 , vl);
6414            vint8m1_t vy1 = __riscv_vle8_v_i8m1(py1, vl);
6415            vint8m1_t vy2 = __riscv_vle8_v_i8m1(py2, vl);
6416            vint8m1_t vy3 = __riscv_vle8_v_i8m1(py3, vl);
6417
6418            // l=0 (bits 1:0)
6419            vuint8m1_t t0 = __riscv_vand_vx_u8m1(vx_u8, 0x03, vl);
6420            vint8m1_t vq0 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(t0), 1, vl);
6421
6422            // l=1 (bits 3:2)
6423            vuint8m1_t t1 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(vx_u8, 2, vl), 0x03, vl);
6424            vint8m1_t vq1 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(t1), 1, vl);
6425
6426            // l=2 (bits 5:4)
6427            vuint8m1_t t2 = __riscv_vand_vx_u8m1(__riscv_vsrl_vx_u8m1(vx_u8, 4, vl), 0x03, vl);
6428            vint8m1_t vq2 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(t2), 1, vl);
6429
6430            // l=3 (bits 7:6)
6431            vuint8m1_t t3 = __riscv_vsrl_vx_u8m1(vx_u8, 6, vl); // No final AND needed as vsrl shifts in zeros
6432            vint8m1_t vq3 = __riscv_vsub_vx_i8m1(__riscv_vreinterpret_v_u8m1_i8m1(t3), 1, vl);
6433
6434            // 4. Multiply and accumulate
6435            vacc16 = __riscv_vwmacc_vv_i16m2(vacc16, vq0, vy0, vl);
6436            vacc16 = __riscv_vwmacc_vv_i16m2(vacc16, vq1, vy1, vl);
6437            vacc16 = __riscv_vwmacc_vv_i16m2(vacc16, vq2, vy2, vl);
6438            vacc16 = __riscv_vwmacc_vv_i16m2(vacc16, vq3, vy3, vl);
6439
6440            vlmax_16m2 = __riscv_vsetvl_e16m2(32);
6441            vint32m1_t vzero32 = __riscv_vmv_v_x_i32m1(0, 1);
6442            vint32m1_t vred32 = __riscv_vwredsum_vs_i16m2_i32m1(vacc16, vzero32, vlmax_16m2);
6443
6444            sumi += __riscv_vmv_x_s_i32m1_i32(vred32);
6445        }
6446        const float d = y[i].d * GGML_CPU_FP16_TO_FP32(x[i].d);
6447        sumf += (float)sumi * d;
6448    }
6449
6450    *s = sumf;
6451}
6452#endif
6453
6454void ggml_vec_dot_tq2_0_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6455#if defined __riscv_v
6456    switch (__riscv_vlenb() * 8) {
6457        case 128:
6458            ggml_vec_dot_tq2_0_q8_K_vl128(n, s, bs, vx, bx, vy, by, nrc);
6459            break;
6460        default: // 256 and above
6461            ggml_vec_dot_tq2_0_q8_K_vl256(n, s, bs, vx, bx, vy, by, nrc);
6462            break;
6463    }
6464#else
6465    ggml_vec_dot_tq2_0_q8_K_generic(n, s, bs, vx, bx, vy, by, nrc);
6466#endif
6467}
6468
6469#if defined __riscv_v
6470static NOINLINE void ggml_vec_dot_mxfp4_q8_0_vl128(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6471    assert(nrc == 1);
6472    UNUSED(nrc);
6473    UNUSED(bx);
6474    UNUSED(by);
6475    UNUSED(bs);
6476    assert(n % QK_MXFP4 == 0);
6477    static_assert(QK_MXFP4 == QK8_0, "QK_MXFP4 and QK8_0 must be the same");
6478
6479    const block_mxfp4 * GGML_RESTRICT x = vx;
6480    const block_q8_0  * GGML_RESTRICT y = vy;
6481
6482    const int nb = n / QK_MXFP4;
6483
6484    int ib = 0;
6485    float sumf = 0;
6486
6487    // Load the lookup table once.
6488    const vint8m2_t values = __riscv_vle8_v_i8m2(kvalues_mxfp4, 16);
6489    int acc1, acc2;
6490
6491    // We process 2 blocks at once.
6492    for (; ib + 1 < nb; ib += 2) {
6493        // Weights and activations.
6494        vuint8m1_t mx_packed1 = __riscv_vle8_v_u8m1(x[ib + 0].qs, 16);
6495        vint8m2_t q8b1 = __riscv_vle8_v_i8m2(y[ib + 0].qs, 32);
6496        vuint8m1_t mx_packed2 = __riscv_vle8_v_u8m1(x[ib + 1].qs, 16);
6497        vint8m2_t q8b2 = __riscv_vle8_v_i8m2(y[ib + 1].qs, 32);
6498
6499        // Unpack the weight blocks.
6500        vuint8m2_t mxbits1 = __riscv_vcreate_v_u8m1_u8m2(
6501            __riscv_vand_vx_u8m1(mx_packed1, 0xf, 16),
6502            __riscv_vsrl_vx_u8m1(mx_packed1, 4, 16)
6503        );
6504        vuint8m2_t mxbits2 = __riscv_vcreate_v_u8m1_u8m2(
6505            __riscv_vand_vx_u8m1(mx_packed2, 0xf, 16),
6506            __riscv_vsrl_vx_u8m1(mx_packed2, 4, 16)
6507        );
6508
6509        // Gather values from the lookup table.
6510        vint8m2_t mxb1 = __riscv_vrgather_vv_i8m2(values, mxbits1, 32);
6511        vint8m2_t mxb2 = __riscv_vrgather_vv_i8m2(values, mxbits2, 32);
6512
6513        // Accumulation.
6514        vint16m4_t sum1 = __riscv_vwmul_vv_i16m4(q8b1, mxb1, 32);
6515        vint16m4_t sum2 = __riscv_vwmul_vv_i16m4(q8b2, mxb2, 32);
6516        __riscv_vse32_v_i32m1(&acc1,__riscv_vwredsum_vs_i16m4_i32m1(sum1, __riscv_vmv_v_x_i32m1(0, 1), 32), 1);
6517        __riscv_vse32_v_i32m1(&acc2,__riscv_vwredsum_vs_i16m4_i32m1(sum2, __riscv_vmv_v_x_i32m1(0, 1), 32), 1);
6518        sumf += ((GGML_E8M0_TO_FP32_HALF(x[ib + 0].e) * GGML_CPU_FP16_TO_FP32(y[ib + 0].d) * acc1));
6519        sumf += ((GGML_E8M0_TO_FP32_HALF(x[ib + 1].e) * GGML_CPU_FP16_TO_FP32(y[ib + 1].d) * acc2));
6520    }
6521
6522    *s = sumf;
6523}
6524
6525static NOINLINE void ggml_vec_dot_mxfp4_q8_0_vl256(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6526    assert(nrc == 1);
6527    UNUSED(nrc);
6528    UNUSED(bx);
6529    UNUSED(by);
6530    UNUSED(bs);
6531    assert(n % QK_MXFP4 == 0);
6532    static_assert(QK_MXFP4 == QK8_0, "QK_MXFP4 and QK8_0 must be the same");
6533
6534    const block_mxfp4 * GGML_RESTRICT x = vx;
6535    const block_q8_0  * GGML_RESTRICT y = vy;
6536
6537    const int nb = n / QK_MXFP4;
6538
6539    int ib = 0;
6540    float sumf = 0;
6541
6542    // Load the lookup table once.
6543    const vint8mf2_t values = __riscv_vle8_v_i8mf2(kvalues_mxfp4, 16);
6544    int acc1, acc2;
6545
6546    // We process 2 blocks at once.
6547    for (; ib + 1 < nb; ib+=2) {
6548        // Weights and activations.
6549        vuint8mf2_t mx_packed1 = __riscv_vle8_v_u8mf2(x[ib + 0].qs, 16);
6550        vint8mf2_t q8b_lo1 = __riscv_vle8_v_i8mf2(y[ib + 0].qs, 16);
6551        vint8mf2_t q8b_hi1 = __riscv_vle8_v_i8mf2(y[ib + 0].qs + 16, 16);
6552        vuint8mf2_t mx_packed2 = __riscv_vle8_v_u8mf2(x[ib + 1].qs, 16);
6553        vint8mf2_t q8b_lo2 = __riscv_vle8_v_i8mf2(y[ib + 1].qs, 16);
6554        vint8mf2_t q8b_hi2 = __riscv_vle8_v_i8mf2(y[ib + 1].qs + 16, 16);
6555
6556        // Unpack the weight blocks.
6557        vuint8mf2_t mxbits_lo1 = __riscv_vand_vx_u8mf2(mx_packed1, 0xf, 16);
6558        vuint8mf2_t mxbits_hi1 = __riscv_vsrl_vx_u8mf2(mx_packed1, 4, 16);
6559        vuint8mf2_t mxbits_lo2 = __riscv_vand_vx_u8mf2(mx_packed2, 0xf, 16);
6560        vuint8mf2_t mxbits_hi2 = __riscv_vsrl_vx_u8mf2(mx_packed2, 4, 16);
6561
6562        // Gather values from the lookup table.
6563        vint8mf2_t mxb_lo1 = __riscv_vrgather_vv_i8mf2(values, mxbits_lo1, 16);
6564        vint8mf2_t mxb_hi1 = __riscv_vrgather_vv_i8mf2(values, mxbits_hi1, 16);
6565        vint8mf2_t mxb_lo2 = __riscv_vrgather_vv_i8mf2(values, mxbits_lo2, 16);
6566        vint8mf2_t mxb_hi2 = __riscv_vrgather_vv_i8mf2(values, mxbits_hi2, 16);
6567
6568        // Accumulation.
6569        vint16m1_t sum1 = __riscv_vwmul_vv_i16m1(q8b_lo1, mxb_lo1, 16);
6570        sum1 = __riscv_vwmacc_vv_i16m1(sum1, q8b_hi1, mxb_hi1, 16);
6571        vint16m1_t sum2 = __riscv_vwmul_vv_i16m1(q8b_lo2, mxb_lo2, 16);
6572        sum2 = __riscv_vwmacc_vv_i16m1(sum2, q8b_hi2, mxb_hi2, 16);
6573        __riscv_vse32_v_i32m1(&acc1,__riscv_vwredsum_vs_i16m1_i32m1(sum1, __riscv_vmv_v_x_i32m1(0, 1), 16), 1);
6574        __riscv_vse32_v_i32m1(&acc2,__riscv_vwredsum_vs_i16m1_i32m1(sum2, __riscv_vmv_v_x_i32m1(0, 1), 16), 1);
6575        sumf += ((GGML_E8M0_TO_FP32_HALF(x[ib + 0].e) * GGML_CPU_FP16_TO_FP32(y[ib + 0].d) * acc1));
6576        sumf += ((GGML_E8M0_TO_FP32_HALF(x[ib + 1].e) * GGML_CPU_FP16_TO_FP32(y[ib + 1].d) * acc2));
6577    }
6578
6579    *s = sumf;
6580}
6581#endif
6582
6583void ggml_vec_dot_mxfp4_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
6584#if defined __riscv_v
6585    switch (__riscv_vlenb() * 8) {
6586        case 128:
6587            ggml_vec_dot_mxfp4_q8_0_vl128(n, s, bs, vx, bx, vy, by, nrc);
6588            break;
6589        default: // 256 and above
6590            ggml_vec_dot_mxfp4_q8_0_vl256(n, s, bs, vx, bx, vy, by, nrc);
6591            break;
6592    }
6593#else
6594    ggml_vec_dot_mxfp4_q8_0_generic(n, s, bs, vx, bx, vy, by, nrc);
6595#endif
6596}