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