1*4bdc9457SAndroid Build Coastguard Worker // Copyright 2022 Google LLC
2*4bdc9457SAndroid Build Coastguard Worker //
3*4bdc9457SAndroid Build Coastguard Worker // This source code is licensed under the BSD-style license found in the
4*4bdc9457SAndroid Build Coastguard Worker // LICENSE file in the root directory of this source tree.
5*4bdc9457SAndroid Build Coastguard Worker
6*4bdc9457SAndroid Build Coastguard Worker #include <cassert>
7*4bdc9457SAndroid Build Coastguard Worker #include <cstddef>
8*4bdc9457SAndroid Build Coastguard Worker #include <limits>
9*4bdc9457SAndroid Build Coastguard Worker
10*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack.h>
11*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/aarch64-assembler.h>
12*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/allocator.h>
13*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/igemm.h>
14*4bdc9457SAndroid Build Coastguard Worker
15*4bdc9457SAndroid Build Coastguard Worker namespace xnnpack {
16*4bdc9457SAndroid Build Coastguard Worker namespace aarch64 {
17*4bdc9457SAndroid Build Coastguard Worker namespace {
18*4bdc9457SAndroid Build Coastguard Worker class Generator : public Assembler {
19*4bdc9457SAndroid Build Coastguard Worker using Assembler::Assembler;
20*4bdc9457SAndroid Build Coastguard Worker public:
21*4bdc9457SAndroid Build Coastguard Worker void generate(size_t max_mr, size_t nc_mod_nr, size_t kc, size_t ks, float min, float max);
22*4bdc9457SAndroid Build Coastguard Worker };
23*4bdc9457SAndroid Build Coastguard Worker
24*4bdc9457SAndroid Build Coastguard Worker // void xnn_f32_igemm_minmax_ukernel_6x8__aarch64_neonfma_ld128(
25*4bdc9457SAndroid Build Coastguard Worker // size_t mr, x0
26*4bdc9457SAndroid Build Coastguard Worker // size_t nc, x1
27*4bdc9457SAndroid Build Coastguard Worker // size_t kc, x2 / x0
28*4bdc9457SAndroid Build Coastguard Worker // size_t ks, x3 / x9
29*4bdc9457SAndroid Build Coastguard Worker // const float**restrict a, x4
30*4bdc9457SAndroid Build Coastguard Worker // const void*restrict w, x5
31*4bdc9457SAndroid Build Coastguard Worker // uint8_t*restrict c, x6
32*4bdc9457SAndroid Build Coastguard Worker // size_t cm_stride, x7
33*4bdc9457SAndroid Build Coastguard Worker // size_t cn_stride, [sp] -> (x0)
34*4bdc9457SAndroid Build Coastguard Worker // size_t a_offset, [sp + 8] -> x11
35*4bdc9457SAndroid Build Coastguard Worker // const float* zero, [sp + 16] -> x12
36*4bdc9457SAndroid Build Coastguard Worker // const xnn_f32_minmax_params params [sp + 24] -> x8
37*4bdc9457SAndroid Build Coastguard Worker
38*4bdc9457SAndroid Build Coastguard Worker // d8-d15, x19-x30 need to be preserved if used. x18 is reserved by the OS.
39*4bdc9457SAndroid Build Coastguard Worker
40*4bdc9457SAndroid Build Coastguard Worker // A pointers
41*4bdc9457SAndroid Build Coastguard Worker // x14 a0
42*4bdc9457SAndroid Build Coastguard Worker // x15 a1
43*4bdc9457SAndroid Build Coastguard Worker // x20 a2
44*4bdc9457SAndroid Build Coastguard Worker // x21 a3
45*4bdc9457SAndroid Build Coastguard Worker // x22 a4
46*4bdc9457SAndroid Build Coastguard Worker // x23 a5
47*4bdc9457SAndroid Build Coastguard Worker
48*4bdc9457SAndroid Build Coastguard Worker // C pointers
49*4bdc9457SAndroid Build Coastguard Worker // x6 c0
50*4bdc9457SAndroid Build Coastguard Worker // x16 c1
51*4bdc9457SAndroid Build Coastguard Worker // x17 c2
52*4bdc9457SAndroid Build Coastguard Worker // x10 c3
53*4bdc9457SAndroid Build Coastguard Worker // x13 c4
54*4bdc9457SAndroid Build Coastguard Worker // x7 c5
55*4bdc9457SAndroid Build Coastguard Worker
56*4bdc9457SAndroid Build Coastguard Worker // Vector register usage
57*4bdc9457SAndroid Build Coastguard Worker // A0 v0
58*4bdc9457SAndroid Build Coastguard Worker // A1 v1
59*4bdc9457SAndroid Build Coastguard Worker // A2 v2
60*4bdc9457SAndroid Build Coastguard Worker // A3 v3
61*4bdc9457SAndroid Build Coastguard Worker // A4 v4
62*4bdc9457SAndroid Build Coastguard Worker // A5 v5
63*4bdc9457SAndroid Build Coastguard Worker // B v16 v17 v18 v19
64*4bdc9457SAndroid Build Coastguard Worker // C v20 v21
65*4bdc9457SAndroid Build Coastguard Worker // C v22 v23
66*4bdc9457SAndroid Build Coastguard Worker // C v24 v25
67*4bdc9457SAndroid Build Coastguard Worker // C v26 v27
68*4bdc9457SAndroid Build Coastguard Worker // C v28 v29
69*4bdc9457SAndroid Build Coastguard Worker // C v30 v31
70*4bdc9457SAndroid Build Coastguard Worker // Clamp v6 v7
71*4bdc9457SAndroid Build Coastguard Worker // unused A v8 v9 v10 v11
72*4bdc9457SAndroid Build Coastguard Worker // unused B v12 v13 v14 v15
73*4bdc9457SAndroid Build Coastguard Worker
74*4bdc9457SAndroid Build Coastguard Worker // Converted from: src/f32-igemm/gen/6x8-minmax-aarch64-neonfma-ld128.S
generate(size_t max_mr,size_t nc_mod_nr,size_t kc,size_t ks,float min,float max)75*4bdc9457SAndroid Build Coastguard Worker void Generator::generate(size_t max_mr, size_t nc_mod_nr, size_t kc, size_t ks, float min, float max) {
76*4bdc9457SAndroid Build Coastguard Worker assert(max_mr <= 6);
77*4bdc9457SAndroid Build Coastguard Worker assert(nc_mod_nr < 8);
78*4bdc9457SAndroid Build Coastguard Worker assert(kc != 0);
79*4bdc9457SAndroid Build Coastguard Worker assert(kc % sizeof(float) == 0);
80*4bdc9457SAndroid Build Coastguard Worker
81*4bdc9457SAndroid Build Coastguard Worker Label l0, l1, l2, l3, l4, l5, l6, l7, l8, l9;
82*4bdc9457SAndroid Build Coastguard Worker
83*4bdc9457SAndroid Build Coastguard Worker const bool clamp_min = min != -std::numeric_limits<float>::infinity();
84*4bdc9457SAndroid Build Coastguard Worker const bool clamp_max = max != +std::numeric_limits<float>::infinity();
85*4bdc9457SAndroid Build Coastguard Worker
86*4bdc9457SAndroid Build Coastguard Worker // Load zero, params pointer
87*4bdc9457SAndroid Build Coastguard Worker ldp(x12, x8, mem[sp, 16]);
88*4bdc9457SAndroid Build Coastguard Worker
89*4bdc9457SAndroid Build Coastguard Worker // Clamp C pointers
90*4bdc9457SAndroid Build Coastguard Worker cmp(x0, 2); // if mr < 2
91*4bdc9457SAndroid Build Coastguard Worker add(x16, x6, x7); // c1 = c0 + cm_stride
92*4bdc9457SAndroid Build Coastguard Worker csel(x16, x6, x16, kLO); // c1 = c0
93*4bdc9457SAndroid Build Coastguard Worker
94*4bdc9457SAndroid Build Coastguard Worker // Load min/max values
95*4bdc9457SAndroid Build Coastguard Worker if (clamp_min || clamp_max) {
96*4bdc9457SAndroid Build Coastguard Worker ld2r({v6.v4s(), v7.v4s()}, mem[x8]);
97*4bdc9457SAndroid Build Coastguard Worker }
98*4bdc9457SAndroid Build Coastguard Worker
99*4bdc9457SAndroid Build Coastguard Worker add(x17, x16, x7); // c2 = c1 + cm_stride
100*4bdc9457SAndroid Build Coastguard Worker // if mr <= 2
101*4bdc9457SAndroid Build Coastguard Worker csel(x17, x16, x17, kLS); // c2 = c1
102*4bdc9457SAndroid Build Coastguard Worker
103*4bdc9457SAndroid Build Coastguard Worker // Save x20,x21,x22,x23 on stack
104*4bdc9457SAndroid Build Coastguard Worker stp(x20, x21, mem[sp, -32]++);
105*4bdc9457SAndroid Build Coastguard Worker
106*4bdc9457SAndroid Build Coastguard Worker cmp(x0, 4); // if mr < 4
107*4bdc9457SAndroid Build Coastguard Worker add(x10, x17, x7); // c3 = c2 + cm_stride
108*4bdc9457SAndroid Build Coastguard Worker csel(x10, x17, x10, kLO); // c3 = c2
109*4bdc9457SAndroid Build Coastguard Worker
110*4bdc9457SAndroid Build Coastguard Worker stp(x22, x23, mem[sp, 16]);
111*4bdc9457SAndroid Build Coastguard Worker
112*4bdc9457SAndroid Build Coastguard Worker add(x13, x10, x7); // c4 = c3 + cm_stride
113*4bdc9457SAndroid Build Coastguard Worker // if mr <= 4
114*4bdc9457SAndroid Build Coastguard Worker csel(x13, x10, x13, kLS); // c4 = c3
115*4bdc9457SAndroid Build Coastguard Worker
116*4bdc9457SAndroid Build Coastguard Worker // Load a_offset
117*4bdc9457SAndroid Build Coastguard Worker ldr(x11, mem[sp, 40]);
118*4bdc9457SAndroid Build Coastguard Worker
119*4bdc9457SAndroid Build Coastguard Worker cmp(x0, 6); // if mr < 6
120*4bdc9457SAndroid Build Coastguard Worker add(x7, x13, x7); // c5 = c4 + cm_stride
121*4bdc9457SAndroid Build Coastguard Worker csel(x7, x13, x7, kLO); // c5 = c4
122*4bdc9457SAndroid Build Coastguard Worker
123*4bdc9457SAndroid Build Coastguard Worker bind(l0);
124*4bdc9457SAndroid Build Coastguard Worker // Load initial bias from w into accumulators
125*4bdc9457SAndroid Build Coastguard Worker ldp(q20, q21, mem[x5], 32);
126*4bdc9457SAndroid Build Coastguard Worker mov(v22.v16b(), v20.v16b());
127*4bdc9457SAndroid Build Coastguard Worker mov(v23.v16b(), v21.v16b());
128*4bdc9457SAndroid Build Coastguard Worker mov(v24.v16b(), v20.v16b());
129*4bdc9457SAndroid Build Coastguard Worker mov(v25.v16b(), v21.v16b());
130*4bdc9457SAndroid Build Coastguard Worker mov(v26.v16b(), v20.v16b());
131*4bdc9457SAndroid Build Coastguard Worker mov(v27.v16b(), v21.v16b());
132*4bdc9457SAndroid Build Coastguard Worker mov(v28.v16b(), v20.v16b());
133*4bdc9457SAndroid Build Coastguard Worker mov(v29.v16b(), v21.v16b());
134*4bdc9457SAndroid Build Coastguard Worker mov(v30.v16b(), v20.v16b());
135*4bdc9457SAndroid Build Coastguard Worker mov(v31.v16b(), v21.v16b());
136*4bdc9457SAndroid Build Coastguard Worker
137*4bdc9457SAndroid Build Coastguard Worker mov(x9, x3); // p = ks
138*4bdc9457SAndroid Build Coastguard Worker
139*4bdc9457SAndroid Build Coastguard Worker bind(l1);
140*4bdc9457SAndroid Build Coastguard Worker // Load next 6 A pointers
141*4bdc9457SAndroid Build Coastguard Worker ldp(x14, x15, mem[x4], 16);
142*4bdc9457SAndroid Build Coastguard Worker ldp(x20, x21, mem[x4], 16);
143*4bdc9457SAndroid Build Coastguard Worker ldp(x22, x23, mem[x4], 16);
144*4bdc9457SAndroid Build Coastguard Worker
145*4bdc9457SAndroid Build Coastguard Worker cmp(x14, x12); // if a0 == zero
146*4bdc9457SAndroid Build Coastguard Worker add(x14, x14, x11); // a0 += a_offset
147*4bdc9457SAndroid Build Coastguard Worker csel(x14, x12, x14, kEQ); // a0 = zero, else += a0 + a_offset
148*4bdc9457SAndroid Build Coastguard Worker cmp(x15, x12); // if a1 == zero
149*4bdc9457SAndroid Build Coastguard Worker add(x15, x15, x11); // a1 += a_offset
150*4bdc9457SAndroid Build Coastguard Worker csel(x15, x12, x15, kEQ); // a1 = zero, else += a1 + a_offset
151*4bdc9457SAndroid Build Coastguard Worker cmp(x20, x12); // if a2 == zero
152*4bdc9457SAndroid Build Coastguard Worker add(x20, x20, x11); // a2 += a_offset
153*4bdc9457SAndroid Build Coastguard Worker csel(x20, x12, x20, kEQ); // a2 = zero, else += a2 + a_offset
154*4bdc9457SAndroid Build Coastguard Worker cmp(x21, x12); // if a3 == zero
155*4bdc9457SAndroid Build Coastguard Worker add(x21, x21, x11); // a3 += a_offset
156*4bdc9457SAndroid Build Coastguard Worker csel(x21, x12, x21, kEQ); // a3 = zero, else += a3 + a_offset
157*4bdc9457SAndroid Build Coastguard Worker cmp(x22, x12); // if a4 == zero
158*4bdc9457SAndroid Build Coastguard Worker add(x22, x22, x11); // a4 += a_offset
159*4bdc9457SAndroid Build Coastguard Worker csel(x22, x12, x22, kEQ); // a4 = zero, else += a4 + a_offset
160*4bdc9457SAndroid Build Coastguard Worker cmp(x23, x12); // if a5 == zero
161*4bdc9457SAndroid Build Coastguard Worker add(x23, x23, x11); // a5 += a_offset
162*4bdc9457SAndroid Build Coastguard Worker csel(x23, x12, x23, kEQ); // a5 = zero, else += a5 + a_offset
163*4bdc9457SAndroid Build Coastguard Worker
164*4bdc9457SAndroid Build Coastguard Worker // Is there at least 4 floats (16 bytes)?
165*4bdc9457SAndroid Build Coastguard Worker subs(x0, x2, 16); // k = kc - 16
166*4bdc9457SAndroid Build Coastguard Worker b_lo(l4);
167*4bdc9457SAndroid Build Coastguard Worker
168*4bdc9457SAndroid Build Coastguard Worker // Main loop - 4 floats of A (16 bytes)
169*4bdc9457SAndroid Build Coastguard Worker // 48 FMA + 6 ld128 A + 4 LDP B
170*4bdc9457SAndroid Build Coastguard Worker bind(l2);
171*4bdc9457SAndroid Build Coastguard Worker ldp(q16, q17, mem[x5], 32);
172*4bdc9457SAndroid Build Coastguard Worker ldr(q0, mem[x14], 16);
173*4bdc9457SAndroid Build Coastguard Worker ldr(q1, mem[x15], 16);
174*4bdc9457SAndroid Build Coastguard Worker ldr(q2, mem[x20], 16);
175*4bdc9457SAndroid Build Coastguard Worker ldr(q3, mem[x21], 16);
176*4bdc9457SAndroid Build Coastguard Worker ldr(q4, mem[x22], 16);
177*4bdc9457SAndroid Build Coastguard Worker ldr(q5, mem[x23], 16);
178*4bdc9457SAndroid Build Coastguard Worker fmla(v20.v4s(), v16.v4s(), v0.s()[0]);
179*4bdc9457SAndroid Build Coastguard Worker fmla(v22.v4s(), v16.v4s(), v1.s()[0]);
180*4bdc9457SAndroid Build Coastguard Worker fmla(v24.v4s(), v16.v4s(), v2.s()[0]);
181*4bdc9457SAndroid Build Coastguard Worker fmla(v26.v4s(), v16.v4s(), v3.s()[0]);
182*4bdc9457SAndroid Build Coastguard Worker ldp(q18, q19, mem[x5], 32);
183*4bdc9457SAndroid Build Coastguard Worker fmla(v28.v4s(), v16.v4s(), v4.s()[0]);
184*4bdc9457SAndroid Build Coastguard Worker fmla(v30.v4s(), v16.v4s(), v5.s()[0]);
185*4bdc9457SAndroid Build Coastguard Worker fmla(v21.v4s(), v17.v4s(), v0.s()[0]);
186*4bdc9457SAndroid Build Coastguard Worker fmla(v23.v4s(), v17.v4s(), v1.s()[0]);
187*4bdc9457SAndroid Build Coastguard Worker fmla(v25.v4s(), v17.v4s(), v2.s()[0]);
188*4bdc9457SAndroid Build Coastguard Worker fmla(v27.v4s(), v17.v4s(), v3.s()[0]);
189*4bdc9457SAndroid Build Coastguard Worker fmla(v29.v4s(), v17.v4s(), v4.s()[0]);
190*4bdc9457SAndroid Build Coastguard Worker fmla(v31.v4s(), v17.v4s(), v5.s()[0]);
191*4bdc9457SAndroid Build Coastguard Worker
192*4bdc9457SAndroid Build Coastguard Worker fmla(v20.v4s(), v18.v4s(), v0.s()[1]);
193*4bdc9457SAndroid Build Coastguard Worker ldp(q16, q17, mem[x5], 32);
194*4bdc9457SAndroid Build Coastguard Worker fmla(v22.v4s(), v18.v4s(), v1.s()[1]);
195*4bdc9457SAndroid Build Coastguard Worker fmla(v24.v4s(), v18.v4s(), v2.s()[1]);
196*4bdc9457SAndroid Build Coastguard Worker fmla(v26.v4s(), v18.v4s(), v3.s()[1]);
197*4bdc9457SAndroid Build Coastguard Worker fmla(v28.v4s(), v18.v4s(), v4.s()[1]);
198*4bdc9457SAndroid Build Coastguard Worker fmla(v30.v4s(), v18.v4s(), v5.s()[1]);
199*4bdc9457SAndroid Build Coastguard Worker fmla(v21.v4s(), v19.v4s(), v0.s()[1]);
200*4bdc9457SAndroid Build Coastguard Worker fmla(v23.v4s(), v19.v4s(), v1.s()[1]);
201*4bdc9457SAndroid Build Coastguard Worker fmla(v25.v4s(), v19.v4s(), v2.s()[1]);
202*4bdc9457SAndroid Build Coastguard Worker fmla(v27.v4s(), v19.v4s(), v3.s()[1]);
203*4bdc9457SAndroid Build Coastguard Worker fmla(v29.v4s(), v19.v4s(), v4.s()[1]);
204*4bdc9457SAndroid Build Coastguard Worker fmla(v31.v4s(), v19.v4s(), v5.s()[1]);
205*4bdc9457SAndroid Build Coastguard Worker
206*4bdc9457SAndroid Build Coastguard Worker fmla(v20.v4s(), v16.v4s(), v0.s()[2]);
207*4bdc9457SAndroid Build Coastguard Worker ldp(q18, q19, mem[x5], 32);
208*4bdc9457SAndroid Build Coastguard Worker fmla(v22.v4s(), v16.v4s(), v1.s()[2]);
209*4bdc9457SAndroid Build Coastguard Worker fmla(v24.v4s(), v16.v4s(), v2.s()[2]);
210*4bdc9457SAndroid Build Coastguard Worker fmla(v26.v4s(), v16.v4s(), v3.s()[2]);
211*4bdc9457SAndroid Build Coastguard Worker fmla(v28.v4s(), v16.v4s(), v4.s()[2]);
212*4bdc9457SAndroid Build Coastguard Worker fmla(v30.v4s(), v16.v4s(), v5.s()[2]);
213*4bdc9457SAndroid Build Coastguard Worker fmla(v21.v4s(), v17.v4s(), v0.s()[2]);
214*4bdc9457SAndroid Build Coastguard Worker fmla(v23.v4s(), v17.v4s(), v1.s()[2]);
215*4bdc9457SAndroid Build Coastguard Worker fmla(v25.v4s(), v17.v4s(), v2.s()[2]);
216*4bdc9457SAndroid Build Coastguard Worker fmla(v27.v4s(), v17.v4s(), v3.s()[2]);
217*4bdc9457SAndroid Build Coastguard Worker fmla(v29.v4s(), v17.v4s(), v4.s()[2]);
218*4bdc9457SAndroid Build Coastguard Worker fmla(v31.v4s(), v17.v4s(), v5.s()[2]);
219*4bdc9457SAndroid Build Coastguard Worker
220*4bdc9457SAndroid Build Coastguard Worker fmla(v20.v4s(), v18.v4s(), v0.s()[3]);
221*4bdc9457SAndroid Build Coastguard Worker fmla(v22.v4s(), v18.v4s(), v1.s()[3]);
222*4bdc9457SAndroid Build Coastguard Worker fmla(v24.v4s(), v18.v4s(), v2.s()[3]);
223*4bdc9457SAndroid Build Coastguard Worker fmla(v26.v4s(), v18.v4s(), v3.s()[3]);
224*4bdc9457SAndroid Build Coastguard Worker fmla(v28.v4s(), v18.v4s(), v4.s()[3]);
225*4bdc9457SAndroid Build Coastguard Worker fmla(v30.v4s(), v18.v4s(), v5.s()[3]);
226*4bdc9457SAndroid Build Coastguard Worker fmla(v21.v4s(), v19.v4s(), v0.s()[3]);
227*4bdc9457SAndroid Build Coastguard Worker fmla(v23.v4s(), v19.v4s(), v1.s()[3]);
228*4bdc9457SAndroid Build Coastguard Worker fmla(v25.v4s(), v19.v4s(), v2.s()[3]);
229*4bdc9457SAndroid Build Coastguard Worker fmla(v27.v4s(), v19.v4s(), v3.s()[3]);
230*4bdc9457SAndroid Build Coastguard Worker subs(x0, x0, 16);
231*4bdc9457SAndroid Build Coastguard Worker fmla(v29.v4s(), v19.v4s(), v4.s()[3]);
232*4bdc9457SAndroid Build Coastguard Worker fmla(v31.v4s(), v19.v4s(), v5.s()[3]);
233*4bdc9457SAndroid Build Coastguard Worker b_hs(l2);
234*4bdc9457SAndroid Build Coastguard Worker
235*4bdc9457SAndroid Build Coastguard Worker // Is there a remainder?- 2 floats of A (8 bytes) or less
236*4bdc9457SAndroid Build Coastguard Worker tst(x0, 15);
237*4bdc9457SAndroid Build Coastguard Worker b_ne(l4);
238*4bdc9457SAndroid Build Coastguard Worker
239*4bdc9457SAndroid Build Coastguard Worker bind(l3);
240*4bdc9457SAndroid Build Coastguard Worker // ks loop
241*4bdc9457SAndroid Build Coastguard Worker subs(x9, x9, 48); // ks -= MR * sizeof(void*)
242*4bdc9457SAndroid Build Coastguard Worker b_hi(l1);
243*4bdc9457SAndroid Build Coastguard Worker
244*4bdc9457SAndroid Build Coastguard Worker // Load cn_stride
245*4bdc9457SAndroid Build Coastguard Worker ldr(x0, mem[sp, 32]);
246*4bdc9457SAndroid Build Coastguard Worker // Clamp
247*4bdc9457SAndroid Build Coastguard Worker if (clamp_min) {
248*4bdc9457SAndroid Build Coastguard Worker fmax(v20.v4s(), v20.v4s(), v6.v4s());
249*4bdc9457SAndroid Build Coastguard Worker fmax(v21.v4s(), v21.v4s(), v6.v4s());
250*4bdc9457SAndroid Build Coastguard Worker fmax(v22.v4s(), v22.v4s(), v6.v4s());
251*4bdc9457SAndroid Build Coastguard Worker fmax(v23.v4s(), v23.v4s(), v6.v4s());
252*4bdc9457SAndroid Build Coastguard Worker fmax(v24.v4s(), v24.v4s(), v6.v4s());
253*4bdc9457SAndroid Build Coastguard Worker fmax(v25.v4s(), v25.v4s(), v6.v4s());
254*4bdc9457SAndroid Build Coastguard Worker fmax(v26.v4s(), v26.v4s(), v6.v4s());
255*4bdc9457SAndroid Build Coastguard Worker fmax(v27.v4s(), v27.v4s(), v6.v4s());
256*4bdc9457SAndroid Build Coastguard Worker fmax(v28.v4s(), v28.v4s(), v6.v4s());
257*4bdc9457SAndroid Build Coastguard Worker fmax(v29.v4s(), v29.v4s(), v6.v4s());
258*4bdc9457SAndroid Build Coastguard Worker fmax(v30.v4s(), v30.v4s(), v6.v4s());
259*4bdc9457SAndroid Build Coastguard Worker fmax(v31.v4s(), v31.v4s(), v6.v4s());
260*4bdc9457SAndroid Build Coastguard Worker }
261*4bdc9457SAndroid Build Coastguard Worker subs(x1, x1, 8);
262*4bdc9457SAndroid Build Coastguard Worker if (clamp_max) {
263*4bdc9457SAndroid Build Coastguard Worker fmin(v20.v4s(), v20.v4s(), v7.v4s());
264*4bdc9457SAndroid Build Coastguard Worker fmin(v21.v4s(), v21.v4s(), v7.v4s());
265*4bdc9457SAndroid Build Coastguard Worker fmin(v22.v4s(), v22.v4s(), v7.v4s());
266*4bdc9457SAndroid Build Coastguard Worker fmin(v23.v4s(), v23.v4s(), v7.v4s());
267*4bdc9457SAndroid Build Coastguard Worker fmin(v24.v4s(), v24.v4s(), v7.v4s());
268*4bdc9457SAndroid Build Coastguard Worker fmin(v25.v4s(), v25.v4s(), v7.v4s());
269*4bdc9457SAndroid Build Coastguard Worker fmin(v26.v4s(), v26.v4s(), v7.v4s());
270*4bdc9457SAndroid Build Coastguard Worker fmin(v27.v4s(), v27.v4s(), v7.v4s());
271*4bdc9457SAndroid Build Coastguard Worker fmin(v28.v4s(), v28.v4s(), v7.v4s());
272*4bdc9457SAndroid Build Coastguard Worker fmin(v29.v4s(), v29.v4s(), v7.v4s());
273*4bdc9457SAndroid Build Coastguard Worker fmin(v30.v4s(), v30.v4s(), v7.v4s());
274*4bdc9457SAndroid Build Coastguard Worker fmin(v31.v4s(), v31.v4s(), v7.v4s());
275*4bdc9457SAndroid Build Coastguard Worker }
276*4bdc9457SAndroid Build Coastguard Worker
277*4bdc9457SAndroid Build Coastguard Worker // Store full 6 x 8
278*4bdc9457SAndroid Build Coastguard Worker b_lo(l6);
279*4bdc9457SAndroid Build Coastguard Worker
280*4bdc9457SAndroid Build Coastguard Worker stp(q30, q31, mem[x7]);
281*4bdc9457SAndroid Build Coastguard Worker add(x7, x7, x0);
282*4bdc9457SAndroid Build Coastguard Worker stp(q28, q29, mem[x13]);
283*4bdc9457SAndroid Build Coastguard Worker add(x13, x13, x0);
284*4bdc9457SAndroid Build Coastguard Worker stp(q26, q27, mem[x10]);
285*4bdc9457SAndroid Build Coastguard Worker add(x10, x10, x0);
286*4bdc9457SAndroid Build Coastguard Worker stp(q24, q25, mem[x17]);
287*4bdc9457SAndroid Build Coastguard Worker add(x17, x17, x0);
288*4bdc9457SAndroid Build Coastguard Worker stp(q22, q23, mem[x16]);
289*4bdc9457SAndroid Build Coastguard Worker add(x16, x16, x0);
290*4bdc9457SAndroid Build Coastguard Worker stp(q20, q21, mem[x6]);
291*4bdc9457SAndroid Build Coastguard Worker add(x6, x6, x0);
292*4bdc9457SAndroid Build Coastguard Worker
293*4bdc9457SAndroid Build Coastguard Worker sub(x4, x4, x3); // a -= ks
294*4bdc9457SAndroid Build Coastguard Worker
295*4bdc9457SAndroid Build Coastguard Worker // nc loop
296*4bdc9457SAndroid Build Coastguard Worker b_hi(l0);
297*4bdc9457SAndroid Build Coastguard Worker
298*4bdc9457SAndroid Build Coastguard Worker // Restore x20,x21,x22,x23 from stack
299*4bdc9457SAndroid Build Coastguard Worker ldp(x22, x23, mem[sp, 16]);
300*4bdc9457SAndroid Build Coastguard Worker ldp(x20, x21, mem[sp], 32);
301*4bdc9457SAndroid Build Coastguard Worker ret();
302*4bdc9457SAndroid Build Coastguard Worker
303*4bdc9457SAndroid Build Coastguard Worker bind(l4);
304*4bdc9457SAndroid Build Coastguard Worker // Is there a remainder?- 2 floats of A (8 bytes)
305*4bdc9457SAndroid Build Coastguard Worker tbz(x0, 3, l5);
306*4bdc9457SAndroid Build Coastguard Worker
307*4bdc9457SAndroid Build Coastguard Worker // Remainder- 2 floats of A (8 bytes)
308*4bdc9457SAndroid Build Coastguard Worker ldr(d0, mem[x14], 8);
309*4bdc9457SAndroid Build Coastguard Worker ldp(q16, q17, mem[x5], 32);
310*4bdc9457SAndroid Build Coastguard Worker ldr(d1, mem[x15], 8);
311*4bdc9457SAndroid Build Coastguard Worker ldr(d2, mem[x20], 8);
312*4bdc9457SAndroid Build Coastguard Worker ldr(d3, mem[x21], 8);
313*4bdc9457SAndroid Build Coastguard Worker ldr(d4, mem[x22], 8);
314*4bdc9457SAndroid Build Coastguard Worker ldr(d5, mem[x23], 8);
315*4bdc9457SAndroid Build Coastguard Worker fmla(v20.v4s(), v16.v4s(), v0.s()[0]);
316*4bdc9457SAndroid Build Coastguard Worker fmla(v22.v4s(), v16.v4s(), v1.s()[0]);
317*4bdc9457SAndroid Build Coastguard Worker fmla(v24.v4s(), v16.v4s(), v2.s()[0]);
318*4bdc9457SAndroid Build Coastguard Worker fmla(v26.v4s(), v16.v4s(), v3.s()[0]);
319*4bdc9457SAndroid Build Coastguard Worker ldp(q18, q19, mem[x5], 32);
320*4bdc9457SAndroid Build Coastguard Worker fmla(v28.v4s(), v16.v4s(), v4.s()[0]);
321*4bdc9457SAndroid Build Coastguard Worker fmla(v30.v4s(), v16.v4s(), v5.s()[0]);
322*4bdc9457SAndroid Build Coastguard Worker fmla(v21.v4s(), v17.v4s(), v0.s()[0]);
323*4bdc9457SAndroid Build Coastguard Worker fmla(v23.v4s(), v17.v4s(), v1.s()[0]);
324*4bdc9457SAndroid Build Coastguard Worker fmla(v25.v4s(), v17.v4s(), v2.s()[0]);
325*4bdc9457SAndroid Build Coastguard Worker fmla(v27.v4s(), v17.v4s(), v3.s()[0]);
326*4bdc9457SAndroid Build Coastguard Worker fmla(v29.v4s(), v17.v4s(), v4.s()[0]);
327*4bdc9457SAndroid Build Coastguard Worker fmla(v31.v4s(), v17.v4s(), v5.s()[0]);
328*4bdc9457SAndroid Build Coastguard Worker
329*4bdc9457SAndroid Build Coastguard Worker fmla(v20.v4s(), v18.v4s(), v0.s()[1]);
330*4bdc9457SAndroid Build Coastguard Worker fmla(v22.v4s(), v18.v4s(), v1.s()[1]);
331*4bdc9457SAndroid Build Coastguard Worker fmla(v24.v4s(), v18.v4s(), v2.s()[1]);
332*4bdc9457SAndroid Build Coastguard Worker fmla(v26.v4s(), v18.v4s(), v3.s()[1]);
333*4bdc9457SAndroid Build Coastguard Worker fmla(v28.v4s(), v18.v4s(), v4.s()[1]);
334*4bdc9457SAndroid Build Coastguard Worker fmla(v30.v4s(), v18.v4s(), v5.s()[1]);
335*4bdc9457SAndroid Build Coastguard Worker fmla(v21.v4s(), v19.v4s(), v0.s()[1]);
336*4bdc9457SAndroid Build Coastguard Worker fmla(v23.v4s(), v19.v4s(), v1.s()[1]);
337*4bdc9457SAndroid Build Coastguard Worker fmla(v25.v4s(), v19.v4s(), v2.s()[1]);
338*4bdc9457SAndroid Build Coastguard Worker fmla(v27.v4s(), v19.v4s(), v3.s()[1]);
339*4bdc9457SAndroid Build Coastguard Worker fmla(v29.v4s(), v19.v4s(), v4.s()[1]);
340*4bdc9457SAndroid Build Coastguard Worker fmla(v31.v4s(), v19.v4s(), v5.s()[1]);
341*4bdc9457SAndroid Build Coastguard Worker
342*4bdc9457SAndroid Build Coastguard Worker // Is there a remainder?- 1 float of A (4 bytes)
343*4bdc9457SAndroid Build Coastguard Worker tbz(x0, 2, l3);
344*4bdc9457SAndroid Build Coastguard Worker
345*4bdc9457SAndroid Build Coastguard Worker // Remainder- 1 float of A (4 bytes)
346*4bdc9457SAndroid Build Coastguard Worker bind(l5);
347*4bdc9457SAndroid Build Coastguard Worker ldr(s0, mem[x14], 4);
348*4bdc9457SAndroid Build Coastguard Worker ldp(q16, q17, mem[x5], 32);
349*4bdc9457SAndroid Build Coastguard Worker ldr(s1, mem[x15], 4);
350*4bdc9457SAndroid Build Coastguard Worker ldr(s2, mem[x20], 4);
351*4bdc9457SAndroid Build Coastguard Worker ldr(s3, mem[x21], 4);
352*4bdc9457SAndroid Build Coastguard Worker ldr(s4, mem[x22], 4);
353*4bdc9457SAndroid Build Coastguard Worker ldr(s5, mem[x23], 4);
354*4bdc9457SAndroid Build Coastguard Worker fmla(v20.v4s(), v16.v4s(), v0.s()[0]);
355*4bdc9457SAndroid Build Coastguard Worker fmla(v22.v4s(), v16.v4s(), v1.s()[0]);
356*4bdc9457SAndroid Build Coastguard Worker fmla(v24.v4s(), v16.v4s(), v2.s()[0]);
357*4bdc9457SAndroid Build Coastguard Worker fmla(v26.v4s(), v16.v4s(), v3.s()[0]);
358*4bdc9457SAndroid Build Coastguard Worker fmla(v28.v4s(), v16.v4s(), v4.s()[0]);
359*4bdc9457SAndroid Build Coastguard Worker fmla(v30.v4s(), v16.v4s(), v5.s()[0]);
360*4bdc9457SAndroid Build Coastguard Worker fmla(v21.v4s(), v17.v4s(), v0.s()[0]);
361*4bdc9457SAndroid Build Coastguard Worker fmla(v23.v4s(), v17.v4s(), v1.s()[0]);
362*4bdc9457SAndroid Build Coastguard Worker fmla(v25.v4s(), v17.v4s(), v2.s()[0]);
363*4bdc9457SAndroid Build Coastguard Worker fmla(v27.v4s(), v17.v4s(), v3.s()[0]);
364*4bdc9457SAndroid Build Coastguard Worker fmla(v29.v4s(), v17.v4s(), v4.s()[0]);
365*4bdc9457SAndroid Build Coastguard Worker fmla(v31.v4s(), v17.v4s(), v5.s()[0]);
366*4bdc9457SAndroid Build Coastguard Worker b(l3);
367*4bdc9457SAndroid Build Coastguard Worker
368*4bdc9457SAndroid Build Coastguard Worker // Store odd width
369*4bdc9457SAndroid Build Coastguard Worker bind(l6);
370*4bdc9457SAndroid Build Coastguard Worker tbz(x1, 2, l7);
371*4bdc9457SAndroid Build Coastguard Worker str(q30, mem[x7], 16);
372*4bdc9457SAndroid Build Coastguard Worker mov(v30.v16b(), v31.v16b());
373*4bdc9457SAndroid Build Coastguard Worker str(q28, mem[x13], 16);
374*4bdc9457SAndroid Build Coastguard Worker mov(v28.v16b(), v29.v16b());
375*4bdc9457SAndroid Build Coastguard Worker str(q26, mem[x10], 16);
376*4bdc9457SAndroid Build Coastguard Worker mov(v26.v16b(), v27.v16b());
377*4bdc9457SAndroid Build Coastguard Worker str(q24, mem[x17], 16);
378*4bdc9457SAndroid Build Coastguard Worker mov(v24.v16b(), v25.v16b());
379*4bdc9457SAndroid Build Coastguard Worker str(q22, mem[x16], 16);
380*4bdc9457SAndroid Build Coastguard Worker mov(v22.v16b(), v23.v16b());
381*4bdc9457SAndroid Build Coastguard Worker str(q20, mem[x6], 16);
382*4bdc9457SAndroid Build Coastguard Worker mov(v20.v16b(), v21.v16b());
383*4bdc9457SAndroid Build Coastguard Worker bind(l7);
384*4bdc9457SAndroid Build Coastguard Worker tbz(x1, 1, l8);
385*4bdc9457SAndroid Build Coastguard Worker str(d30, mem[x7], 8);
386*4bdc9457SAndroid Build Coastguard Worker str(d28, mem[x13], 8);
387*4bdc9457SAndroid Build Coastguard Worker dup(d30, v30.d()[1]);
388*4bdc9457SAndroid Build Coastguard Worker dup(d28, v28.d()[1]);
389*4bdc9457SAndroid Build Coastguard Worker str(d26, mem[x10], 8);
390*4bdc9457SAndroid Build Coastguard Worker str(d24, mem[x17], 8);
391*4bdc9457SAndroid Build Coastguard Worker dup(d26, v26.d()[1]);
392*4bdc9457SAndroid Build Coastguard Worker dup(d24, v24.d()[1]);
393*4bdc9457SAndroid Build Coastguard Worker str(d22, mem[x16], 8);
394*4bdc9457SAndroid Build Coastguard Worker str(d20, mem[x6], 8);
395*4bdc9457SAndroid Build Coastguard Worker dup(d22, v22.d()[1]);
396*4bdc9457SAndroid Build Coastguard Worker dup(d20, v20.d()[1]);
397*4bdc9457SAndroid Build Coastguard Worker
398*4bdc9457SAndroid Build Coastguard Worker bind(l8);
399*4bdc9457SAndroid Build Coastguard Worker tbz(x1, 0, l9);
400*4bdc9457SAndroid Build Coastguard Worker str(s30, mem[x7]);
401*4bdc9457SAndroid Build Coastguard Worker str(s28, mem[x13]);
402*4bdc9457SAndroid Build Coastguard Worker str(s26, mem[x10]);
403*4bdc9457SAndroid Build Coastguard Worker str(s24, mem[x17]);
404*4bdc9457SAndroid Build Coastguard Worker str(s22, mem[x16]);
405*4bdc9457SAndroid Build Coastguard Worker str(s20, mem[x6]);
406*4bdc9457SAndroid Build Coastguard Worker bind(l9);
407*4bdc9457SAndroid Build Coastguard Worker // Restore x20,x21,x22,x23 from stack
408*4bdc9457SAndroid Build Coastguard Worker ldp(x22, x23, mem[sp, 16]);
409*4bdc9457SAndroid Build Coastguard Worker ldp(x20, x21, mem[sp], 32);
410*4bdc9457SAndroid Build Coastguard Worker ret();
411*4bdc9457SAndroid Build Coastguard Worker
412*4bdc9457SAndroid Build Coastguard Worker align(16, AlignInstruction::kHlt);
413*4bdc9457SAndroid Build Coastguard Worker }
414*4bdc9457SAndroid Build Coastguard Worker } // namespace
415*4bdc9457SAndroid Build Coastguard Worker } // aarch64
416*4bdc9457SAndroid Build Coastguard Worker } // xnnpack
417*4bdc9457SAndroid Build Coastguard Worker
xnn_generate_f32_igemm_ukernel_6x8__aarch64_neonfma_ld128(xnn_code_buffer * code,size_t max_mr,size_t nc_mod_nr,size_t kc,size_t ks,const void * params)418*4bdc9457SAndroid Build Coastguard Worker xnn_status_t xnn_generate_f32_igemm_ukernel_6x8__aarch64_neonfma_ld128(
419*4bdc9457SAndroid Build Coastguard Worker xnn_code_buffer* code, size_t max_mr, size_t nc_mod_nr, size_t kc, size_t ks, const void* params) {
420*4bdc9457SAndroid Build Coastguard Worker using namespace xnnpack::aarch64;
421*4bdc9457SAndroid Build Coastguard Worker Generator g(code);
422*4bdc9457SAndroid Build Coastguard Worker assert(params != nullptr);
423*4bdc9457SAndroid Build Coastguard Worker const jit_gemm_params* gemm_params = static_cast<const jit_gemm_params*>(params);
424*4bdc9457SAndroid Build Coastguard Worker g.generate(max_mr, nc_mod_nr, kc, ks, gemm_params->f32_minmax.min, gemm_params->f32_minmax.max);
425*4bdc9457SAndroid Build Coastguard Worker g.finalize();
426*4bdc9457SAndroid Build Coastguard Worker if (g.error() != xnnpack::Error::kNoError) {
427*4bdc9457SAndroid Build Coastguard Worker return xnn_status_invalid_state;
428*4bdc9457SAndroid Build Coastguard Worker }
429*4bdc9457SAndroid Build Coastguard Worker return xnn_status_success;
430*4bdc9457SAndroid Build Coastguard Worker }
431