xref: /aosp_15_r20/external/XNNPACK/src/qc8-gemm/gen/4x8-minmax-fp32-aarch32-neon-mlal-lane-ld64.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/qs8-gemm/4x8-aarch32-neon-mlal-lane-ld64.S.in
3//   Generator: tools/xngen
4//
5// Copyright 2021 Google LLC
6//
7// This source code is licensed under the BSD-style license found in the
8// LICENSE file in the root directory of this source tree.
9
10
11#include <xnnpack/assembly.h>
12
13.syntax unified
14
15// void xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_ld64(
16//     size_t mr,                            r0
17//     size_t nc,                            r1
18//     size_t kc,                            r2 -> r5
19//     const int8_t*restrict a,              r3
20//     size_t a_stride,           sp + 72 -> (r7)
21//     const void*restrict w,     sp + 76 -> r9
22//     int8_t*restrict c,         sp + 80 -> r11
23//     size_t cm_stride,          sp + 84 -> (r6)
24//     size_t cn_stride,          sp + 88 -> r7
25//     xnn_qs8_minmax_params params)  sp + 92 -> (r5)
26
27// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
28
29// Register usage
30// A0   r3  d0-d1 q0
31// A1  r12  d2-d3 q1
32// A2  r10  d4-d5 q2
33// A3   r0  d6-d7 q3
34
35// B    r9  d10-d11 q5
36
37// C0  r11 d16-d17  q8  d18-d19  q9
38// C1   r4 d20-d21 q10  d22-d23 q11
39// C2   r8 d24-d25 q12  d26-d27 q13
40// C3   r6 d28-d29 q14  d30-d31 q15
41
42// Unused d13-d15
43
44// params structure is 10 bytes
45// struct {
46//   float magic_bias;                           d12[0]
47//   int32_t magic_bias_less_output_zero_point;  d12[1]
48//   int8_t output_min;                          d13[6]
49//   int8_t output_max;                          d13[7]
50// } xnn_qs8_minmax_params.neon;
51
52BEGIN_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_ld64
53        # Push 72 bytes
54        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
55        SUB     sp, sp, 8                           // +8
56        VPUSH   {d10-d13}                           // +32 = 72
57
58        LDR     r7, [sp, 72]            // a_stride
59        LDR     r11, [sp, 80]           // c
60        LDR     r6, [sp, 84]            // cm_stride
61        LDR     r9, [sp, 76]            // w
62        LDR     r5, [sp, 92]            // params
63
64        # Clamp A and C pointers
65        CMP     r0, 2                   // if mr >= 2
66        ADD     r12, r3, r7             //   a1 = a0 + a_stride
67        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
68        MOVLO   r12, r3                 // a1
69        MOVLO   r4, r11                 // c1
70                                        // if mr > 2
71        ADD     r10, r12, r7            //   a2 = a1 + a_stride
72        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
73        MOVLS   r10, r12                // a2
74        MOVLS   r8, r4                  // c2
75
76        CMP     r0, 4                   // if mr >=4
77        ADD     r0, r10, r7             //   a3 = a2 + a_stride
78        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
79        MOVLO   r0, r10                 // a3
80        MOVLO   r6, r8                  // c3
81
82        # Load params values
83        VLDM    r5!, {d12}              // QC8 neon params
84        VLD1.16 {d13[]}, [r5]           // output_min/max
85        LDR     r7, [sp, 88]            // cn_stride
86
87
88        .p2align 3
890:
90        # Load initial bias from w into accumulators
91        VLDM    r9!, {d16-d19}          // Bias
92        SUBS    r5, r2, 8               // k = kc - 8
93
94        VMOV    q10, q8
95        VMOV    q11, q9
96        VMOV    q12, q8
97        VMOV    q13, q9
98        VMOV    q14, q8
99        VMOV    q15, q9
100        BLO     3f                      // less than 8 channels?
101
102        # Main loop - 8 bytes
103        # 64 bytes for weights.
104        .p2align 3
1051:
106        VLD1.8  {d0},  [r3]!            // A0
107        VLD1.8  {d10},  [r9]!            // B
108        VLD1.8  {d2}, [r12]!            // A1
109        VLD1.8  {d4}, [r10]!            // A2
110        VLD1.8  {d6},  [r0]!            // A3
111        SUBS    r5, r5, 8
112        VMOVL.S8 q0, d0
113        VMOVL.S8 q5, d10
114        VMOVL.S8 q1, d2
115        VMOVL.S8 q2, d4
116        VMOVL.S8 q3, d6
117        VMLAL.S16 q8, d10, d0[0]
118        VMLAL.S16 q9, d11, d0[0]
119        VMLAL.S16 q10, d10, d2[0]
120        VMLAL.S16 q11, d11, d2[0]
121        VMLAL.S16 q12, d10, d4[0]
122        VMLAL.S16 q13, d11, d4[0]
123        VMLAL.S16 q14, d10, d6[0]
124        VMLAL.S16 q15, d11, d6[0]
125
126        VLD1.8  {d10},  [r9]!
127
128        VMOVL.S8 q5, d10
129        VMLAL.S16 q8, d10, d0[1]
130        VMLAL.S16 q9, d11, d0[1]
131        VMLAL.S16 q10, d10, d2[1]
132        VMLAL.S16 q11, d11, d2[1]
133        VMLAL.S16 q12, d10, d4[1]
134        VMLAL.S16 q13, d11, d4[1]
135        VMLAL.S16 q14, d10, d6[1]
136        VMLAL.S16 q15, d11, d6[1]
137
138        VLD1.8  {d10},  [r9]!
139        VMOVL.S8 q5, d10
140        VMLAL.S16 q8, d10, d0[2]
141        VMLAL.S16 q9, d11, d0[2]
142        VMLAL.S16 q10, d10, d2[2]
143        VMLAL.S16 q11, d11, d2[2]
144        VMLAL.S16 q12, d10, d4[2]
145        VMLAL.S16 q13, d11, d4[2]
146        VMLAL.S16 q14, d10, d6[2]
147        VMLAL.S16 q15, d11, d6[2]
148
149        VLD1.8  {d10},  [r9]!
150        VMOVL.S8 q5, d10
151        VMLAL.S16 q8, d10, d0[3]
152        VMLAL.S16 q9, d11, d0[3]
153        VMLAL.S16 q10, d10, d2[3]
154        VMLAL.S16 q11, d11, d2[3]
155        VMLAL.S16 q12, d10, d4[3]
156        VMLAL.S16 q13, d11, d4[3]
157        VMLAL.S16 q14, d10, d6[3]
158        VMLAL.S16 q15, d11, d6[3]
159
160        VLD1.8  {d10},  [r9]!
161        VMOVL.S8 q5, d10
162        VMLAL.S16 q8, d10, d1[0]
163        VMLAL.S16 q9, d11, d1[0]
164        VMLAL.S16 q10, d10, d3[0]
165        VMLAL.S16 q11, d11, d3[0]
166        VMLAL.S16 q12, d10, d5[0]
167        VMLAL.S16 q13, d11, d5[0]
168        VMLAL.S16 q14, d10, d7[0]
169        VMLAL.S16 q15, d11, d7[0]
170
171        VLD1.8  {d10},  [r9]!
172        VMOVL.S8 q5, d10
173        VMLAL.S16 q8, d10, d1[1]
174        VMLAL.S16 q9, d11, d1[1]
175        VMLAL.S16 q10, d10, d3[1]
176        VMLAL.S16 q11, d11, d3[1]
177        VMLAL.S16 q12, d10, d5[1]
178        VMLAL.S16 q13, d11, d5[1]
179        VMLAL.S16 q14, d10, d7[1]
180        VMLAL.S16 q15, d11, d7[1]
181
182        VLD1.8  {d10},  [r9]!
183        VMOVL.S8 q5, d10
184        VMLAL.S16 q8, d10, d1[2]
185        VMLAL.S16 q9, d11, d1[2]
186        VMLAL.S16 q10, d10, d3[2]
187        VMLAL.S16 q11, d11, d3[2]
188        VMLAL.S16 q12, d10, d5[2]
189        VMLAL.S16 q13, d11, d5[2]
190        VMLAL.S16 q14, d10, d7[2]
191        VMLAL.S16 q15, d11, d7[2]
192
193        VLD1.8  {d10},  [r9]!
194        VMOVL.S8 q5, d10
195        VMLAL.S16 q8, d10, d1[3]
196        VMLAL.S16 q9, d11, d1[3]
197        VMLAL.S16 q10, d10, d3[3]
198        VMLAL.S16 q11, d11, d3[3]
199        VMLAL.S16 q12, d10, d5[3]
200        VMLAL.S16 q13, d11, d5[3]
201        VMLAL.S16 q14, d10, d7[3]
202        VMLAL.S16 q15, d11, d7[3]
203        BHS     1b
204
205        # Is there a remainder?- 1-7 bytes of A
206        ADDS    r5, r5, 8
207        BNE     3f
208
2092:
210        # QC8 FP32 quantization
211        VLD1.8  {q0-q1},  [r9]!
212
213        VDUP.32 q2, d12[0]              // magic_bias
214        VDUP.32 q3, d12[1]              // magic_bias_less_output_zero_point
215
216        VCVT.F32.S32 q8,  q8
217        VCVT.F32.S32 q9,  q9
218        VCVT.F32.S32 q10, q10
219        VCVT.F32.S32 q11, q11
220        VCVT.F32.S32 q12, q12
221        VCVT.F32.S32 q13, q13
222        VCVT.F32.S32 q14, q14
223        VCVT.F32.S32 q15, q15
224
225        VMUL.F32 q8,  q8, q0            // multiplier
226        VMUL.F32 q9,  q9, q1
227        VMUL.F32 q10, q10, q0
228        VMUL.F32 q11, q11, q1
229        VMUL.F32 q12, q12, q0
230        VMUL.F32 q13, q13, q1
231        VMUL.F32 q14, q14, q0
232        VMUL.F32 q15, q15, q1
233
234        VADD.F32 q8,  q8, q2            // magic_bias
235        VADD.F32 q9,  q9, q2
236        VADD.F32 q10, q10, q2
237        VADD.F32 q11, q11, q2
238        VADD.F32 q12, q12, q2
239        VADD.F32 q13, q13, q2
240        VADD.F32 q14, q14, q2
241        VADD.F32 q15, q15, q2
242
243        VQSUB.S32 q8,  q8, q3           // magic_bias_less_output_zero_point
244        VQSUB.S32 q9,  q9, q3
245        VQSUB.S32 q10, q10, q3
246        VQSUB.S32 q11, q11, q3
247        VQSUB.S32 q12, q12, q3
248        VQSUB.S32 q13, q13, q3
249        VQSUB.S32 q14, q14, q3
250        VQSUB.S32 q15, q15, q3
251
252
253        VQMOVN.S32 d16, q8
254        VQMOVN.S32 d17, q9
255        VQMOVN.S32 d18, q10
256        VQMOVN.S32 d19, q11
257        VQMOVN.S32 d20, q12
258        VQMOVN.S32 d21, q13
259        VQMOVN.S32 d22, q14
260        VQMOVN.S32 d23, q15
261
262
263        VDUP.8  q12, d13[6]             // output_min
264
265        VQMOVN.S16 d0,  q8
266        VQMOVN.S16 d1,  q9
267        VQMOVN.S16 d2, q10
268        VQMOVN.S16 d3, q11
269
270        VDUP.8  q13, d13[7]             // output_max
271
272        VMAX.S8 q0, q0, q12
273        VMAX.S8 q1, q1, q12
274
275        SUBS    r1, r1, 8
276
277        VMIN.S8 q0, q0, q13
278        VMIN.S8 q1, q1, q13
279
280        # Store full 4 x 8
281        BLO     4f
282        VST1.8  {d0}, [r11], r7
283        SUB     r3, r3, r2
284        VST1.8  {d1}, [r4], r7
285        SUB     r12, r12, r2
286        VST1.8  {d2}, [r8], r7
287        SUB     r10, r10, r2
288        VST1.8  {d3}, [r6], r7
289        SUB     r0, r0, r2
290        BHI     0b
291
292        VPOP    {d10-d13}
293        ADD     sp, sp, 8
294        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
295        BX      lr
296
297        # Remainder- 1 to 7 bytes of A
298        .p2align 3
2993:
300        AND     r5, r5, 7               // kc remainder 1 to 7
301
302        VLD1.8  {d0},  [r3], r5
303        VLD1.8  {d10},  [r9]!
304        VLD1.8  {d2}, [r12], r5
305        VLD1.8  {d4}, [r10], r5
306        VLD1.8  {d6},  [r0], r5
307
308        VMOVL.S8 q0, d0
309        VMOVL.S8 q5, d10
310        VMOVL.S8 q1, d2
311        VMOVL.S8 q2, d4
312        VMOVL.S8 q3, d6
313        VMLAL.S16 q8, d10, d0[0]
314        VMLAL.S16 q9, d11, d0[0]
315        VMLAL.S16 q10, d10, d2[0]
316        VMLAL.S16 q11, d11, d2[0]
317        VMLAL.S16 q12, d10, d4[0]
318        VMLAL.S16 q13, d11, d4[0]
319        VMLAL.S16 q14, d10, d6[0]
320        VMLAL.S16 q15, d11, d6[0]
321        CMP     r5, 2
322        BLO     2b
323
324        VLD1.8  {d10},  [r9]!
325        VMOVL.S8 q5, d10
326        VMLAL.S16 q8, d10, d0[1]
327        VMLAL.S16 q9, d11, d0[1]
328        VMLAL.S16 q10, d10, d2[1]
329        VMLAL.S16 q11, d11, d2[1]
330        VMLAL.S16 q12, d10, d4[1]
331        VMLAL.S16 q13, d11, d4[1]
332        VMLAL.S16 q14, d10, d6[1]
333        VMLAL.S16 q15, d11, d6[1]
334        BEQ     2b
335
336        VLD1.8  {d10},  [r9]!
337        VMOVL.S8 q5, d10
338        VMLAL.S16 q8, d10, d0[2]
339        VMLAL.S16 q9, d11, d0[2]
340        VMLAL.S16 q10, d10, d2[2]
341        VMLAL.S16 q11, d11, d2[2]
342        VMLAL.S16 q12, d10, d4[2]
343        VMLAL.S16 q13, d11, d4[2]
344        VMLAL.S16 q14, d10, d6[2]
345        VMLAL.S16 q15, d11, d6[2]
346        CMP     r5, 4
347        BLO     2b
348
349        VLD1.8  {d10},  [r9]!
350        VMOVL.S8 q5, d10
351        VMLAL.S16 q8, d10, d0[3]
352        VMLAL.S16 q9, d11, d0[3]
353        VMLAL.S16 q10, d10, d2[3]
354        VMLAL.S16 q11, d11, d2[3]
355        VMLAL.S16 q12, d10, d4[3]
356        VMLAL.S16 q13, d11, d4[3]
357        VMLAL.S16 q14, d10, d6[3]
358        VMLAL.S16 q15, d11, d6[3]
359        BEQ     2b
360
361        VLD1.8  {d10},  [r9]!
362        VMOVL.S8 q5, d10
363        VMLAL.S16 q8, d10, d1[0]
364        VMLAL.S16 q9, d11, d1[0]
365        VMLAL.S16 q10, d10, d3[0]
366        VMLAL.S16 q11, d11, d3[0]
367        VMLAL.S16 q12, d10, d5[0]
368        VMLAL.S16 q13, d11, d5[0]
369        VMLAL.S16 q14, d10, d7[0]
370        VMLAL.S16 q15, d11, d7[0]
371        CMP     r5, 6
372        BLO     2b
373
374        VLD1.8  {d10},  [r9]!
375        VMOVL.S8 q5, d10
376        VMLAL.S16 q8, d10, d1[1]
377        VMLAL.S16 q9, d11, d1[1]
378        VMLAL.S16 q10, d10, d3[1]
379        VMLAL.S16 q11, d11, d3[1]
380        VMLAL.S16 q12, d10, d5[1]
381        VMLAL.S16 q13, d11, d5[1]
382        VMLAL.S16 q14, d10, d7[1]
383        VMLAL.S16 q15, d11, d7[1]
384        BEQ     2b
385
386        VLD1.8  {d10},  [r9]!
387        VMOVL.S8 q5, d10
388        VMLAL.S16 q8, d10, d1[2]
389        VMLAL.S16 q9, d11, d1[2]
390        VMLAL.S16 q10, d10, d3[2]
391        VMLAL.S16 q11, d11, d3[2]
392        VMLAL.S16 q12, d10, d5[2]
393        VMLAL.S16 q13, d11, d5[2]
394        VMLAL.S16 q14, d10, d7[2]
395        VMLAL.S16 q15, d11, d7[2]
396        B       2b
397
398        # Store odd width
399        .p2align 3
4004:
401        TST     r1, 4
402        BEQ     5f
403        VST1.32 {d0[0]}, [r11]!
404        VST1.32 {d1[0]}, [r4]!
405        VST1.32 {d2[0]}, [r8]!
406        VST1.32 {d3[0]}, [r6]!
407        VEXT.8  q0, q0, q0, 4
408        VEXT.8  q1, q1, q1, 4
4095:
410        TST     r1, 2
411        BEQ     6f
412        VST1.16 {d0[0]}, [r11]!
413        VST1.16 {d1[0]}, [r4]!
414        VST1.16 {d2[0]}, [r8]!
415        VST1.16 {d3[0]}, [r6]!
416        VEXT.8  q0, q0, q0, 2
417        VEXT.8  q1, q1, q1, 2
418
4196:
420        TST     r1, 1
421        BEQ     7f
422        VST1.8  {d0[0]}, [r11]
423        VST1.8  {d1[0]}, [r4]
424        VST1.8  {d2[0]}, [r8]
425        VST1.8  {d3[0]}, [r6]
426
4277:
428        VPOP    {d10-d13}
429        ADD     sp, sp, 8
430        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
431        BX      lr
432
433END_FUNCTION xnn_qc8_gemm_minmax_fp32_ukernel_4x8__aarch32_neon_mlal_lane_ld64
434
435#ifdef __ELF__
436.section ".note.GNU-stack","",%progbits
437#endif
438
439