• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ukernel_4x8__aarch32_neon_pld_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_output_params params[restrict static 1])  sp + 116 -> (r7)
25
26
27// inner loop registers
28
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_ukernel_4x8__aarch32_neon_pld_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     r9, [sp, 100]        // w
56        LDR    r11, [sp, 104]        // c
57        LDR     r6, [sp, 108]        // cm_stride
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
801:
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
106        BLO         4f               // less than 4 channels?
107
108        // Prologue
109        VLD1.32    {d0}, [r3]!       // A0
110        VLDM        r9!, {d8-d11}    // B0
111        VLD1.32    {d1}, [r12]!      // A1
112        VLD1.32    {d2}, [r10]!      // A2
113        VLD1.32    {d3}, [ r0]!      // A3
114
115        SUBS        r5, r5, 16
116        BLO         3f               // less than 4 channels?  skip main loop
117
118        .p2align 3
119
120        // Main loop - 4 floats of A (16 bytes)
1212:
122        VMLA.F32     q8, q4, d0[0]
123        VLDM        r9!, {d12-d15}   // B1
124        VMLA.F32    q10, q4, d1[0]
125        VMLA.F32    q12, q4, d2[0]
126        VLD1.32    {d4}, [r3]!       // A0
127        VMLA.F32    q14, q4, d3[0]
128        VMLA.F32     q9, q5, d0[0]
129        VLD1.32    {d5}, [r12]!      // A1
130        VMLA.F32    q11, q5, d1[0]
131        VMLA.F32    q13, q5, d2[0]
132        VMLA.F32    q15, q5, d3[0]
133        VLD1.32    {d6}, [r10]!      // A2
134        VMLA.F32     q8, q6, d0[1]
135        VMLA.F32    q10, q6, d1[1]
136        VLD1.32    {d7}, [ r0]!      // A3
137        VMLA.F32    q12, q6, d2[1]
138        VMLA.F32    q14, q6, d3[1]
139        VLDM        r9!, {d8-d11}    // B0
140        VMLA.F32     q9, q7, d0[1]
141        VMLA.F32    q11, q7, d1[1]
142        VMLA.F32    q13, q7, d2[1]
143        VMLA.F32    q15, q7, d3[1]
144
145        VMLA.F32     q8, q4, d4[0]
146        VLDM        r9!, {d12-d15}   // B1
147        VMLA.F32    q10, q4, d5[0]
148        PLD         [r3, 128]        // Prefetch A0
149        VMLA.F32    q12, q4, d6[0]
150        VLD1.32    {d0}, [r3]!       // A0
151        VMLA.F32    q14, q4, d7[0]
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        PLD         [r10, 128]       // Prefetch A2
157        VMLA.F32    q13, q5, d6[0]
158        VLD1.32    {d2}, [r10]!      // A2
159        VMLA.F32    q15, q5, d7[0]
160        PLD         [r0, 128]        // Prefetch A3
161        VMLA.F32     q8, q6, d4[1]
162        VLD1.32    {d3}, [ r0]!      // A3
163        VMLA.F32    q10, q6, d5[1]
164        PLD         [r9, 384]        // Prefetch B
165        VMLA.F32    q12, q6, d6[1]
166        PLD         [r9, 448]        // Prefetch B
167        VMLA.F32    q14, q6, d7[1]
168        VLDM        r9!, {d8-d11}    // B0
169        VMLA.F32     q9, q7, d4[1]
170        VMLA.F32    q11, q7, d5[1]
171        SUBS         r5, r5, 16
172        VMLA.F32    q13, q7, d6[1]
173        VMLA.F32    q15, q7, d7[1]
174        BHS         2b
175
176        // Epilogue
1773:
178        VMLA.F32     q8, q4, d0[0]
179        VLDM        r9!, {d12-d15}   // B1
180        VMLA.F32    q10, q4, d1[0]
181        VMLA.F32    q12, q4, d2[0]
182        VLD1.32    {d4}, [r3]!       // A0
183        VMLA.F32    q14, q4, d3[0]
184        VMLA.F32     q9, q5, d0[0]
185        VLD1.32    {d5}, [r12]!      // A1
186        VMLA.F32    q11, q5, d1[0]
187        VMLA.F32    q13, q5, d2[0]
188        VMLA.F32    q15, q5, d3[0]
189        VLD1.32    {d6}, [r10]!      // A2
190        VMLA.F32     q8, q6, d0[1]
191        VMLA.F32    q10, q6, d1[1]
192        VLD1.32    {d7}, [ r0]!      // A3
193        VMLA.F32    q12, q6, d2[1]
194        VMLA.F32    q14, q6, d3[1]
195        VLDM        r9!, {d8-d11}    // B0
196        VMLA.F32     q9, q7, d0[1]
197        VMLA.F32    q11, q7, d1[1]
198        VMLA.F32    q13, q7, d2[1]
199        VMLA.F32    q15, q7, d3[1]
200
201        VMLA.F32     q8, q4, d4[0]
202        VLDM        r9!, {d12-d15}   // B1
203        VMLA.F32    q10, q4, d5[0]
204        VMLA.F32    q12, q4, d6[0]
205        VMLA.F32    q14, q4, d7[0]
206        VMLA.F32     q9, q5, d4[0]
207        VMLA.F32    q11, q5, d5[0]
208        VMLA.F32    q13, q5, d6[0]
209        VMLA.F32    q15, q5, d7[0]
210        VMLA.F32     q8, q6, d4[1]
211        VMLA.F32    q10, q6, d5[1]
212        VMLA.F32    q12, q6, d6[1]
213        VMLA.F32    q14, q6, d7[1]
214        VMLA.F32     q9, q7, d4[1]
215        VMLA.F32    q11, q7, d5[1]
216        VMLA.F32    q13, q7, d6[1]
217        VMLA.F32    q15, q7, d7[1]
218
2194:
220        // Is there a remainder?- 1 to 3 floats of A (4, 8 or 12 bytes)
221        TST         r5, 12
222        BNE         7f
223
224        .p2align 3
2255:
226        // Load params pointer
227        LDR    r5, [sp, 116]         // clamping_params
228
229        // Load clamping_params values
230        VLD1.32     {d4[],d5[]}, [r5]!
231        SUBS        r1, r1, 8
232        VLD1.32     {d6[],d7[]}, [r5]
233
234        // Clamp
235        VMIN.F32     q8,  q8, q2
236        VMIN.F32     q9,  q9, q2
237        VMIN.F32    q10, q10, q2
238        VMIN.F32    q11, q11, q2
239        VMIN.F32    q12, q12, q2
240        VMIN.F32    q13, q13, q2
241        VMIN.F32    q14, q14, q2
242        VMIN.F32    q15, q15, q2
243        VMAX.F32     q8,  q8, q3
244        VMAX.F32     q9,  q9, q3
245        VMAX.F32    q10, q10, q3
246        VMAX.F32    q11, q11, q3
247        VMAX.F32    q12, q12, q3
248        VMAX.F32    q13, q13, q3
249        VMAX.F32    q14, q14, q3
250        VMAX.F32    q15, q15, q3
251
252        // Store full 4 x 8
253        BLO         10f
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         1b
263
2646:
265        VPOP        {d8-d15}
266        POP         {r4, r5, r6, r7, r8, r9, r10, r11}
267        BX          lr
268
269        .p2align 3
2707:
271        // Is there a remainder?- 2 floats of A (8 bytes)
272        TST         r5, 8
273        BEQ         8f
274
275        // Remainder - 2 floats of A (8 bytes)
276        VLD1.32    {d0}, [r3]!       // A0
277        VLDM        r9!, {d8-d11}    // B0
278        VLD1.32    {d1}, [r12]!      // A1
279        VLD1.32    {d2}, [r10]!      // A2
280        VLD1.32    {d3}, [ r0]!      // A3
281
282        VMLA.F32     q8, q4, d0[0]
283        VMLA.F32     q9, q5, d0[0]
284        VMLA.F32    q10, q4, d1[0]
285        VMLA.F32    q11, q5, d1[0]
286        VLDM        r9!, {d12-d15}   // B1
287        VMLA.F32    q12, q4, d2[0]
288        VMLA.F32    q13, q5, d2[0]
289        VMLA.F32    q14, q4, d3[0]
290        VMLA.F32    q15, q5, d3[0]
291        VMLA.F32     q8, q6, d0[1]
292        VMLA.F32     q9, q7, d0[1]
293        VMLA.F32    q10, q6, d1[1]
294        VMLA.F32    q11, q7, d1[1]
295        VMLA.F32    q12, q6, d2[1]
296        VMLA.F32    q13, q7, d2[1]
297        VMLA.F32    q14, q6, d3[1]
298        VMLA.F32    q15, q7, d3[1]
2998:
300        // Is there a remainder?- 1 floats of A (4 bytes)
301        TST         r5, 4
302        BEQ         5b
303
3049:
305        // Remainder- 1 floats of A (4 bytes)
306        VLDM        r3!,  {s0}       // A0
307        VLDM        r9!, {d8-d11}    // B0
308        VLDM        r12!, {s2}       // A1
309        VLDM        r10!, {s4}       // A2
310        VLDM         r0!, {s6}       // A3
311        VMLA.F32     q8, q4, d0[0]
312        VMLA.F32     q9, q5, d0[0]
313        VMLA.F32    q10, q4, d1[0]
314        VMLA.F32    q11, q5, d1[0]
315        VMLA.F32    q12, q4, d2[0]
316        VMLA.F32    q13, q5, d2[0]
317        VMLA.F32    q14, q4, d3[0]
318        VMLA.F32    q15, q5, d3[0]
319        B           5b
320
321// Store odd width
32210:
323        TST         r1, 4
324        BEQ         11f
325        VST1.32    {d16-d17}, [r11]!
326        VMOV         q8,  q9
327        VST1.32    {d20-d21},  [r4]!
328        VMOV        q10, q11
329        VST1.32    {d24-d25},  [r8]!
330        VMOV        q12, q13
331        VST1.32    {d28-d29},  [r6]!
332        VMOV        q14, q15
333
33411:
335        TST        r1, 2
336        BEQ        12f
337        VST1.32    {d16}, [r11]!
338        VMOV        d16, d17
339        VST1.32    {d20},  [r4]!
340        VMOV        d20, d21
341        VST1.32    {d24},  [r8]!
342        VMOV        d24, d25
343        VST1.32    {d28},  [r6]!
344        VMOV        d28, d29
345
34612:
347        TST         r1, 1
348        BEQ         13f
349        VST1.32    {d16[0]}, [r11]
350        VST1.32    {d20[0]},  [r4]
351        VST1.32    {d24[0]},  [r8]
352        VST1.32    {d28[0]},  [r6]
353
35413:
355        VPOP        {d8-d15}
356        POP         {r4, r5, r6, r7, r8, r9, r10, r11}
357        BX          lr
358
359END_FUNCTION xnn_f32_gemm_ukernel_4x8__aarch32_neon_pld_cortex_a75
360
361#ifdef __ELF__
362.section ".note.GNU-stack","",%progbits
363#endif
364
365
366
367