xref: /aosp_15_r20/external/XNNPACK/src/f32-gemm/gen/4x8-minmax-aarch32-neon-prfm-cortex-a75.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/f32-gemm/4x8-aarch32-neon-cortex-a75.S.in
3//   Generator: tools/xngen
4//
5// Copyright 2019 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#include <xnnpack/assembly.h>
11
12.syntax unified
13
14// void xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_prfm_cortex_a75(
15//     size_t mr,                            r0
16//     size_t nc,                            r1
17//     size_t kc,                            r2 -> r5
18//     const uint8_t*restrict a,             r3
19//     size_t a_stride,          sp + 96  -> (r7)
20//     const void*restrict w,    sp + 100 -> r9
21//     uint8_t*restrict c,       sp + 104 -> r11
22//     size_t cm_stride,         sp + 108 -> (r6)
23//     size_t cn_stride,         sp + 112 -> r7
24//     const union xnn_f32_minmax_params params)  sp + 116 -> (r7)
25
26// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
27
28// Register usage
29// A0   r3  d0
30// A1  r12  d1
31// A2  r10  d2
32// A3   r0  d3
33
34// B    r9  d8,  d9, d10, d11
35// B       d12, d13, d14, d15
36
37// C0  r11 d16-d17  q8  d18-d19  q9
38// C1   r4 d20-d21 q10  d22-d23 q11
39// C2   r8 d24-d25 q12  d26-d27 q13
40// C3   r6 d28-d29 q14  d30-d31 q15
41
42// Clamp (r5) d4 d5 d6 d7
43
44BEGIN_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_prfm_cortex_a75
45        .arm
46#ifndef __APPLE__
47        .arch   armv7-a
48        .fpu    neon
49#endif
50        # Push 96 bytes
51        PUSH    {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
52        VPUSH   {d8-d15}                            // +64 = 96
53
54        LDR     r7, [sp, 96]            // a_stride
55        LDR     r6, [sp, 108]           // cm_stride
56        LDR     r11, [sp, 104]          // c
57        LDR     r9, [sp, 100]           // w
58
59        # Clamp A and C pointers
60        CMP     r0, 2                   // if mr >= 2
61        ADD     r12, r3, r7             //   a1 = a0 + a_stride
62        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
63        MOVLO   r12, r3                 // a1
64        MOVLO   r4, r11                 // c1
65                                        // if mr > 2
66        ADD     r10, r12, r7            //   a2 = a1 + a_stride
67        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
68        MOVLS   r10, r12                // a2
69        MOVLS   r8, r4                  // c2
70
71        CMP     r0, 4                   // if mr >=4
72        ADD     r0, r10, r7             //   a3 = a2 + a_stride
73        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
74        MOVLO   r0, r10                 // a3
75        MOVLO   r6, r8                  // c3
76
77        LDR     r7, [sp, 112]           // cn_stride
78
79        .p2align 3
800:
81        # Load initial bias from w into accumulators
82        VLDM    r9!, {d16-d19}          // Bias
83        SUBS    r5, r2, 16
84        VMOV    q10, q8
85        VMOV    q11, q9
86        VMOV    q12, q8
87        VMOV    q13, q9
88        VMOV    q14, q8
89        VMOV    q15, q9
90
91        PLD     [r3,  0]                // Prefetch A
92        PLD     [r3, 64]
93        PLD     [r12,  0]
94        PLD     [r12, 64]
95        PLD     [r10,  0]
96        PLD     [r10, 64]
97        PLD     [r0,  0]
98        PLD     [r0, 64]
99        PLD     [r9,   0]               // Prefetch B
100        PLD     [r9,  64]
101        PLD     [r9, 128]
102        PLD     [r9, 192]
103        PLD     [r9, 256]
104        PLD     [r9, 320]
105        PLD     [r9, 384]
106
107        BLO     4f                      // less than 4 channels?
108
109        # Prologue
110        VLD1.32 {d0}, [r3]!             // A0
111        VLDM    r9!, {d8-d11}           // B0
112        VLD1.32 {d1}, [r12]!            // A1
113        VLD1.32 {d2}, [r10]!            // A2
114        VLD1.32 {d3}, [ r0]!            // A3
115
116        SUBS    r5, r5, 16
117        BLO     2f                      // less than 4 channels?  skip main loop
118
119        .p2align 3
120
121        # Main loop - 4 floats of A (16 bytes)
1221:
123        VMLA.F32 q8, q4, d0[0]
124        VLDM    r9!, {d12-d15}          // B1
125        VMLA.F32 q10, q4, d1[0]
126        VMLA.F32 q12, q4, d2[0]
127        VLD1.32 {d4}, [r3]!             // A0
128        VMLA.F32 q14, q4, d3[0]
129        VMLA.F32 q9, q5, d0[0]
130        VLD1.32 {d5}, [r12]!            // A1
131        VMLA.F32 q11, q5, d1[0]
132        VMLA.F32 q13, q5, d2[0]
133        VMLA.F32 q15, q5, d3[0]
134        VLD1.32 {d6}, [r10]!            // A2
135        VMLA.F32 q8, q6, d0[1]
136        VMLA.F32 q10, q6, d1[1]
137        VLD1.32 {d7}, [ r0]!            // A3
138        VMLA.F32 q12, q6, d2[1]
139        VMLA.F32 q14, q6, d3[1]
140        VLDM    r9!, {d8-d11}           // B0
141        VMLA.F32 q9, q7, d0[1]
142        VMLA.F32 q11, q7, d1[1]
143        VMLA.F32 q13, q7, d2[1]
144        VMLA.F32 q15, q7, d3[1]
145
146        VMLA.F32 q8, q4, d4[0]
147        VLDM    r9!, {d12-d15}          // B1
148        VMLA.F32 q10, q4, d5[0]
149        PLD     [r3, 128]               // Prefetch A0
150        VMLA.F32 q12, q4, d6[0]
151        VLD1.32 {d0}, [r3]!             // A0
152        VMLA.F32 q14, q4, d7[0]
153        PLD     [r12, 128]              // Prefetch A1
154        VMLA.F32 q9, q5, d4[0]
155        VLD1.32 {d1}, [r12]!            // A1
156        VMLA.F32 q11, q5, d5[0]
157        PLD     [r10, 128]              // Prefetch A2
158        VMLA.F32 q13, q5, d6[0]
159        VLD1.32 {d2}, [r10]!            // A2
160        VMLA.F32 q15, q5, d7[0]
161        PLD     [r0, 128]               // Prefetch A3
162        VMLA.F32 q8, q6, d4[1]
163        VLD1.32 {d3}, [ r0]!            // A3
164        VMLA.F32 q10, q6, d5[1]
165        PLD     [r9, 352]               // Prefetch B
166        VMLA.F32 q12, q6, d6[1]
167        PLD     [r9, 416]               // Prefetch B
168        VMLA.F32 q14, q6, d7[1]
169        VLDM    r9!, {d8-d11}           // B0
170        VMLA.F32 q9, q7, d4[1]
171        VMLA.F32 q11, q7, d5[1]
172        SUBS    r5, r5, 16
173        VMLA.F32 q13, q7, d6[1]
174        VMLA.F32 q15, q7, d7[1]
175        BHS     1b
176
177        # Epilogue
1782:
179        VMLA.F32 q8, q4, d0[0]
180        VLDM    r9!, {d12-d15}          // B1
181        VMLA.F32 q10, q4, d1[0]
182        VMLA.F32 q12, q4, d2[0]
183        VLD1.32 {d4}, [r3]!             // A0
184        VMLA.F32 q14, q4, d3[0]
185        VMLA.F32 q9, q5, d0[0]
186        VLD1.32 {d5}, [r12]!            // A1
187        VMLA.F32 q11, q5, d1[0]
188        VMLA.F32 q13, q5, d2[0]
189        VMLA.F32 q15, q5, d3[0]
190        VLD1.32 {d6}, [r10]!            // A2
191        VMLA.F32 q8, q6, d0[1]
192        VMLA.F32 q10, q6, d1[1]
193        VLD1.32 {d7}, [ r0]!            // A3
194        VMLA.F32 q12, q6, d2[1]
195        VMLA.F32 q14, q6, d3[1]
196        VLDM    r9!, {d8-d11}           // B0
197        VMLA.F32 q9, q7, d0[1]
198        VMLA.F32 q11, q7, d1[1]
199        VMLA.F32 q13, q7, d2[1]
200        VMLA.F32 q15, q7, d3[1]
201
202        VMLA.F32 q8, q4, d4[0]
203        VLDM    r9!, {d12-d15}          // B1
204        VMLA.F32 q10, q4, d5[0]
205        VMLA.F32 q12, q4, d6[0]
206        VMLA.F32 q14, q4, d7[0]
207        VMLA.F32 q9, q5, d4[0]
208        VMLA.F32 q11, q5, d5[0]
209        VMLA.F32 q13, q5, d6[0]
210        VMLA.F32 q15, q5, d7[0]
211        VMLA.F32 q8, q6, d4[1]
212        VMLA.F32 q10, q6, d5[1]
213        VMLA.F32 q12, q6, d6[1]
214        VMLA.F32 q14, q6, d7[1]
215        VMLA.F32 q9, q7, d4[1]
216        VMLA.F32 q11, q7, d5[1]
217        TST     r5, 15
218        VMLA.F32 q13, q7, d6[1]
219        VMLA.F32 q15, q7, d7[1]
220
221        # Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes)
222        BNE     4f
223
224        .p2align 3
2253:
226        # Load params pointer
227        LDR     r5, [sp, 116]           // params
228
229        # Load min/max values
230        VLD1.32 {d4[],d5[]}, [r5]!
231        SUBS    r1, r1, 8
232        VLD1.32 {d6[],d7[]}, [r5]
233
234        # Clamp
235        VMAX.F32 q8,  q8, q2
236        VMAX.F32 q9,  q9, q2
237        VMAX.F32 q10, q10, q2
238        VMAX.F32 q11, q11, q2
239        VMAX.F32 q12, q12, q2
240        VMAX.F32 q13, q13, q2
241        VMAX.F32 q14, q14, q2
242        VMAX.F32 q15, q15, q2
243        VMIN.F32 q8,  q8, q3
244        VMIN.F32 q9,  q9, q3
245        VMIN.F32 q10, q10, q3
246        VMIN.F32 q11, q11, q3
247        VMIN.F32 q12, q12, q3
248        VMIN.F32 q13, q13, q3
249        VMIN.F32 q14, q14, q3
250        VMIN.F32 q15, q15, q3
251
252        # Store full 4 x 8
253        BLO     6f
254        VST1.32 {d16-d19}, [r11], r7
255        SUB     r0, r0, r2
256        VST1.32 {d20-d23}, [r4], r7
257        SUB     r10, r10, r2
258        VST1.32 {d24-d27}, [r8], r7
259        SUB     r12, r12, r2
260        VST1.32 {d28-d31}, [r6], r7
261        SUB     r3, r3, r2
262        BHI     0b
263
264        VPOP    {d8-d15}
265        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
266        BX      lr
267
268        .p2align 3
2694:
270        # Is there a remainder?- 2 floats of A (8 bytes)
271        TST     r5, 8
272        BEQ     5f
273
274        # Remainder - 2 floats of A (8 bytes)
275        VLD1.32 {d0}, [r3]!             // A0
276        VLDM    r9!, {d8-d11}           // B0
277        VLD1.32 {d1}, [r12]!            // A1
278        VLD1.32 {d2}, [r10]!            // A2
279        VLD1.32 {d3}, [ r0]!            // A3
280
281        VMLA.F32 q8, q4, d0[0]
282        VMLA.F32 q9, q5, d0[0]
283        VMLA.F32 q10, q4, d1[0]
284        VMLA.F32 q11, q5, d1[0]
285        VLDM    r9!, {d12-d15}          // B1
286        VMLA.F32 q12, q4, d2[0]
287        VMLA.F32 q13, q5, d2[0]
288        VMLA.F32 q14, q4, d3[0]
289        VMLA.F32 q15, q5, d3[0]
290        VMLA.F32 q8, q6, d0[1]
291        VMLA.F32 q9, q7, d0[1]
292        VMLA.F32 q10, q6, d1[1]
293        VMLA.F32 q11, q7, d1[1]
294        VMLA.F32 q12, q6, d2[1]
295        VMLA.F32 q13, q7, d2[1]
296        VMLA.F32 q14, q6, d3[1]
297        VMLA.F32 q15, q7, d3[1]
298
299        # Is there a remainder?- 1 float of A (4 bytes)
300        TST     r5, 4
301        BEQ     3b
302
3035:
304        # Remainder- 1 float of A (4 bytes)
305        VLDM    r3!,  {s0}              // A0
306        VLDM    r9!, {d8-d11}           // B0
307        VLDM    r12!, {s2}              // A1
308        VLDM    r10!, {s4}              // A2
309        VLDM    r0!, {s6}               // A3
310        VMLA.F32 q8, q4, d0[0]
311        VMLA.F32 q9, q5, d0[0]
312        VMLA.F32 q10, q4, d1[0]
313        VMLA.F32 q11, q5, d1[0]
314        VMLA.F32 q12, q4, d2[0]
315        VMLA.F32 q13, q5, d2[0]
316        VMLA.F32 q14, q4, d3[0]
317        VMLA.F32 q15, q5, d3[0]
318        B       3b
319
320        # Store odd width
3216:
322        TST     r1, 4
323        BEQ     7f
324        VST1.32 {d16-d17}, [r11]!
325        VST1.32 {d20-d21},  [r4]!
326        VMOV    q8,  q9
327        VMOV    q10, q11
328        VST1.32 {d24-d25},  [r8]!
329        VST1.32 {d28-d29},  [r6]!
330        VMOV    q12, q13
331        VMOV    q14, q15
332
3337:
334        TST     r1, 2
335        BEQ     8f
336        VST1.32 {d16}, [r11]!
337        VST1.32 {d20},  [r4]!
338        VMOV    d16, d17
339        VMOV    d20, d21
340        VST1.32 {d24},  [r8]!
341        VST1.32 {d28},  [r6]!
342        VMOV    d24, d25
343        VMOV    d28, d29
344
3458:
346        TST     r1, 1
347        BEQ     9f
348        VST1.32 {d16[0]}, [r11]
349        VST1.32 {d20[0]},  [r4]
350        VST1.32 {d24[0]},  [r8]
351        VST1.32 {d28[0]},  [r6]
352
3539:
354        VPOP    {d8-d15}
355        POP     {r4, r5, r6, r7, r8, r9, r10, r11}
356        BX      lr
357
358END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_prfm_cortex_a75
359
360#ifdef __ELF__
361.section ".note.GNU-stack","",%progbits
362#endif
363
364