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