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