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