• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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_minmax_ukernel_4x8__aarch32_neon_${"pld_" if PREFETCH else ""}cortex_a75(
11//     size_t mr,                            r0
12//     size_t nc,                            r1
13//     size_t kc,                            r2 -> r5
14//     const uint8_t*restrict a,             r3
15//     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 -> r7
20//     const union xnn_f32_minmax_params params[restrict XNN_MIN_ELEMENTS(1)])  sp + 116 -> (r7)
21
22
23// inner loop registers
24
25// A0   r3  d0
26// A1  r12  d1
27// A2  r10  d2
28// A3   r0  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_minmax_ukernel_4x8__aarch32_neon_${"pld_" if PREFETCH else ""}cortex_a75
41        .arm
42#ifndef __APPLE__
43        .arch armv7-a
44        .fpu neon
45#endif
46        // Push 96 bytes
47        PUSH   {r4, r5, r6, r7, r8, r9, r10, r11}  // 32
48        VPUSH  {d8-d15}                            // +64 = 96
49
50        LDR     r7, [sp, 96]         // a_stride
51        LDR     r6, [sp, 108]        // cm_stride
52        LDR    r11, [sp, 104]        // c
53        LDR     r9, [sp, 100]        // w
54
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    r0, r10, r7           //   a3 = a2 + a_stride
69        ADD    r6, r8, r6            //   c3 = c2 + cm_stride
70        MOVLO  r0, r10               // a3
71        MOVLO  r6, r8                // c3
72
73        LDR    r7, [sp, 112]         // cn_stride
74
75        .p2align 3
760:
77        # Load initial bias from w into accumulators
78        VLDM        r9!, {d16-d19}   // Bias
79        SUBS        r5, r2, 16
80        VMOV        q10, q8
81        VMOV        q11, q9
82        VMOV        q12, q8
83        VMOV        q13, q9
84        VMOV        q14, q8
85        VMOV        q15, q9
86
87        $if PREFETCH:
88          PLD         [r3,  0]    // Prefetch A
89          PLD         [r3, 64]
90          PLD         [r12,  0]
91          PLD         [r12, 64]
92          PLD         [r10,  0]
93          PLD         [r10, 64]
94          PLD         [r0,  0]
95          PLD         [r0, 64]
96          PLD         [r9,   0]  // Prefetch B
97          PLD         [r9,  64]
98          PLD         [r9, 128]
99          PLD         [r9, 192]
100          PLD         [r9, 256]
101          PLD         [r9, 320]
102          PLD         [r9, 384]
103
104        BLO         4f               // less than 4 channels?
105
106        // Prologue
107        VLD1.32    {d0}, [r3]!       // A0
108        VLDM        r9!, {d8-d11}    // B0
109        VLD1.32    {d1}, [r12]!      // A1
110        VLD1.32    {d2}, [r10]!      // A2
111        VLD1.32    {d3}, [ r0]!      // A3
112
113        SUBS        r5, r5, 16
114        BLO         2f               // less than 4 channels?  skip main loop
115
116        .p2align 3
117
118        // Main loop - 4 floats of A (16 bytes)
1191:
120        VMLA.F32     q8, q4, d0[0]
121        VLDM        r9!, {d12-d15}   // B1
122        VMLA.F32    q10, q4, d1[0]
123        VMLA.F32    q12, q4, d2[0]
124        VLD1.32    {d4}, [r3]!       // A0
125        VMLA.F32    q14, q4, d3[0]
126        VMLA.F32     q9, q5, d0[0]
127        VLD1.32    {d5}, [r12]!      // A1
128        VMLA.F32    q11, q5, d1[0]
129        VMLA.F32    q13, q5, d2[0]
130        VMLA.F32    q15, q5, d3[0]
131        VLD1.32    {d6}, [r10]!      // A2
132        VMLA.F32     q8, q6, d0[1]
133        VMLA.F32    q10, q6, d1[1]
134        VLD1.32    {d7}, [ r0]!      // A3
135        VMLA.F32    q12, q6, d2[1]
136        VMLA.F32    q14, q6, d3[1]
137        VLDM        r9!, {d8-d11}    // B0
138        VMLA.F32     q9, q7, d0[1]
139        VMLA.F32    q11, q7, d1[1]
140        VMLA.F32    q13, q7, d2[1]
141        VMLA.F32    q15, q7, d3[1]
142
143        VMLA.F32     q8, q4, d4[0]
144        VLDM        r9!, {d12-d15}   // B1
145        VMLA.F32    q10, q4, d5[0]
146        $if PREFETCH:
147          PLD         [r3, 128]        // Prefetch A0
148        VMLA.F32    q12, q4, d6[0]
149        VLD1.32    {d0}, [r3]!       // A0
150        VMLA.F32    q14, q4, d7[0]
151        $if PREFETCH:
152          PLD         [r12, 128]       // Prefetch A1
153        VMLA.F32     q9, q5, d4[0]
154        VLD1.32    {d1}, [r12]!      // A1
155        VMLA.F32    q11, q5, d5[0]
156        $if PREFETCH:
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        $if PREFETCH:
162          PLD         [r0, 128]        // Prefetch A3
163        VMLA.F32     q8, q6, d4[1]
164        VLD1.32    {d3}, [ r0]!      // A3
165        VMLA.F32    q10, q6, d5[1]
166        $if PREFETCH:
167          PLD         [r9, 352]        // Prefetch B
168        VMLA.F32    q12, q6, d6[1]
169        $if PREFETCH:
170          PLD         [r9, 416]        // Prefetch B
171        VMLA.F32    q14, q6, d7[1]
172        VLDM        r9!, {d8-d11}    // B0
173        VMLA.F32     q9, q7, d4[1]
174        VMLA.F32    q11, q7, d5[1]
175        SUBS         r5, r5, 16
176        VMLA.F32    q13, q7, d6[1]
177        VMLA.F32    q15, q7, d7[1]
178        BHS         1b
179
180        // Epilogue
1812:
182        VMLA.F32     q8, q4, d0[0]
183        VLDM        r9!, {d12-d15}   // B1
184        VMLA.F32    q10, q4, d1[0]
185        VMLA.F32    q12, q4, d2[0]
186        VLD1.32    {d4}, [r3]!       // A0
187        VMLA.F32    q14, q4, d3[0]
188        VMLA.F32     q9, q5, d0[0]
189        VLD1.32    {d5}, [r12]!      // A1
190        VMLA.F32    q11, q5, d1[0]
191        VMLA.F32    q13, q5, d2[0]
192        VMLA.F32    q15, q5, d3[0]
193        VLD1.32    {d6}, [r10]!      // A2
194        VMLA.F32     q8, q6, d0[1]
195        VMLA.F32    q10, q6, d1[1]
196        VLD1.32    {d7}, [ r0]!      // A3
197        VMLA.F32    q12, q6, d2[1]
198        VMLA.F32    q14, q6, d3[1]
199        VLDM        r9!, {d8-d11}    // B0
200        VMLA.F32     q9, q7, d0[1]
201        VMLA.F32    q11, q7, d1[1]
202        VMLA.F32    q13, q7, d2[1]
203        VMLA.F32    q15, q7, d3[1]
204
205        VMLA.F32     q8, q4, d4[0]
206        VLDM        r9!, {d12-d15}   // B1
207        VMLA.F32    q10, q4, d5[0]
208        VMLA.F32    q12, q4, d6[0]
209        VMLA.F32    q14, q4, d7[0]
210        VMLA.F32     q9, q5, d4[0]
211        VMLA.F32    q11, q5, d5[0]
212        VMLA.F32    q13, q5, d6[0]
213        VMLA.F32    q15, q5, d7[0]
214        VMLA.F32     q8, q6, d4[1]
215        VMLA.F32    q10, q6, d5[1]
216        VMLA.F32    q12, q6, d6[1]
217        VMLA.F32    q14, q6, d7[1]
218        VMLA.F32     q9, q7, d4[1]
219        VMLA.F32    q11, q7, d5[1]
220        TST         r5, 15
221        VMLA.F32    q13, q7, d6[1]
222        VMLA.F32    q15, q7, d7[1]
223
224        // Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes)
225        BNE         4f
226
227        .p2align 3
2283:
229        // Load params pointer
230        LDR    r5, [sp, 116]         // params
231
232        // Load min/max values
233        VLD1.32     {d4[],d5[]}, [r5]!
234        SUBS        r1, r1, 8
235        VLD1.32     {d6[],d7[]}, [r5]
236
237        // Clamp
238        VMAX.F32     q8,  q8, q2
239        VMAX.F32     q9,  q9, q2
240        VMAX.F32    q10, q10, q2
241        VMAX.F32    q11, q11, q2
242        VMAX.F32    q12, q12, q2
243        VMAX.F32    q13, q13, q2
244        VMAX.F32    q14, q14, q2
245        VMAX.F32    q15, q15, q2
246        VMIN.F32     q8,  q8, q3
247        VMIN.F32     q9,  q9, q3
248        VMIN.F32    q10, q10, q3
249        VMIN.F32    q11, q11, q3
250        VMIN.F32    q12, q12, q3
251        VMIN.F32    q13, q13, q3
252        VMIN.F32    q14, q14, q3
253        VMIN.F32    q15, q15, q3
254
255        // Store full 4 x 8
256        BLO         6f
257        VST1.32     {d16-d19}, [r11], r7
258        SUB         r0, r0, r2
259        VST1.32     {d20-d23}, [r4], r7
260        SUB         r10, r10, r2
261        VST1.32     {d24-d27}, [r8], r7
262        SUB         r12, r12, r2
263        VST1.32     {d28-d31}, [r6], r7
264        SUB         r3, r3, r2
265        BHI         0b
266
267        VPOP        {d8-d15}
268        POP         {r4, r5, r6, r7, r8, r9, r10, r11}
269        BX          lr
270
271        .p2align 3
2724:
273        // Is there a remainder?- 2 floats of A (8 bytes)
274        TST         r5, 8
275        BEQ         5f
276
277        // Remainder - 2 floats of A (8 bytes)
278        VLD1.32    {d0}, [r3]!       // A0
279        VLDM        r9!, {d8-d11}    // B0
280        VLD1.32    {d1}, [r12]!      // A1
281        VLD1.32    {d2}, [r10]!      // A2
282        VLD1.32    {d3}, [ r0]!      // A3
283
284        VMLA.F32     q8, q4, d0[0]
285        VMLA.F32     q9, q5, d0[0]
286        VMLA.F32    q10, q4, d1[0]
287        VMLA.F32    q11, q5, d1[0]
288        VLDM        r9!, {d12-d15}   // B1
289        VMLA.F32    q12, q4, d2[0]
290        VMLA.F32    q13, q5, d2[0]
291        VMLA.F32    q14, q4, d3[0]
292        VMLA.F32    q15, q5, d3[0]
293        VMLA.F32     q8, q6, d0[1]
294        VMLA.F32     q9, q7, d0[1]
295        VMLA.F32    q10, q6, d1[1]
296        VMLA.F32    q11, q7, d1[1]
297        VMLA.F32    q12, q6, d2[1]
298        VMLA.F32    q13, q7, d2[1]
299        VMLA.F32    q14, q6, d3[1]
300        VMLA.F32    q15, q7, d3[1]
301
302        // Is there a remainder?- 1 floats of A (4 bytes)
303        TST         r5, 4
304        BEQ         3b
305
3065:
307        // Remainder- 1 floats of A (4 bytes)
308        VLDM        r3!,  {s0}       // A0
309        VLDM        r9!, {d8-d11}    // B0
310        VLDM        r12!, {s2}       // A1
311        VLDM        r10!, {s4}       // A2
312        VLDM         r0!, {s6}       // A3
313        VMLA.F32     q8, q4, d0[0]
314        VMLA.F32     q9, q5, d0[0]
315        VMLA.F32    q10, q4, d1[0]
316        VMLA.F32    q11, q5, d1[0]
317        VMLA.F32    q12, q4, d2[0]
318        VMLA.F32    q13, q5, d2[0]
319        VMLA.F32    q14, q4, d3[0]
320        VMLA.F32    q15, q5, d3[0]
321        B           3b
322
323        // Store odd width
3246:
325        TST         r1, 4
326        BEQ         7f
327        VST1.32    {d16-d17}, [r11]!
328        VMOV         q8,  q9
329        VST1.32    {d20-d21},  [r4]!
330        VMOV        q10, q11
331        VST1.32    {d24-d25},  [r8]!
332        VMOV        q12, q13
333        VST1.32    {d28-d29},  [r6]!
334        VMOV        q14, q15
335
3367:
337        TST        r1, 2
338        BEQ        8f
339        VST1.32    {d16}, [r11]!
340        VMOV        d16, d17
341        VST1.32    {d20},  [r4]!
342        VMOV        d20, d21
343        VST1.32    {d24},  [r8]!
344        VMOV        d24, d25
345        VST1.32    {d28},  [r6]!
346        VMOV        d28, d29
347
3488:
349        TST         r1, 1
350        BEQ         9f
351        VST1.32    {d16[0]}, [r11]
352        VST1.32    {d20[0]},  [r4]
353        VST1.32    {d24[0]},  [r8]
354        VST1.32    {d28[0]},  [r6]
355
3569:
357        VPOP        {d8-d15}
358        POP         {r4, r5, r6, r7, r8, r9, r10, r11}
359        BX          lr
360
361END_FUNCTION xnn_f32_gemm_minmax_ukernel_4x8__aarch32_neon_${"pld_" if PREFETCH else ""}cortex_a75
362
363#ifdef __ELF__
364.section ".note.GNU-stack","",%progbits
365#endif
366
367