blob: 2251e8fffd1d35f29cef72a3a42686be04763021 [file] [log] [blame]
Frank Barchardb7dd29e2020-03-11 12:37:10 -07001// Copyright 2019 Google LLC
2//
3// This source code is licensed under the BSD-style license found in the
4// LICENSE file in the root directory of this source tree.
5
6#include <xnnpack/assembly.h>
7
8.syntax unified
9
10// void xnn_f32_gemm_ukernel_4x8__aarch32_neon_cortex_a55(
11// size_t mr, r0
12// size_t nc, r1
Frank Barchard36053aa2020-03-12 12:28:55 -070013// size_t kc, r2 -> r5
Frank Barchardb7dd29e2020-03-11 12:37:10 -070014// const uint8_t*restrict a, r3
Frank Barchard36053aa2020-03-12 12:28:55 -070015// size_t a_stride, sp + 96 -> (r7)
16// const void*restrict w, sp + 100 -> r9
17// uint8_t*restrict c, sp + 104 -> r11
18// size_t cm_stride, sp + 108 -> (r6)
19// size_t cn_stride, sp + 112 -> (r0)
Marat Dukhaneb09a6b2020-04-08 17:34:32 -070020// minmax_params*params, sp + 116 -> (r5)
Frank Barchardb7dd29e2020-03-11 12:37:10 -070021
22// inner loop registers
Frank Barchardb7dd29e2020-03-11 12:37:10 -070023// r14 (lr) unused
24
25// A0 r3 d0
26// A1 r12 d1
27// A2 r10 d2
28// A3 r7 d3
29
30// B r9 d8, d9, d10, d11
31// B d12, d13, d14, d15
32
33// C0 r11 d16-d17 q8 d18-d19 q9
34// C1 r4 d20-d21 q10 d22-d23 q11
35// C2 r8 d24-d25 q12 d26-d27 q13
36// C3 r6 d28-d29 q14 d30-d31 q15
37
38// Clamp (r5) d4 d5 d6 d7
39
40BEGIN_FUNCTION xnn_f32_gemm_ukernel_4x8__aarch32_neon_cortex_a55
41 .arm
42#ifndef __APPLE__
43 .arch armv7-a
44 .fpu neon
45#endif
Frank Barchard36053aa2020-03-12 12:28:55 -070046 // Push 96 bytes
47 VPUSH {d8-d15} // 64
48 PUSH {r4, r5, r6, r7, r8, r9, r10, r11} // +32 = 96
Frank Barchardb7dd29e2020-03-11 12:37:10 -070049
Frank Barchard36053aa2020-03-12 12:28:55 -070050 LDR r7, [sp, 96] // a_stride
51 LDR r11, [sp, 104] // c
52 LDR r6, [sp, 108] // cm_stride
53 LDR r9, [sp, 100] // w
Frank Barchardb7dd29e2020-03-11 12:37:10 -070054
55 // Clamp A and C pointers
56 CMP r0, 2 // if mr >= 2
57 ADD r12, r3, r7 // a1 = a0 + a_stride
58 ADD r4, r11, r6 // c1 = c0 + cm_stride
59 MOVLO r12, r3 // a1
60 MOVLO r4, r11 // c1
61 // if mr > 2
62 ADD r10, r12, r7 // a2 = a1 + a_stride
63 ADD r8, r4, r6 // c2 = c1 + cm_stride
64 MOVLS r10, r12 // a2
65 MOVLS r8, r4 // c2
66
67 CMP r0, 4 // if mr >=4
68 ADD r7, r10, r7 // a3 = a2 + a_stride
69 ADD r6, r8, r6 // c3 = c2 + cm_stride
70 MOVLO r7, r10 // a3
71 MOVLO r6, r8 // c3
72
73 .p2align 3
741:
75 # Load initial bias from w into accumulators
76 VLDM r9!, {d16-d19} // Bias
77
78 SUBS r5, r2, 16 // kc - 16
79 PLD [r3, 0] // Prefetch A
80 PLD [r3, 64]
81 VMOV q10, q8
82 PLD [r12, 0]
83 PLD [r12, 64]
84 VMOV q11, q9
85 PLD [r10, 0]
86 PLD [r10, 64]
87 VMOV q12, q8
88 PLD [r7, 0]
89 PLD [r7, 64]
90 VMOV q13, q9
91 PLD [r9, 0] // Prefetch B
92 PLD [r9, 64]
93 VMOV q14, q8
94 PLD [r9, 128]
95 PLD [r9, 192]
96 VMOV q15, q9
97 PLD [r9, 256]
98 PLD [r9, 320]
99 BLO 5f // less than 4 channels?
100
101 // Prologue
102 VLD1.32 {d0}, [r3]! // A0
103 VLD1.32 {d1}, [r12]! // A1
104 VLD1.32 {d2}, [r10]! // A2
105 VLD1.32 {d3}, [r7]! // A3
106 SUBS r5, r5, 16
107 VLDM r9, {d8-d11} // B0
108 VLDR d15, [r9, 56] // B1CK 0
109 VLDR d13, [r9, 40] // B1
110 BLO 3f // less than 4 channels? skip main loop
111
112 # Main loop - 4 floats of A (16 bytes)
113 # 32 FMA + 8 LD64 A + 8 LDR B
114 .p2align 3
1152:
116 # First group of 16 FMA, Second group loads
117 // BLOCK 0
118 VMLA.F32 q8, q4, d0[0]
119 VLD1.32 {d4}, [r3]! // A0
120 VMLA.F32 q10, q4, d1[0]
121 VLD1.32 {d5}, [r12]! // A1
122 VMLA.F32 q12, q4, d2[0]
123
124 // BLOCK 1
125 VMLA.F32 q14, q4, d3[0]
126 VLDR d12, [r9, 32] // B1
127 VMLA.F32 q9, q5, d0[0]
128 VLDR d9, [r9, 72] // B0
129 VMLA.F32 q11, q5, d1[0]
130
131 // BLOCK 2
132 VMLA.F32 q13, q5, d2[0]
133 VLD1.32 {d6}, [r10]! // A2
134 VMLA.F32 q15, q5, d3[0]
135 VLD1.32 {d7}, [r7]! // A3
136 VMLA.F32 q8, q6, d0[1]
137
138 // BLOCK 3
139 VMLA.F32 q10, q6, d1[1]
140 VLDR d14, [r9, 48] // B1
141 VMLA.F32 q12, q6, d2[1]
142 VLDR d11, [r9, 88] // B0
143 VMLA.F32 q14, q6, d3[1]
144
145 // BLOCK 4
146 VMLA.F32 q9, q7, d0[1]
147 VLDR d8, [r9, 64] // B0
148 VMLA.F32 q11, q7, d1[1]
149 VLDR d13, [r9, 104] // B1
150 VMLA.F32 q13, q7, d2[1]
151 VLDR d10, [r9, 80] // B0
152
153 // BLOCK 5
154 VMLA.F32 q15, q7, d3[1]
155 VLDR d15, [r9, 120] // B1
156
157 # Second group of 16 FMA, First group of loads
158 // BLOCK 0
159 VMLA.F32 q8, q4, d4[0]
160 VLD1.32 {d0}, [r3]! // A0
161 VMLA.F32 q10, q4, d5[0]
162 VLD1.32 {d1}, [r12]! // A1
163 VMLA.F32 q12, q4, d6[0]
164
165 // BLOCK 1
166 VMLA.F32 q14, q4, d7[0]
167 VLDR d12, [r9, 96] // B1
168 VMLA.F32 q9, q5, d4[0]
169 VLDR d9, [r9, 136] // B0
170 VMLA.F32 q11, q5, d5[0]
171
172 // BLOCK 2
173 VMLA.F32 q13, q5, d6[0]
174 VLD1.32 {d2}, [r10]! // A2
175 VMLA.F32 q15, q5, d7[0]
176 VLD1.32 {d3}, [r7]! // A3
177 VMLA.F32 q8, q6, d4[1]
178
179 // BLOCK 3
180 VMLA.F32 q10, q6, d5[1]
181 VLDR d14, [r9, 112] // B1
182 VMLA.F32 q12, q6, d6[1]
183 VLDR d11, [r9, 152] // B0
184 VMLA.F32 q14, q6, d7[1]
185 SUBS r5, r5, 16
186
187 // BLOCK 4
188 VMLA.F32 q9, q7, d4[1]
189 VLDR d8, [r9, 128] // B0
190 VMLA.F32 q11, q7, d5[1]
191 VLDR d13, [r9, 168] // B1
192 VMLA.F32 q13, q7, d6[1]
193 VLDR d10, [r9, 144] // B0
194
195 // BLOCK 5
196 VMLA.F32 q15, q7, d7[1]
197 VLDR d15, [r9, 184] // B1
198 ADD r9, r9, 128 // B++
199 BHS 2b
200
201
202 # Epilogue - 4 floats of A (16 bytes)
2033:
204 # First group of 16 FMA, Second group loads
205 // BLOCK 0
206 VMLA.F32 q8, q4, d0[0]
207 VLD1.32 {d4}, [r3]! // A0
208 VMLA.F32 q10, q4, d1[0]
209 VLD1.32 {d5}, [r12]! // A1
210 VMLA.F32 q12, q4, d2[0]
211
212 // BLOCK 1
213 VMLA.F32 q14, q4, d3[0]
214 VLDR d12, [r9, 32] // B1
215 VMLA.F32 q9, q5, d0[0]
216 VLDR d9, [r9, 72] // B0
217 VMLA.F32 q11, q5, d1[0]
218
219 // BLOCK 2
220 VMLA.F32 q13, q5, d2[0]
221 VLD1.32 {d6}, [r10]! // A2
222 VMLA.F32 q15, q5, d3[0]
223 VLD1.32 {d7}, [r7]! // A3
224 VMLA.F32 q8, q6, d0[1]
225
226 // BLOCK 3
227 VMLA.F32 q10, q6, d1[1]
228 VLDR d14, [r9, 48] // B1
229 VMLA.F32 q12, q6, d2[1]
230 VLDR d11, [r9, 88] // B0
231 VMLA.F32 q14, q6, d3[1]
232
233 // BLOCK 4
234 VMLA.F32 q9, q7, d0[1]
235 VLDR d8, [r9, 64] // B0
236 VMLA.F32 q11, q7, d1[1]
237 VLDR d13, [r9, 104] // B1
238 VMLA.F32 q13, q7, d2[1]
239 VLDR d10, [r9, 80] // B0
240
241 // BLOCK 5
242 VMLA.F32 q15, q7, d3[1]
243 VLDR d15, [r9, 120] // B1
244
245 # Second group of 16 FMA, First group of loads
246 // BLOCK 0
247 VMLA.F32 q8, q4, d4[0]
248 VLDR d12, [r9, 96] // B1
249 VMLA.F32 q10, q4, d5[0]
250 VMLA.F32 q12, q4, d6[0]
251
252 // BLOCK 1
253 VMLA.F32 q14, q4, d7[0]
254 VLDR d14, [r9, 112] // B1
255 VMLA.F32 q9, q5, d4[0]
256 VMLA.F32 q11, q5, d5[0]
257
258 // BLOCK 2
259 VMLA.F32 q13, q5, d6[0]
260 VMLA.F32 q15, q5, d7[0]
261 VMLA.F32 q8, q6, d4[1]
262 ADD r9, r9, 128 // B++
263
264 // BLOCK 3
265 VMLA.F32 q10, q6, d5[1]
266 VMLA.F32 q12, q6, d6[1]
267 VMLA.F32 q14, q6, d7[1]
268 TST r5, 15
269
270 // BLOCK 4
271 VMLA.F32 q9, q7, d4[1]
272 VMLA.F32 q11, q7, d5[1]
273 VMLA.F32 q13, q7, d6[1]
274
275 // BLOCK 5
276 VMLA.F32 q15, q7, d7[1]
277
278 // Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes)
279 BNE 5f
280
281 .p2align 3
2824:
283 // Load params pointer
Frank Barchard36053aa2020-03-12 12:28:55 -0700284 LDR r0, [sp, 112] // cn_stride
Marat Dukhaneb09a6b2020-04-08 17:34:32 -0700285 LDR r5, [sp, 116] // params
Frank Barchardb7dd29e2020-03-11 12:37:10 -0700286 SUBS r1, r1, 8
287
Marat Dukhaneb09a6b2020-04-08 17:34:32 -0700288 // Load min/max values
Frank Barchardb7dd29e2020-03-11 12:37:10 -0700289 VLD1.32 {d4[],d5[]}, [r5]!
290 VLD1.32 {d6[],d7[]}, [r5]
291
292 // Clamp
Marat Dukhana51cf482020-04-08 16:16:19 -0700293 VMAX.F32 q8, q8, q2
294 VMAX.F32 q9, q9, q2
295 VMAX.F32 q10, q10, q2
296 VMAX.F32 q11, q11, q2
297 VMAX.F32 q12, q12, q2
298 VMAX.F32 q13, q13, q2
299 VMAX.F32 q14, q14, q2
300 VMAX.F32 q15, q15, q2
301 VMIN.F32 q8, q8, q3
302 VMIN.F32 q9, q9, q3
303 VMIN.F32 q10, q10, q3
304 VMIN.F32 q11, q11, q3
305 VMIN.F32 q12, q12, q3
306 VMIN.F32 q13, q13, q3
307 VMIN.F32 q14, q14, q3
308 VMIN.F32 q15, q15, q3
Frank Barchardb7dd29e2020-03-11 12:37:10 -0700309
310 // Store full 4 x 8
311 BLO 10f
312 VST1.32 {d16-d19}, [r11], r0
313 SUB r7, r7, r2
314 VST1.32 {d20-d23}, [r4], r0
315 SUB r10, r10, r2
316 VST1.32 {d24-d27}, [r8], r0
317 SUB r12, r12, r2
318 VST1.32 {d28-d31}, [r6], r0
319 SUB r3, r3, r2
320 BHI 1b
321
Frank Barchardb7dd29e2020-03-11 12:37:10 -0700322 POP {r4, r5, r6, r7, r8, r9, r10, r11}
323 VPOP {d8-d15}
324 BX lr
325
326 .p2align 3
3275:
328 // Is there a remainder?- 2 floats of A (8 bytes)
329 TST r5, 8
330 BEQ 6f
331
332 // Remainder - 2 floats of A (8 bytes)
333 VLD1.32 {d0}, [r3]! // A0
334 VLDM r9!, {d8-d11} // B0
335 VLD1.32 {d1}, [r12]! // A1
336 VLD1.32 {d2}, [r10]! // A2
337 VLD1.32 {d3}, [ r7]! // A3
338
339 VMLA.F32 q8, q4, d0[0]
340 VMLA.F32 q9, q5, d0[0]
341 VMLA.F32 q10, q4, d1[0]
342 VMLA.F32 q11, q5, d1[0]
343 VLDM r9!, {d12-d15} // B1
344 VMLA.F32 q12, q4, d2[0]
345 VMLA.F32 q13, q5, d2[0]
346 VMLA.F32 q14, q4, d3[0]
347 VMLA.F32 q15, q5, d3[0]
348 VMLA.F32 q8, q6, d0[1]
349 VMLA.F32 q9, q7, d0[1]
350 VMLA.F32 q10, q6, d1[1]
351 VMLA.F32 q11, q7, d1[1]
352 VMLA.F32 q12, q6, d2[1]
353 VMLA.F32 q13, q7, d2[1]
354 VMLA.F32 q14, q6, d3[1]
355 VMLA.F32 q15, q7, d3[1]
356
357 // Is there a remainder?- 1 floats of A (4 bytes)
358 TST r5, 4
359 BEQ 4b
360
3616:
362 // Remainder- 1 floats of A (4 bytes)
363 VLDM r3!, {s0} // A0
364 VLDM r9!, {d8-d11} // B0
365 VLDM r12!, {s2} // A1
366 VLDM r10!, {s4} // A2
367 VLDM r7!, {s6} // A3
368 VMLA.F32 q8, q4, d0[0]
369 VMLA.F32 q9, q5, d0[0]
370 VMLA.F32 q10, q4, d1[0]
371 VMLA.F32 q11, q5, d1[0]
372 VMLA.F32 q12, q4, d2[0]
373 VMLA.F32 q13, q5, d2[0]
374 VMLA.F32 q14, q4, d3[0]
375 VMLA.F32 q15, q5, d3[0]
376 B 4b
377
378 // Store odd width
37910:
380 TST r1, 4
381 BEQ 11f
382 VST1.32 {d16-d17}, [r11]!
383 VMOV q8, q9
384 VST1.32 {d20-d21}, [r4]!
385 VMOV q10, q11
386 VST1.32 {d24-d25}, [r8]!
387 VMOV q12, q13
388 VST1.32 {d28-d29}, [r6]!
389 VMOV q14, q15
390
39111:
392 TST r1, 2
393 BEQ 12f
394 VST1.32 {d16}, [r11]!
395 VMOV d16, d17
396 VST1.32 {d20}, [r4]!
397 VMOV d20, d21
398 VST1.32 {d24}, [r8]!
399 VMOV d24, d25
400 VST1.32 {d28}, [r6]!
401 VMOV d28, d29
402
40312:
404 TST r1, 1
405 BEQ 13f
406 VST1.32 {d16[0]}, [r11]
407 VST1.32 {d20[0]}, [r4]
408 VST1.32 {d24[0]}, [r8]
409 VST1.32 {d28[0]}, [r6]
410
41113:
Frank Barchardb7dd29e2020-03-11 12:37:10 -0700412 POP {r4, r5, r6, r7, r8, r9, r10, r11}
413 VPOP {d8-d15}
414 BX lr
415
416END_FUNCTION xnn_f32_gemm_ukernel_4x8__aarch32_neon_cortex_a55
417
418#ifdef __ELF__
419.section ".note.GNU-stack","",%progbits
420#endif