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