• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 #ifdef __ARM_FEATURE_SVE
25 #ifdef ARM_COMPUTE_ENABLE_SME2
26 
27 #include "arm_gemm.hpp"
28 #include "../../utils.hpp"
29 
30 #include <cassert>
31 #include <limits>
32 
33 namespace arm_gemm {
34 
sme2_gemv_fp32_mla_16VL(const float * A_ptr,const float * B_ptr,float * output_ptr,size_t N,size_t K,const float * bias,Activation act,bool)35 void sme2_gemv_fp32_mla_16VL (
36     const float *A_ptr, const float *B_ptr, float *output_ptr,
37     size_t N, size_t K,
38     const float *bias, Activation act, bool
39 )
40 {
41     struct KernelArgs {
42         float maxval = static_cast<float>(std::numeric_limits<float>::infinity());
43         float minval = - static_cast<float>(std::numeric_limits<float>::infinity());
44         const float *B_ptr = {};
45         size_t output_offset = {};
46         unsigned int input_initial_col = {};
47     } ka;
48 
49     unsigned long flags=0;
50     ka.B_ptr = B_ptr;
51     switch(act.type) {
52         default:
53         case Activation::Type::None:
54             break;
55         case Activation::Type::BoundedReLU:
56             ka.maxval = static_cast<float>(act.param1);
57             /* fall through */
58         case Activation::Type::ReLU:
59             ka.minval = 0;
60             flags |= 0x2;
61             break;
62     }
63     __asm__ __volatile__(
64       "ptrue p1.b\n"
65       ".inst 0xd503477f  // SMSTART ZA\n"
66       "cntw x27, ALL, MUL #4\n"
67       "add x26, %x[N], x27\n"
68       "sub x26, x26, #0x1\n"
69       "udiv x26, x26, x27\n"
70       "add x21, x26, #0x3\n"
71       "and x21, x21, #0xfffffffffffffffc\n"
72       "mul x21, x21, x27\n"
73       "mul x21, x21, %x[K]\n"
74       "mov x9, #0x0\n"
75       "mov x25, %x[B_ptr]\n"
76       "mov x24, %x[output_ptr]\n"
77       "ptrue p1.b\n"
78       ".inst 0x25207811  // ptrue pn9.b\n"
79       "lsl x21, x21, #0x2\n"
80       "mov x20, #0x1\n"
81       "1:"  // RHS size check loop
82       "cmp x21, #0x200000\n"
83       "blt 2f\n"
84       "tbnz x21, #0, 3f\n"
85       "lsr x21, x21, #0x1\n"
86       "lsl x20, x20, #0x1\n"
87       "b 1b\n"
88       "2:"  // RHS do prefetch
89       "lsl x19, x21, #0x26\n"
90       "sub x20, x20, #0x1\n"
91       "lsl x20, x20, #0x16\n"
92       "orr x21, x21, x19\n"
93       "orr x21, x21, x20\n"
94       ".inst 0xf8b54b3a  // rprfm pldonce, x21, [x25]\n"
95       "3:"  // RHS prefetch exit
96       "mov x23, %x[bias]\n"
97       "4:"  // Column loop
98       "cmp x26, #0x4\n"
99       "bge 28f\n"
100       "cmp x26, #0x2\n"
101       "bgt 20f\n"
102       "beq 12f\n"
103       "mov x22, %x[A_ptr]\n"
104       "lsl x21, %x[K], #0x2\n"
105       "mov x19, %x[N]\n"
106       "mov x20, %x[K]\n"
107       ".inst 0xf8b54ad8  // rprfm pldmany, x21, [x22]\n"
108       ".inst 0x25b367f0  // whilelt p8.s, XZR, x19, VLx4\n"
109       "cbz x23, 5f\n"
110       ".inst 0xa040c6e0  // ld1w { z0.s-z3.s }, pn9.b/Z, [x23]\n"
111       ".inst 0xc0042c00  // mova za.d[x9, #0], { z0.d-z3.d }\n"
112       "b 6f\n"
113       "5:"  // Width 1: no bias
114       ".inst 0xc00800ff  // zero { zad0, zad1, zad2, zad3, zad4, zad5, zad6, zad7 }\n"
115       "6:"  // Width 1: setup done
116       "cmp x20, #0x4\n"
117       "ble 8f\n"
118       "7:"  // Width 1: Multiply loop: Main loop head
119       "whilelt p0.s, XZR, x20\n"
120       "ld1rqw { z10.s }, p0/Z, [x22]\n"
121       "sub x20, x20, #0x4\n"
122       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
123       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
124       "addvl x25, x25, #16\n"
125       "cmp x20, #0x4\n"
126       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
127       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
128       "addvl x25, x25, #16\n"
129       "add x22, x22, #0x10\n"
130       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
131       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
132       "addvl x25, x25, #16\n"
133       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
134       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
135       "addvl x25, x25, #16\n"
136       "bgt 7b\n"
137       "8:"  // Width 1: Multiply loop: Single iteration only
138       "whilelt p0.s, XZR, x20\n"
139       "ld1rqw { z10.s }, p0/Z, [x22]\n"
140       "subs x20, x20, #0x1\n"
141       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
142       "add x22, x22, #0x10\n"
143       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
144       "addvl x25, x25, #16\n"
145       "ble 9f\n"
146       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
147       "subs x20, x20, #0x1\n"
148       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
149       "addvl x25, x25, #16\n"
150       "ble 9f\n"
151       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
152       "subs x20, x20, #0x1\n"
153       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
154       "addvl x25, x25, #16\n"
155       "ble 9f\n"
156       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
157       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
158       "addvl x25, x25, #16\n"
159       "9:"  // Width 1: Multiply loop: multiply skip
160       "tbz %x[flags], #1, 10f\n"
161       "add x20, %x[args_ptr], %[offset_min]\n"
162       "add x19, %x[args_ptr], %[offset_max]\n"
163       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
164       "ld1rw { z0.s }, p1/Z, [x20]\n"
165       "ld1rw { z6.s }, p1/Z, [x19]\n"
166       ".inst 0xc1a6c808  // fclamp { z8.s-z11.s }, z0.s, z6.s\n"
167       ".inst 0xa060c308  // st1w { z8.s-z11.s }, p8, [x24]\n"
168       "addvl x24, x24, #4\n"
169       "b 11f\n"
170       "10:"  // Width 1: No activation
171       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
172       ".inst 0xa060c308  // st1w { z8.s-z11.s }, p8, [x24]\n"
173       "addvl x24, x24, #4\n"
174       "11:"  // Width 1: Output done
175       "b 36f\n"
176       "12:"  // Width 2
177       "mov x22, %x[A_ptr]\n"
178       "lsl x21, %x[K], #0x2\n"
179       "sub x19, %x[N], x27\n"
180       "mov x20, %x[K]\n"
181       ".inst 0xf8b54ad8  // rprfm pldmany, x21, [x22]\n"
182       ".inst 0x25b367f0  // whilelt p8.s, XZR, x19, VLx4\n"
183       "cbz x23, 13f\n"
184       ".inst 0xa040c6e0  // ld1w { z0.s-z3.s }, pn9.b/Z, [x23]\n"
185       ".inst 0xc0042c00  // mova za.d[x9, #0], { z0.d-z3.d }\n"
186       ".inst 0xa041c6e8  // ld1w { z8.s-z11.s }, pn9.b/Z, [x23, #0x4, MUL VL]\n"
187       ".inst 0xc0042d01  // mova za.d[x9, #1], { z8.d-z11.d }\n"
188       "b 14f\n"
189       "13:"  // Width 2: no bias
190       ".inst 0xc00800ff  // zero { zad0, zad1, zad2, zad3, zad4, zad5, zad6, zad7 }\n"
191       "14:"  // Width 2: setup done
192       "cmp x20, #0x4\n"
193       "ble 16f\n"
194       "15:"  // Width 2: Multiply loop: Main loop head
195       "whilelt p0.s, XZR, x20\n"
196       "ld1rqw { z10.s }, p0/Z, [x22]\n"
197       "sub x20, x20, #0x4\n"
198       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
199       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
200       "cmp x20, #0x4\n"
201       "add x22, x22, #0x10\n"
202       ".inst 0xa041c725  // ldnt1w { z4.s-z7.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
203       ".inst 0xc15aa081  // fmla za.s[x9, 1], { z4.s-z7.s }, z10.s[0]\n"
204       "addvl x25, x25, #16\n"
205       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
206       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
207       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
208       ".inst 0xc15aa601  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[1]\n"
209       "addvl x25, x25, #16\n"
210       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
211       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
212       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
213       ".inst 0xc15aaa01  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[2]\n"
214       "addvl x25, x25, #16\n"
215       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
216       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
217       ".inst 0xa041c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
218       ".inst 0xc15aaf01  // fmla za.s[x9, 1], { z24.s-z27.s }, z10.s[3]\n"
219       "addvl x25, x25, #16\n"
220       "bgt 15b\n"
221       "16:"  // Width 2: Multiply loop: Single iteration only
222       "whilelt p0.s, XZR, x20\n"
223       "ld1rqw { z10.s }, p0/Z, [x22]\n"
224       "subs x20, x20, #0x1\n"
225       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
226       "add x22, x22, #0x10\n"
227       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
228       ".inst 0xa041c725  // ldnt1w { z4.s-z7.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
229       ".inst 0xc15aa081  // fmla za.s[x9, 1], { z4.s-z7.s }, z10.s[0]\n"
230       "addvl x25, x25, #16\n"
231       "ble 17f\n"
232       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
233       "subs x20, x20, #0x1\n"
234       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
235       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
236       ".inst 0xc15aa601  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[1]\n"
237       "addvl x25, x25, #16\n"
238       "ble 17f\n"
239       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
240       "subs x20, x20, #0x1\n"
241       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
242       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
243       ".inst 0xc15aaa01  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[2]\n"
244       "addvl x25, x25, #16\n"
245       "ble 17f\n"
246       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
247       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
248       ".inst 0xa041c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
249       ".inst 0xc15aaf01  // fmla za.s[x9, 1], { z24.s-z27.s }, z10.s[3]\n"
250       "addvl x25, x25, #16\n"
251       "17:"  // Width 2: Multiply loop: multiply skip
252       "tbz %x[flags], #1, 18f\n"
253       "add x20, %x[args_ptr], %[offset_min]\n"
254       "add x19, %x[args_ptr], %[offset_max]\n"
255       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
256       "ld1rw { z0.s }, p1/Z, [x20]\n"
257       ".inst 0xc0062c34  // mova { z20.d-z23.d }, za.d[x9, #1]\n"
258       "ld1rw { z6.s }, p1/Z, [x19]\n"
259       ".inst 0xc1a6c808  // fclamp { z8.s-z11.s }, z0.s, z6.s\n"
260       ".inst 0xa060c708  // st1w { z8.s-z11.s }, pn9.b, [x24]\n"
261       ".inst 0xc1a6c814  // fclamp { z20.s-z23.s }, z0.s, z6.s\n"
262       ".inst 0xa061c314  // st1w { z20.s-z23.s }, p8, [x24, #0x4, MUL VL]\n"
263       "addvl x24, x24, #8\n"
264       "b 19f\n"
265       "18:"  // Width 2: No activation
266       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
267       ".inst 0xa060c708  // st1w { z8.s-z11.s }, pn9.b, [x24]\n"
268       ".inst 0xc0062c34  // mova { z20.d-z23.d }, za.d[x9, #1]\n"
269       ".inst 0xa061c314  // st1w { z20.s-z23.s }, p8, [x24, #0x4, MUL VL]\n"
270       "addvl x24, x24, #8\n"
271       "19:"  // Width 2: Output done
272       "b 36f\n"
273       "20:"  // Width 3
274       "mov x19, #0x2\n"
275       "mov x22, %x[A_ptr]\n"
276       "lsl x21, %x[K], #0x2\n"
277       "msub x19, x27, x19, %x[N]\n"
278       "mov x20, %x[K]\n"
279       ".inst 0xf8b54ad8  // rprfm pldmany, x21, [x22]\n"
280       ".inst 0x25b367f0  // whilelt p8.s, XZR, x19, VLx4\n"
281       "cbz x23, 21f\n"
282       ".inst 0xa040c6e0  // ld1w { z0.s-z3.s }, pn9.b/Z, [x23]\n"
283       ".inst 0xc0042c00  // mova za.d[x9, #0], { z0.d-z3.d }\n"
284       ".inst 0xa041c6e8  // ld1w { z8.s-z11.s }, pn9.b/Z, [x23, #0x4, MUL VL]\n"
285       ".inst 0xc0042d01  // mova za.d[x9, #1], { z8.d-z11.d }\n"
286       ".inst 0xa042c6e4  // ld1w { z4.s-z7.s }, pn9.b/Z, [x23, #0x8, MUL VL]\n"
287       ".inst 0xc0042c82  // mova za.d[x9, #2], { z4.d-z7.d }\n"
288       "b 22f\n"
289       "21:"  // Width 3: no bias
290       ".inst 0xc00800ff  // zero { zad0, zad1, zad2, zad3, zad4, zad5, zad6, zad7 }\n"
291       "22:"  // Width 3: setup done
292       "cmp x20, #0x4\n"
293       "ble 24f\n"
294       "23:"  // Width 3: Multiply loop: Main loop head
295       "whilelt p0.s, XZR, x20\n"
296       "ld1rqw { z10.s }, p0/Z, [x22]\n"
297       "sub x20, x20, #0x4\n"
298       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
299       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
300       "cmp x20, #0x4\n"
301       "add x22, x22, #0x10\n"
302       ".inst 0xa041c725  // ldnt1w { z4.s-z7.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
303       ".inst 0xc15aa081  // fmla za.s[x9, 1], { z4.s-z7.s }, z10.s[0]\n"
304       ".inst 0xa042c735  // ldnt1w { z20.s-z23.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
305       ".inst 0xc15aa282  // fmla za.s[x9, 2], { z20.s-z23.s }, z10.s[0]\n"
306       "addvl x25, x25, #16\n"
307       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
308       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
309       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
310       ".inst 0xc15aa601  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[1]\n"
311       ".inst 0xa042c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
312       ".inst 0xc15aa702  // fmla za.s[x9, 2], { z24.s-z27.s }, z10.s[1]\n"
313       "addvl x25, x25, #16\n"
314       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
315       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
316       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
317       ".inst 0xc15aaa01  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[2]\n"
318       ".inst 0xa042c73d  // ldnt1w { z28.s-z31.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
319       ".inst 0xc15aab82  // fmla za.s[x9, 2], { z28.s-z31.s }, z10.s[2]\n"
320       "addvl x25, x25, #16\n"
321       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
322       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
323       ".inst 0xa041c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
324       ".inst 0xc15aaf01  // fmla za.s[x9, 1], { z24.s-z27.s }, z10.s[3]\n"
325       ".inst 0xa042c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
326       ".inst 0xc15aae02  // fmla za.s[x9, 2], { z16.s-z19.s }, z10.s[3]\n"
327       "addvl x25, x25, #16\n"
328       "bgt 23b\n"
329       "24:"  // Width 3: Multiply loop: Single iteration only
330       "whilelt p0.s, XZR, x20\n"
331       "ld1rqw { z10.s }, p0/Z, [x22]\n"
332       "subs x20, x20, #0x1\n"
333       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
334       "add x22, x22, #0x10\n"
335       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
336       ".inst 0xa041c725  // ldnt1w { z4.s-z7.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
337       ".inst 0xc15aa081  // fmla za.s[x9, 1], { z4.s-z7.s }, z10.s[0]\n"
338       ".inst 0xa042c735  // ldnt1w { z20.s-z23.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
339       ".inst 0xc15aa282  // fmla za.s[x9, 2], { z20.s-z23.s }, z10.s[0]\n"
340       "addvl x25, x25, #16\n"
341       "ble 25f\n"
342       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
343       "subs x20, x20, #0x1\n"
344       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
345       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
346       ".inst 0xc15aa601  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[1]\n"
347       ".inst 0xa042c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
348       ".inst 0xc15aa702  // fmla za.s[x9, 2], { z24.s-z27.s }, z10.s[1]\n"
349       "addvl x25, x25, #16\n"
350       "ble 25f\n"
351       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
352       "subs x20, x20, #0x1\n"
353       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
354       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
355       ".inst 0xc15aaa01  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[2]\n"
356       ".inst 0xa042c73d  // ldnt1w { z28.s-z31.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
357       ".inst 0xc15aab82  // fmla za.s[x9, 2], { z28.s-z31.s }, z10.s[2]\n"
358       "addvl x25, x25, #16\n"
359       "ble 25f\n"
360       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
361       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
362       ".inst 0xa041c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
363       ".inst 0xc15aaf01  // fmla za.s[x9, 1], { z24.s-z27.s }, z10.s[3]\n"
364       ".inst 0xa042c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
365       ".inst 0xc15aae02  // fmla za.s[x9, 2], { z16.s-z19.s }, z10.s[3]\n"
366       "addvl x25, x25, #16\n"
367       "25:"  // Width 3: Multiply loop: multiply skip
368       "tbz %x[flags], #1, 26f\n"
369       "add x20, %x[args_ptr], %[offset_min]\n"
370       "add x19, %x[args_ptr], %[offset_max]\n"
371       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
372       "ld1rw { z0.s }, p1/Z, [x20]\n"
373       ".inst 0xc0062c34  // mova { z20.d-z23.d }, za.d[x9, #1]\n"
374       "ld1rw { z6.s }, p1/Z, [x19]\n"
375       ".inst 0xc1a6c808  // fclamp { z8.s-z11.s }, z0.s, z6.s\n"
376       ".inst 0xc0062c50  // mova { z16.d-z19.d }, za.d[x9, #2]\n"
377       ".inst 0xa060c708  // st1w { z8.s-z11.s }, pn9.b, [x24]\n"
378       ".inst 0xc1a6c814  // fclamp { z20.s-z23.s }, z0.s, z6.s\n"
379       ".inst 0xa061c714  // st1w { z20.s-z23.s }, pn9.b, [x24, #0x4, MUL VL]\n"
380       ".inst 0xc1a6c810  // fclamp { z16.s-z19.s }, z0.s, z6.s\n"
381       ".inst 0xa062c310  // st1w { z16.s-z19.s }, p8, [x24, #0x8, MUL VL]\n"
382       "addvl x24, x24, #12\n"
383       "b 27f\n"
384       "26:"  // Width 3: No activation
385       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
386       ".inst 0xa060c708  // st1w { z8.s-z11.s }, pn9.b, [x24]\n"
387       ".inst 0xc0062c34  // mova { z20.d-z23.d }, za.d[x9, #1]\n"
388       ".inst 0xa061c714  // st1w { z20.s-z23.s }, pn9.b, [x24, #0x4, MUL VL]\n"
389       ".inst 0xc0062c50  // mova { z16.d-z19.d }, za.d[x9, #2]\n"
390       ".inst 0xa062c310  // st1w { z16.s-z19.s }, p8, [x24, #0x8, MUL VL]\n"
391       "addvl x24, x24, #12\n"
392       "27:"  // Width 3: Output done
393       "b 36f\n"
394       "28:"  // Width 4
395       "mov x19, #0x3\n"
396       "mov x22, %x[A_ptr]\n"
397       "lsl x21, %x[K], #0x2\n"
398       "msub x19, x27, x19, %x[N]\n"
399       "mov x20, %x[K]\n"
400       ".inst 0xf8b54ad8  // rprfm pldmany, x21, [x22]\n"
401       ".inst 0x25b367f0  // whilelt p8.s, XZR, x19, VLx4\n"
402       "cbz x23, 29f\n"
403       ".inst 0xa040c6e0  // ld1w { z0.s-z3.s }, pn9.b/Z, [x23]\n"
404       ".inst 0xc0042c00  // mova za.d[x9, #0], { z0.d-z3.d }\n"
405       ".inst 0xa041c6e8  // ld1w { z8.s-z11.s }, pn9.b/Z, [x23, #0x4, MUL VL]\n"
406       ".inst 0xc0042d01  // mova za.d[x9, #1], { z8.d-z11.d }\n"
407       ".inst 0xa042c6e4  // ld1w { z4.s-z7.s }, pn9.b/Z, [x23, #0x8, MUL VL]\n"
408       ".inst 0xc0042c82  // mova za.d[x9, #2], { z4.d-z7.d }\n"
409       ".inst 0xa043c6f0  // ld1w { z16.s-z19.s }, pn9.b/Z, [x23, #0xc, MUL VL]\n"
410       ".inst 0xc0042e03  // mova za.d[x9, #3], { z16.d-z19.d }\n"
411       "addvl x23, x23, #16\n"
412       "b 30f\n"
413       "29:"  // Width 4: no bias
414       ".inst 0xc00800ff  // zero { zad0, zad1, zad2, zad3, zad4, zad5, zad6, zad7 }\n"
415       "30:"  // Width 4: setup done
416       "cmp x20, #0x4\n"
417       "ble 32f\n"
418       "31:"  // Width 4: Multiply loop: Main loop head
419       "whilelt p0.s, XZR, x20\n"
420       "ld1rqw { z10.s }, p0/Z, [x22]\n"
421       "sub x20, x20, #0x4\n"
422       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
423       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
424       "cmp x20, #0x4\n"
425       "add x22, x22, #0x10\n"
426       ".inst 0xa041c725  // ldnt1w { z4.s-z7.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
427       ".inst 0xc15aa081  // fmla za.s[x9, 1], { z4.s-z7.s }, z10.s[0]\n"
428       ".inst 0xa042c735  // ldnt1w { z20.s-z23.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
429       ".inst 0xc15aa282  // fmla za.s[x9, 2], { z20.s-z23.s }, z10.s[0]\n"
430       ".inst 0xa043c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
431       ".inst 0xc15aa203  // fmla za.s[x9, 3], { z16.s-z19.s }, z10.s[0]\n"
432       "addvl x25, x25, #16\n"
433       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
434       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
435       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
436       ".inst 0xc15aa601  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[1]\n"
437       ".inst 0xa042c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
438       ".inst 0xc15aa702  // fmla za.s[x9, 2], { z24.s-z27.s }, z10.s[1]\n"
439       ".inst 0xa043c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
440       ".inst 0xc15aa603  // fmla za.s[x9, 3], { z16.s-z19.s }, z10.s[1]\n"
441       "addvl x25, x25, #16\n"
442       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
443       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
444       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
445       ".inst 0xc15aaa01  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[2]\n"
446       ".inst 0xa042c73d  // ldnt1w { z28.s-z31.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
447       ".inst 0xc15aab82  // fmla za.s[x9, 2], { z28.s-z31.s }, z10.s[2]\n"
448       ".inst 0xa043c735  // ldnt1w { z20.s-z23.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
449       ".inst 0xc15aaa83  // fmla za.s[x9, 3], { z20.s-z23.s }, z10.s[2]\n"
450       "addvl x25, x25, #16\n"
451       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
452       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
453       ".inst 0xa041c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
454       ".inst 0xc15aaf01  // fmla za.s[x9, 1], { z24.s-z27.s }, z10.s[3]\n"
455       ".inst 0xa042c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
456       ".inst 0xc15aae02  // fmla za.s[x9, 2], { z16.s-z19.s }, z10.s[3]\n"
457       ".inst 0xa043c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
458       ".inst 0xc15aae03  // fmla za.s[x9, 3], { z16.s-z19.s }, z10.s[3]\n"
459       "addvl x25, x25, #16\n"
460       "bgt 31b\n"
461       "32:"  // Width 4: Multiply loop: Single iteration only
462       "whilelt p0.s, XZR, x20\n"
463       "ld1rqw { z10.s }, p0/Z, [x22]\n"
464       "subs x20, x20, #0x1\n"
465       ".inst 0xa040c721  // ldnt1w { z0.s-z3.s }, pn9.b/Z, [x25]\n"
466       "add x22, x22, #0x10\n"
467       ".inst 0xc15aa000  // fmla za.s[x9, 0], { z0.s-z3.s }, z10.s[0]\n"
468       ".inst 0xa041c725  // ldnt1w { z4.s-z7.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
469       ".inst 0xc15aa081  // fmla za.s[x9, 1], { z4.s-z7.s }, z10.s[0]\n"
470       ".inst 0xa042c735  // ldnt1w { z20.s-z23.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
471       ".inst 0xc15aa282  // fmla za.s[x9, 2], { z20.s-z23.s }, z10.s[0]\n"
472       ".inst 0xa043c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
473       ".inst 0xc15aa203  // fmla za.s[x9, 3], { z16.s-z19.s }, z10.s[0]\n"
474       "addvl x25, x25, #16\n"
475       "ble 33f\n"
476       ".inst 0xa040c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25]\n"
477       "subs x20, x20, #0x1\n"
478       ".inst 0xc15aa700  // fmla za.s[x9, 0], { z24.s-z27.s }, z10.s[1]\n"
479       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
480       ".inst 0xc15aa601  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[1]\n"
481       ".inst 0xa042c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
482       ".inst 0xc15aa702  // fmla za.s[x9, 2], { z24.s-z27.s }, z10.s[1]\n"
483       ".inst 0xa043c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
484       ".inst 0xc15aa603  // fmla za.s[x9, 3], { z16.s-z19.s }, z10.s[1]\n"
485       "addvl x25, x25, #16\n"
486       "ble 33f\n"
487       ".inst 0xa040c72d  // ldnt1w { z12.s-z15.s }, pn9.b/Z, [x25]\n"
488       "subs x20, x20, #0x1\n"
489       ".inst 0xc15aa980  // fmla za.s[x9, 0], { z12.s-z15.s }, z10.s[2]\n"
490       ".inst 0xa041c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
491       ".inst 0xc15aaa01  // fmla za.s[x9, 1], { z16.s-z19.s }, z10.s[2]\n"
492       ".inst 0xa042c73d  // ldnt1w { z28.s-z31.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
493       ".inst 0xc15aab82  // fmla za.s[x9, 2], { z28.s-z31.s }, z10.s[2]\n"
494       ".inst 0xa043c735  // ldnt1w { z20.s-z23.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
495       ".inst 0xc15aaa83  // fmla za.s[x9, 3], { z20.s-z23.s }, z10.s[2]\n"
496       "addvl x25, x25, #16\n"
497       "ble 33f\n"
498       ".inst 0xa040c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25]\n"
499       ".inst 0xc15aae00  // fmla za.s[x9, 0], { z16.s-z19.s }, z10.s[3]\n"
500       ".inst 0xa041c739  // ldnt1w { z24.s-z27.s }, pn9.b/Z, [x25, #0x4, MUL VL]\n"
501       ".inst 0xc15aaf01  // fmla za.s[x9, 1], { z24.s-z27.s }, z10.s[3]\n"
502       ".inst 0xa042c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0x8, MUL VL]\n"
503       ".inst 0xc15aae02  // fmla za.s[x9, 2], { z16.s-z19.s }, z10.s[3]\n"
504       ".inst 0xa043c731  // ldnt1w { z16.s-z19.s }, pn9.b/Z, [x25, #0xc, MUL VL]\n"
505       ".inst 0xc15aae03  // fmla za.s[x9, 3], { z16.s-z19.s }, z10.s[3]\n"
506       "addvl x25, x25, #16\n"
507       "33:"  // Width 4: Multiply loop: multiply skip
508       "tbz %x[flags], #1, 34f\n"
509       "add x20, %x[args_ptr], %[offset_min]\n"
510       "add x19, %x[args_ptr], %[offset_max]\n"
511       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
512       "ld1rw { z0.s }, p1/Z, [x20]\n"
513       ".inst 0xc0062c34  // mova { z20.d-z23.d }, za.d[x9, #1]\n"
514       "ld1rw { z6.s }, p1/Z, [x19]\n"
515       ".inst 0xc1a6c808  // fclamp { z8.s-z11.s }, z0.s, z6.s\n"
516       ".inst 0xc0062c50  // mova { z16.d-z19.d }, za.d[x9, #2]\n"
517       ".inst 0xa060c708  // st1w { z8.s-z11.s }, pn9.b, [x24]\n"
518       ".inst 0xc1a6c814  // fclamp { z20.s-z23.s }, z0.s, z6.s\n"
519       ".inst 0xc0062c78  // mova { z24.d-z27.d }, za.d[x9, #3]\n"
520       ".inst 0xa061c714  // st1w { z20.s-z23.s }, pn9.b, [x24, #0x4, MUL VL]\n"
521       ".inst 0xc1a6c810  // fclamp { z16.s-z19.s }, z0.s, z6.s\n"
522       ".inst 0xa062c710  // st1w { z16.s-z19.s }, pn9.b, [x24, #0x8, MUL VL]\n"
523       ".inst 0xc1a6c818  // fclamp { z24.s-z27.s }, z0.s, z6.s\n"
524       ".inst 0xa063c318  // st1w { z24.s-z27.s }, p8, [x24, #0xc, MUL VL]\n"
525       "addvl x24, x24, #16\n"
526       "b 35f\n"
527       "34:"  // Width 4: No activation
528       ".inst 0xc0062c08  // mova { z8.d-z11.d }, za.d[x9, #0]\n"
529       ".inst 0xa060c708  // st1w { z8.s-z11.s }, pn9.b, [x24]\n"
530       ".inst 0xc0062c34  // mova { z20.d-z23.d }, za.d[x9, #1]\n"
531       ".inst 0xa061c714  // st1w { z20.s-z23.s }, pn9.b, [x24, #0x4, MUL VL]\n"
532       ".inst 0xc0062c50  // mova { z16.d-z19.d }, za.d[x9, #2]\n"
533       ".inst 0xa062c710  // st1w { z16.s-z19.s }, pn9.b, [x24, #0x8, MUL VL]\n"
534       ".inst 0xc0062c78  // mova { z24.d-z27.d }, za.d[x9, #3]\n"
535       ".inst 0xa063c318  // st1w { z24.s-z27.s }, p8, [x24, #0xc, MUL VL]\n"
536       "addvl x24, x24, #16\n"
537       "35:"  // Width 4: Output done
538       "subs x26, x26, #0x4\n"
539       "sub %x[N], %x[N], x27, LSL #2\n"
540       "bgt 4b\n"
541       "36:"  // Exit
542       ".inst 0xd503467f  // SMSTOP\n"
543       "ptrue p1.b\n"
544       : [N] "+&r" (N)
545       : [A_ptr] "r" (A_ptr), [B_ptr] "r" (B_ptr), [K] "r" (K), [args_ptr] "r" (&ka), [bias] "r" (bias), [flags] "r" (flags), [offset_max] "I" (offsetof(KernelArgs, maxval)), [offset_min] "I" (offsetof(KernelArgs, minval)), [output_ptr] "r" (output_ptr)
546       : "cc", "memory", "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", "x9", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10", "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21", "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31"
547     );
548 }
549 
550 } // namespace arm_gemm
551 
552 #endif // ARM_COMPUTE_ENABLE_SME2
553 #endif
554