xref: /aosp_15_r20/external/XNNPACK/src/f32-igemm/gen/4x8-minmax-aarch32-neon-ld64.S (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1// Auto-generated file. Do not edit!
2//   Template: src/f32-igemm/4x8-minmax-aarch32-neon-ld64.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_igemm_minmax_ukernel_4x8__aarch32_neon_ld64(
15//     size_t mr,                            r0
16//     size_t nc,                            r1
17//     size_t kc,                            r2 -> r5 -> sp + 68
18//     size_t ks,                            r3 -> sp + 72 -> r14
19//     const float**restrict a,  sp + 112 -> r2
20//     const void*restrict w,    sp + 116 -> r9
21//     uint8_t*restrict c,       sp + 120 -> r11
22//     size_t cm_stride,         sp + 124 -> (r6)
23//     size_t cn_stride,         sp + 128 -> (r7)
24//     size_t a_offset,          sp + 132 -> (r5)
25//     const float* zero,        sp + 136 -> (r7)
26//     minmax_params*params,     sp + 140 -> (r5)
27
28// d8-d15, r4-r11,r14(lr) need to be preserved if used. r13(sp),r15(pc) are reserved.
29
30// Register usage
31// A0   r3  d0
32// A1  r12  d1
33// A2  r10  d2
34// A3   r0  d3
35
36// B    r9  d8,  d9, d10, d11
37// B       d12, d13, d14, d15
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// Clamp (r5) d4 d5 d6 d7
45
46BEGIN_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_ld64
47        .arm
48#ifndef __APPLE__
49        .arch   armv7-a
50        .fpu    neon
51#endif
52        # Push 112 bytes
53        # r2 will be reloaded in outer loop.  r3 is ks
54        PUSH    {r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}   // +44
55        SUB     sp, sp, 4                                        // 4
56        VPUSH   {d8-d15}                                         // +64 = 112
57
58        LDR     r11, [sp, 120]          // c
59        LDR     r6, [sp, 124]           // cm_stride
60        LDR     r2, [sp, 112]           // a
61        LDR     r9, [sp, 116]           // w
62        LDR     r5, [sp, 140]           // params
63        MOV     r14, r3                 // p = ks
64
65        # Clamp C pointers
66        CMP     r0, 2                   // if mr >= 2
67        ADD     r4, r11, r6             //   c1 = c0 + cm_stride
68        MOVLO   r4, r11                 // c1
69                                        // if mr > 2
70        ADD     r8, r4, r6              //   c2 = c1 + cm_stride
71        MOVLS   r8, r4                  // c2
72        CMP     r0, 4                   // if mr >=4
73        ADD     r6, r8, r6              //   c3 = c2 + cm_stride
74        MOVLO   r6, r8                  // c3
75
76        # Load min/max values
77        VLD1.32 {d4[], d5[]}, [r5]!
78        VLD1.32 {d6[], d7[]}, [r5]
79
800:
81        # Load initial bias from w into accumulators
82        VLDM    r9!, {d16-d19}          // Bias
83        VMOV    q10, q8
84        VMOV    q11, q9
85        VMOV    q12, q8
86        VMOV    q13, q9
87        VMOV    q14, q8
88        VMOV    q15, q9
89
901:
91        # Load next 4 A pointers
92        LDR     r3, [r2,  0]
93        LDR     r12, [r2,  4]
94        LDR     r10, [r2,  8]
95        LDR     r0, [r2, 12]
96        ADD     r2, r2, 16
97
98        # Add a_offset
99        LDR     r5, [sp, 132]           // a_offset
100        LDR     r7, [sp, 136]           // zero
101        CMP     r3,  r7                 // if a0 == zero
102        ADD     r3,  r3, r5             // a0 += a_offset
103        MOVEQ   r3,  r7                 //   a0 = zero, else += a0 + a_offset
104        CMP     r12,  r7                // if a1 == zero
105        ADD     r12, r12, r5            // a1 += a_offset
106        MOVEQ   r12,  r7                //   a1 = zero, else += a1 + a_offset
107        CMP     r10,  r7                // if a2 == zero
108        ADD     r10, r10, r5            // a2 += a_offset
109        MOVEQ   r10,  r7                //   a2 = zero, else += a2 + a_offset
110        CMP     r0,  r7                 // if a3 == zero
111        ADD     r0,  r0, r5             // a3 += a_offset
112        LDR     r5, [sp, 68]            // kc
113        MOVEQ   r0,  r7                 //   a3 = zero, else += a3 + a_offset
114
115
116        SUBS    r5, r5, 8               // kc - 8
117        BLO     4f                      // less than 2 channels?
118
119        # Main loop - 2 floats of A (8 bytes)
1202:
121        VLD1.32 {d0}, [r3]!             // A0
122        VLDM    r9!, {d8-d11}           // B0
123        VLD1.32 {d1}, [r12]!            // A1
124        VLD1.32 {d2}, [r10]!            // A2
125        VLD1.32 {d3}, [ r0]!            // A3
126        VLDM    r9!, {d12-d15}          // B1
127
128        VMLA.F32 q8, q4, d0[0]
129        VMLA.F32 q9, q5, d0[0]
130        VMLA.F32 q10, q4, d1[0]
131        VMLA.F32 q11, q5, d1[0]
132        VMLA.F32 q12, q4, d2[0]
133        VMLA.F32 q13, q5, d2[0]
134        VMLA.F32 q14, q4, d3[0]
135        VMLA.F32 q15, q5, d3[0]
136        VMLA.F32 q8, q6, d0[1]
137        VMLA.F32 q9, q7, d0[1]
138        VMLA.F32 q10, q6, d1[1]
139        VMLA.F32 q11, q7, d1[1]
140        SUBS    r5, r5, 8
141        VMLA.F32 q12, q6, d2[1]
142        VMLA.F32 q13, q7, d2[1]
143        VMLA.F32 q14, q6, d3[1]
144        VMLA.F32 q15, q7, d3[1]
145        BHS     2b
146
147        # Is there a remainder?- 1 float of A (4 bytes)
148        TST     r5, 4
149        BNE     4f
150
1513:
152        # ks loop
153        SUBS    r14, r14, 16            // ks -= MR * sizeof(void*)
154        BHI     1b
155
156        LDR     r7, [sp, 128]           // cn_stride
157        LDR     r14, [sp, 72]           // p = ks
158
159        # Clamp
160        VMAX.F32 q8,  q8, q2
161        SUBS    r1, r1, 8
162        VMAX.F32 q9,  q9, q2
163        VMAX.F32 q10, q10, q2
164        VMAX.F32 q11, q11, q2
165        VMAX.F32 q12, q12, q2
166        VMAX.F32 q13, q13, q2
167        VMAX.F32 q14, q14, q2
168        VMAX.F32 q15, q15, q2
169        VMIN.F32 q8,  q8, q3
170        VMIN.F32 q9,  q9, q3
171        VMIN.F32 q10, q10, q3
172        VMIN.F32 q11, q11, q3
173        VMIN.F32 q12, q12, q3
174        VMIN.F32 q13, q13, q3
175        VMIN.F32 q14, q14, q3
176        VMIN.F32 q15, q15, q3
177
178        # Store full 4 x 8
179        BLO     5f
180        VST1.32 {d28-d31},  [r6], r7
181        VST1.32 {d24-d27},  [r8], r7
182        VST1.32 {d20-d23},  [r4], r7
183        VST1.32 {d16-d19}, [r11], r7
184        SUB     r2, r2, r14             // a -= ks
185        BHI     0b
186
187        VPOP    {d8-d15}
188        ADD     sp, sp, 12              // skip pad, r2, r3
189        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
190
1914:
192        # Remainder- 1 float of A (4 bytes)
193        VLDM    r3!, {s0}               // A0
194        VLDM    r9!, {d8-d11}           // B0
195        VLDM    r12!, {s2}              // A1
196        VLDM    r10!, {s4}              // A2
197        VLDM    r0!, {s6}               // A3
198        VMLA.F32 q8, q4, d0[0]
199        VMLA.F32 q9, q5, d0[0]
200        VMLA.F32 q10, q4, d1[0]
201        VMLA.F32 q11, q5, d1[0]
202        VMLA.F32 q12, q4, d2[0]
203        VMLA.F32 q13, q5, d2[0]
204        VMLA.F32 q14, q4, d3[0]
205        VMLA.F32 q15, q5, d3[0]
206        B       3b
207
208        # Store odd width
2095:
210        TST     r1, 4
211        BEQ     6f
212        VST1.32 {d28-d29},  [r6]!
213        VST1.32 {d24-d25},  [r8]!
214        VMOV    q14, q15
215        VMOV    q12, q13
216        VST1.32 {d20-d21},  [r4]!
217        VST1.32 {d16-d17}, [r11]!
218        VMOV    q10, q11
219        VMOV    q8,  q9
220
2216:
222        TST     r1, 2
223        BEQ     7f
224        VST1.32 {d28},  [r6]!
225        VST1.32 {d24},  [r8]!
226        VMOV    d28, d29
227        VMOV    d24, d25
228        VST1.32 {d20},  [r4]!
229        VST1.32 {d16}, [r11]!
230        VMOV    d20, d21
231        VMOV    d16, d17
232
2337:
234        TST     r1, 1
235        BEQ     8f
236        VST1.32 {d28[0]},  [r6]!
237        VST1.32 {d24[0]},  [r8]!
238        VST1.32 {d20[0]},  [r4]!
239        VST1.32 {d16[0]}, [r11]!
240
2418:
242        VPOP    {d8-d15}
243        ADD     sp, sp, 12              // skip pad, r2, r3
244        POP     {r4, r5, r6, r7, r8, r9, r10, r11, pc}
245
246END_FUNCTION xnn_f32_igemm_minmax_ukernel_4x8__aarch32_neon_ld64
247
248#ifdef __ELF__
249.section ".note.GNU-stack","",%progbits
250#endif
251