1 // Copyright 2016 The Gemmlowp Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef GEMMLOWP_META_TRANSFORM_KERNELS_ARM_32_H_
16 #define GEMMLOWP_META_TRANSFORM_KERNELS_ARM_32_H_
17
18 #ifdef GEMMLOWP_NEON_32
19
20 #include <cassert>
21 #include <cstdint>
22
23 namespace gemmlowp {
24 namespace meta {
25
26 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)27 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 0>::Transform(
28 const int32_t* input, const Requantize& params, uint8_t* output) {
29 #ifdef DEBUG
30 #ifdef DEBUG_METAGEMM_VERBOSE
31 std::cout << __FILE__ << "(" << __LINE__
32 << ") Requantize<int32_t, uint8_t, Requantize, 16, 0>::Transform()"
33 << std::endl
34 << std::flush;
35 #endif
36 #endif
37 int params_count_copy = params.count;
38 asm volatile(
39
40 // Requantize::Prepare
41 "vdup.32 q4, %[input_range_min]\n"
42 "vdup.32 q5, %[output_range_min]\n"
43 "vdup.32 q6, %[input_range_offset]\n"
44 "vdup.32 q7, %[input_range_scale]\n"
45 "vdup.32 q8, %[one_over_output_range_scale]\n"
46 "vsub.f32 q4, q4, q5\n"
47
48 "1:"
49 "subs %[count], %[count], #16\n"
50
51 // Requantize::Transform
52 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
53 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
54 "pld [%[input], #64]\n"
55 "vcvt.f32.s32 q0, q0\n"
56 "vcvt.f32.s32 q1, q1\n"
57 "vcvt.f32.s32 q2, q2\n"
58 "vcvt.f32.s32 q3, q3\n"
59 "vsub.f32 q0, q0, q6\n"
60 "vsub.f32 q1, q1, q6\n"
61 "vsub.f32 q2, q2, q6\n"
62 "vsub.f32 q3, q3, q6\n"
63 "vmul.f32 q0, q0, q7\n"
64 "vmul.f32 q1, q1, q7\n"
65 "vmul.f32 q2, q2, q7\n"
66 "vmul.f32 q3, q3, q7\n"
67 "vadd.f32 q0, q0, q4\n"
68 "vadd.f32 q1, q1, q4\n"
69 "vadd.f32 q2, q2, q4\n"
70 "vadd.f32 q3, q3, q4\n"
71 "vmul.f32 q0, q0, q8\n"
72 "vmul.f32 q1, q1, q8\n"
73 "vmul.f32 q2, q2, q8\n"
74 "vmul.f32 q3, q3, q8\n"
75 "vcvt.s32.f32 q0, q0\n"
76 "vcvt.s32.f32 q1, q1\n"
77 "vcvt.s32.f32 q2, q2\n"
78 "vcvt.s32.f32 q3, q3\n"
79 "vqmovn.s32 d0, q0\n"
80 "vqmovn.s32 d1, q1\n"
81 "vqmovn.s32 d4, q2\n"
82 "vqmovn.s32 d5, q3\n"
83 "vqmovun.s16 d0, q0\n"
84 "vqmovun.s16 d1, q2\n"
85
86 "vst1.32 {d0, d1}, [%[output]]!\n"
87 "pld [%[output]]\n"
88
89 "bne 1b\n"
90 : [count] "+r"(params_count_copy), [input] "+r"(input),
91 [output] "+r"(output)
92 : [input_range_min] "r"(params.input_range_min),
93 [output_range_min] "r"(params.output_range_min),
94 [input_range_offset] "r"(params.input_range_offset),
95 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
96 [input_range_scale] "r"(params.input_range_scale)
97 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
98 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
99 }
100
101 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)102 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 1>::Transform(
103 const int32_t* input, const Requantize& params, uint8_t* output) {
104 #ifdef DEBUG
105 #ifdef DEBUG_METAGEMM_VERBOSE
106 std::cout << __FILE__ << "(" << __LINE__
107 << ") Requantize<int32_t, uint8_t, Requantize, 16, 1>::Transform()"
108 << std::endl
109 << std::flush;
110 #endif
111 #endif
112 int params_count_copy = params.count;
113 asm volatile(
114
115 // Requantize::Prepare
116 "vdup.32 q4, %[input_range_min]\n"
117 "vdup.32 q5, %[output_range_min]\n"
118 "vdup.32 q6, %[input_range_offset]\n"
119 "vdup.32 q7, %[input_range_scale]\n"
120 "vdup.32 q8, %[one_over_output_range_scale]\n"
121 "vsub.f32 q4, q4, q5\n"
122
123 // Reduce count by leftovers.
124 "subs %[count], %[count], #1\n"
125 "beq 2f\n"
126
127 "1:"
128 "subs %[count], %[count], #16\n"
129
130 // Requantize::Transform
131 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
132 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
133 "pld [%[input], #64]\n"
134 "vcvt.f32.s32 q0, q0\n"
135 "vcvt.f32.s32 q1, q1\n"
136 "vcvt.f32.s32 q2, q2\n"
137 "vcvt.f32.s32 q3, q3\n"
138 "vsub.f32 q0, q0, q6\n"
139 "vsub.f32 q1, q1, q6\n"
140 "vsub.f32 q2, q2, q6\n"
141 "vsub.f32 q3, q3, q6\n"
142 "vmul.f32 q0, q0, q7\n"
143 "vmul.f32 q1, q1, q7\n"
144 "vmul.f32 q2, q2, q7\n"
145 "vmul.f32 q3, q3, q7\n"
146 "vadd.f32 q0, q0, q4\n"
147 "vadd.f32 q1, q1, q4\n"
148 "vadd.f32 q2, q2, q4\n"
149 "vadd.f32 q3, q3, q4\n"
150 "vmul.f32 q0, q0, q8\n"
151 "vmul.f32 q1, q1, q8\n"
152 "vmul.f32 q2, q2, q8\n"
153 "vmul.f32 q3, q3, q8\n"
154 "vcvt.s32.f32 q0, q0\n"
155 "vcvt.s32.f32 q1, q1\n"
156 "vcvt.s32.f32 q2, q2\n"
157 "vcvt.s32.f32 q3, q3\n"
158 "vqmovn.s32 d0, q0\n"
159 "vqmovn.s32 d1, q1\n"
160 "vqmovn.s32 d4, q2\n"
161 "vqmovn.s32 d5, q3\n"
162 "vqmovun.s16 d0, q0\n"
163 "vqmovun.s16 d1, q2\n"
164
165 "vst1.32 {d0, d1}, [%[output]]!\n"
166 "pld [%[output]]\n"
167
168 "bne 1b\n"
169 "2:"
170
171 // Handle leftovers.
172
173 // Requantize::Transform
174 "vld1.32 {d0[0]}, [%[input]]!\n"
175 "pld [%[input], #64]\n"
176 "vcvt.f32.s32 q0, q0\n"
177 "vsub.f32 q0, q0, q6\n"
178 "vmul.f32 q0, q0, q7\n"
179 "vadd.f32 q0, q0, q4\n"
180 "vmul.f32 q0, q0, q8\n"
181 "vcvt.s32.f32 q0, q0\n"
182 "vqmovn.s32 d0, q0\n"
183 "vqmovun.s16 d0, q0\n"
184
185 "vst1.8 {d0[0]}, [%[output]]!\n"
186 "pld [%[output]]\n"
187 : [count] "+r"(params_count_copy), [input] "+r"(input),
188 [output] "+r"(output)
189 : [input_range_min] "r"(params.input_range_min),
190 [output_range_min] "r"(params.output_range_min),
191 [input_range_offset] "r"(params.input_range_offset),
192 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
193 [input_range_scale] "r"(params.input_range_scale)
194 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
195 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
196 }
197
198 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)199 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 2>::Transform(
200 const int32_t* input, const Requantize& params, uint8_t* output) {
201 #ifdef DEBUG
202 #ifdef DEBUG_METAGEMM_VERBOSE
203 std::cout << __FILE__ << "(" << __LINE__
204 << ") Requantize<int32_t, uint8_t, Requantize, 16, 2>::Transform()"
205 << std::endl
206 << std::flush;
207 #endif
208 #endif
209 int params_count_copy = params.count;
210 asm volatile(
211
212 // Requantize::Prepare
213 "vdup.32 q4, %[input_range_min]\n"
214 "vdup.32 q5, %[output_range_min]\n"
215 "vdup.32 q6, %[input_range_offset]\n"
216 "vdup.32 q7, %[input_range_scale]\n"
217 "vdup.32 q8, %[one_over_output_range_scale]\n"
218 "vsub.f32 q4, q4, q5\n"
219
220 // Reduce count by leftovers.
221 "subs %[count], %[count], #2\n"
222 "beq 2f\n"
223
224 "1:"
225 "subs %[count], %[count], #16\n"
226
227 // Requantize::Transform
228 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
229 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
230 "pld [%[input], #64]\n"
231 "vcvt.f32.s32 q0, q0\n"
232 "vcvt.f32.s32 q1, q1\n"
233 "vcvt.f32.s32 q2, q2\n"
234 "vcvt.f32.s32 q3, q3\n"
235 "vsub.f32 q0, q0, q6\n"
236 "vsub.f32 q1, q1, q6\n"
237 "vsub.f32 q2, q2, q6\n"
238 "vsub.f32 q3, q3, q6\n"
239 "vmul.f32 q0, q0, q7\n"
240 "vmul.f32 q1, q1, q7\n"
241 "vmul.f32 q2, q2, q7\n"
242 "vmul.f32 q3, q3, q7\n"
243 "vadd.f32 q0, q0, q4\n"
244 "vadd.f32 q1, q1, q4\n"
245 "vadd.f32 q2, q2, q4\n"
246 "vadd.f32 q3, q3, q4\n"
247 "vmul.f32 q0, q0, q8\n"
248 "vmul.f32 q1, q1, q8\n"
249 "vmul.f32 q2, q2, q8\n"
250 "vmul.f32 q3, q3, q8\n"
251 "vcvt.s32.f32 q0, q0\n"
252 "vcvt.s32.f32 q1, q1\n"
253 "vcvt.s32.f32 q2, q2\n"
254 "vcvt.s32.f32 q3, q3\n"
255 "vqmovn.s32 d0, q0\n"
256 "vqmovn.s32 d1, q1\n"
257 "vqmovn.s32 d4, q2\n"
258 "vqmovn.s32 d5, q3\n"
259 "vqmovun.s16 d0, q0\n"
260 "vqmovun.s16 d1, q2\n"
261
262 "vst1.32 {d0, d1}, [%[output]]!\n"
263 "pld [%[output]]\n"
264
265 "bne 1b\n"
266 "2:"
267
268 // Handle leftovers.
269
270 // Requantize::Transform
271 "vld1.32 {d0}, [%[input]]!\n"
272 "pld [%[input], #64]\n"
273 "vcvt.f32.s32 q0, q0\n"
274 "vsub.f32 q0, q0, q6\n"
275 "vmul.f32 q0, q0, q7\n"
276 "vadd.f32 q0, q0, q4\n"
277 "vmul.f32 q0, q0, q8\n"
278 "vcvt.s32.f32 q0, q0\n"
279 "vqmovn.s32 d0, q0\n"
280 "vqmovun.s16 d0, q0\n"
281
282 "vst1.16 {d0[0]}, [%[output]]!\n"
283 "pld [%[output]]\n"
284 : [count] "+r"(params_count_copy), [input] "+r"(input),
285 [output] "+r"(output)
286 : [input_range_min] "r"(params.input_range_min),
287 [output_range_min] "r"(params.output_range_min),
288 [input_range_offset] "r"(params.input_range_offset),
289 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
290 [input_range_scale] "r"(params.input_range_scale)
291 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
292 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
293 }
294
295 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)296 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 3>::Transform(
297 const int32_t* input, const Requantize& params, uint8_t* output) {
298 #ifdef DEBUG
299 #ifdef DEBUG_METAGEMM_VERBOSE
300 std::cout << __FILE__ << "(" << __LINE__
301 << ") Requantize<int32_t, uint8_t, Requantize, 16, 3>::Transform()"
302 << std::endl
303 << std::flush;
304 #endif
305 #endif
306 int params_count_copy = params.count;
307 asm volatile(
308
309 // Requantize::Prepare
310 "vdup.32 q4, %[input_range_min]\n"
311 "vdup.32 q5, %[output_range_min]\n"
312 "vdup.32 q6, %[input_range_offset]\n"
313 "vdup.32 q7, %[input_range_scale]\n"
314 "vdup.32 q8, %[one_over_output_range_scale]\n"
315 "vsub.f32 q4, q4, q5\n"
316
317 // Reduce count by leftovers.
318 "subs %[count], %[count], #3\n"
319 "beq 2f\n"
320
321 "1:"
322 "subs %[count], %[count], #16\n"
323
324 // Requantize::Transform
325 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
326 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
327 "pld [%[input], #64]\n"
328 "vcvt.f32.s32 q0, q0\n"
329 "vcvt.f32.s32 q1, q1\n"
330 "vcvt.f32.s32 q2, q2\n"
331 "vcvt.f32.s32 q3, q3\n"
332 "vsub.f32 q0, q0, q6\n"
333 "vsub.f32 q1, q1, q6\n"
334 "vsub.f32 q2, q2, q6\n"
335 "vsub.f32 q3, q3, q6\n"
336 "vmul.f32 q0, q0, q7\n"
337 "vmul.f32 q1, q1, q7\n"
338 "vmul.f32 q2, q2, q7\n"
339 "vmul.f32 q3, q3, q7\n"
340 "vadd.f32 q0, q0, q4\n"
341 "vadd.f32 q1, q1, q4\n"
342 "vadd.f32 q2, q2, q4\n"
343 "vadd.f32 q3, q3, q4\n"
344 "vmul.f32 q0, q0, q8\n"
345 "vmul.f32 q1, q1, q8\n"
346 "vmul.f32 q2, q2, q8\n"
347 "vmul.f32 q3, q3, q8\n"
348 "vcvt.s32.f32 q0, q0\n"
349 "vcvt.s32.f32 q1, q1\n"
350 "vcvt.s32.f32 q2, q2\n"
351 "vcvt.s32.f32 q3, q3\n"
352 "vqmovn.s32 d0, q0\n"
353 "vqmovn.s32 d1, q1\n"
354 "vqmovn.s32 d4, q2\n"
355 "vqmovn.s32 d5, q3\n"
356 "vqmovun.s16 d0, q0\n"
357 "vqmovun.s16 d1, q2\n"
358
359 "vst1.32 {d0, d1}, [%[output]]!\n"
360 "pld [%[output]]\n"
361
362 "bne 1b\n"
363 "2:"
364
365 // Handle leftovers.
366
367 // Requantize::Transform
368 "vld1.32 {d0}, [%[input]]!\n"
369 "vld1.32 {d1[0]}, [%[input]]!\n"
370 "pld [%[input], #64]\n"
371 "vcvt.f32.s32 q0, q0\n"
372 "vsub.f32 q0, q0, q6\n"
373 "vmul.f32 q0, q0, q7\n"
374 "vadd.f32 q0, q0, q4\n"
375 "vmul.f32 q0, q0, q8\n"
376 "vcvt.s32.f32 q0, q0\n"
377 "vqmovn.s32 d0, q0\n"
378 "vqmovun.s16 d0, q0\n"
379
380 "vst1.16 {d0[0]}, [%[output]]!\n"
381 "vst1.8 {d0[2]}, [%[output]]!\n"
382 "pld [%[output]]\n"
383 : [count] "+r"(params_count_copy), [input] "+r"(input),
384 [output] "+r"(output)
385 : [input_range_min] "r"(params.input_range_min),
386 [output_range_min] "r"(params.output_range_min),
387 [input_range_offset] "r"(params.input_range_offset),
388 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
389 [input_range_scale] "r"(params.input_range_scale)
390 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
391 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
392 }
393
394 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)395 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 4>::Transform(
396 const int32_t* input, const Requantize& params, uint8_t* output) {
397 #ifdef DEBUG
398 #ifdef DEBUG_METAGEMM_VERBOSE
399 std::cout << __FILE__ << "(" << __LINE__
400 << ") Requantize<int32_t, uint8_t, Requantize, 16, 4>::Transform()"
401 << std::endl
402 << std::flush;
403 #endif
404 #endif
405 int params_count_copy = params.count;
406 asm volatile(
407
408 // Requantize::Prepare
409 "vdup.32 q4, %[input_range_min]\n"
410 "vdup.32 q5, %[output_range_min]\n"
411 "vdup.32 q6, %[input_range_offset]\n"
412 "vdup.32 q7, %[input_range_scale]\n"
413 "vdup.32 q8, %[one_over_output_range_scale]\n"
414 "vsub.f32 q4, q4, q5\n"
415
416 // Reduce count by leftovers.
417 "subs %[count], %[count], #4\n"
418 "beq 2f\n"
419
420 "1:"
421 "subs %[count], %[count], #16\n"
422
423 // Requantize::Transform
424 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
425 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
426 "pld [%[input], #64]\n"
427 "vcvt.f32.s32 q0, q0\n"
428 "vcvt.f32.s32 q1, q1\n"
429 "vcvt.f32.s32 q2, q2\n"
430 "vcvt.f32.s32 q3, q3\n"
431 "vsub.f32 q0, q0, q6\n"
432 "vsub.f32 q1, q1, q6\n"
433 "vsub.f32 q2, q2, q6\n"
434 "vsub.f32 q3, q3, q6\n"
435 "vmul.f32 q0, q0, q7\n"
436 "vmul.f32 q1, q1, q7\n"
437 "vmul.f32 q2, q2, q7\n"
438 "vmul.f32 q3, q3, q7\n"
439 "vadd.f32 q0, q0, q4\n"
440 "vadd.f32 q1, q1, q4\n"
441 "vadd.f32 q2, q2, q4\n"
442 "vadd.f32 q3, q3, q4\n"
443 "vmul.f32 q0, q0, q8\n"
444 "vmul.f32 q1, q1, q8\n"
445 "vmul.f32 q2, q2, q8\n"
446 "vmul.f32 q3, q3, q8\n"
447 "vcvt.s32.f32 q0, q0\n"
448 "vcvt.s32.f32 q1, q1\n"
449 "vcvt.s32.f32 q2, q2\n"
450 "vcvt.s32.f32 q3, q3\n"
451 "vqmovn.s32 d0, q0\n"
452 "vqmovn.s32 d1, q1\n"
453 "vqmovn.s32 d4, q2\n"
454 "vqmovn.s32 d5, q3\n"
455 "vqmovun.s16 d0, q0\n"
456 "vqmovun.s16 d1, q2\n"
457
458 "vst1.32 {d0, d1}, [%[output]]!\n"
459 "pld [%[output]]\n"
460
461 "bne 1b\n"
462 "2:"
463
464 // Handle leftovers.
465
466 // Requantize::Transform
467 "vld1.32 {d0, d1}, [%[input]]!\n"
468 "pld [%[input], #64]\n"
469 "vcvt.f32.s32 q0, q0\n"
470 "vsub.f32 q0, q0, q6\n"
471 "vmul.f32 q0, q0, q7\n"
472 "vadd.f32 q0, q0, q4\n"
473 "vmul.f32 q0, q0, q8\n"
474 "vcvt.s32.f32 q0, q0\n"
475 "vqmovn.s32 d0, q0\n"
476 "vqmovun.s16 d0, q0\n"
477
478 "vst1.32 {d0[0]}, [%[output]]!\n"
479 "pld [%[output]]\n"
480 : [count] "+r"(params_count_copy), [input] "+r"(input),
481 [output] "+r"(output)
482 : [input_range_min] "r"(params.input_range_min),
483 [output_range_min] "r"(params.output_range_min),
484 [input_range_offset] "r"(params.input_range_offset),
485 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
486 [input_range_scale] "r"(params.input_range_scale)
487 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
488 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
489 }
490
491 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)492 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 5>::Transform(
493 const int32_t* input, const Requantize& params, uint8_t* output) {
494 #ifdef DEBUG
495 #ifdef DEBUG_METAGEMM_VERBOSE
496 std::cout << __FILE__ << "(" << __LINE__
497 << ") Requantize<int32_t, uint8_t, Requantize, 16, 5>::Transform()"
498 << std::endl
499 << std::flush;
500 #endif
501 #endif
502 int params_count_copy = params.count;
503 asm volatile(
504
505 // Requantize::Prepare
506 "vdup.32 q4, %[input_range_min]\n"
507 "vdup.32 q5, %[output_range_min]\n"
508 "vdup.32 q6, %[input_range_offset]\n"
509 "vdup.32 q7, %[input_range_scale]\n"
510 "vdup.32 q8, %[one_over_output_range_scale]\n"
511 "vsub.f32 q4, q4, q5\n"
512
513 // Reduce count by leftovers.
514 "subs %[count], %[count], #5\n"
515 "beq 2f\n"
516
517 "1:"
518 "subs %[count], %[count], #16\n"
519
520 // Requantize::Transform
521 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
522 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
523 "pld [%[input], #64]\n"
524 "vcvt.f32.s32 q0, q0\n"
525 "vcvt.f32.s32 q1, q1\n"
526 "vcvt.f32.s32 q2, q2\n"
527 "vcvt.f32.s32 q3, q3\n"
528 "vsub.f32 q0, q0, q6\n"
529 "vsub.f32 q1, q1, q6\n"
530 "vsub.f32 q2, q2, q6\n"
531 "vsub.f32 q3, q3, q6\n"
532 "vmul.f32 q0, q0, q7\n"
533 "vmul.f32 q1, q1, q7\n"
534 "vmul.f32 q2, q2, q7\n"
535 "vmul.f32 q3, q3, q7\n"
536 "vadd.f32 q0, q0, q4\n"
537 "vadd.f32 q1, q1, q4\n"
538 "vadd.f32 q2, q2, q4\n"
539 "vadd.f32 q3, q3, q4\n"
540 "vmul.f32 q0, q0, q8\n"
541 "vmul.f32 q1, q1, q8\n"
542 "vmul.f32 q2, q2, q8\n"
543 "vmul.f32 q3, q3, q8\n"
544 "vcvt.s32.f32 q0, q0\n"
545 "vcvt.s32.f32 q1, q1\n"
546 "vcvt.s32.f32 q2, q2\n"
547 "vcvt.s32.f32 q3, q3\n"
548 "vqmovn.s32 d0, q0\n"
549 "vqmovn.s32 d1, q1\n"
550 "vqmovn.s32 d4, q2\n"
551 "vqmovn.s32 d5, q3\n"
552 "vqmovun.s16 d0, q0\n"
553 "vqmovun.s16 d1, q2\n"
554
555 "vst1.32 {d0, d1}, [%[output]]!\n"
556 "pld [%[output]]\n"
557
558 "bne 1b\n"
559 "2:"
560
561 // Handle leftovers.
562
563 // Requantize::Transform
564 "vld1.32 {d0, d1}, [%[input]]!\n"
565 "vld1.32 {d2[0]}, [%[input]]!\n"
566 "pld [%[input], #64]\n"
567 "vcvt.f32.s32 q0, q0\n"
568 "vcvt.f32.s32 q1, q1\n"
569 "vsub.f32 q0, q0, q6\n"
570 "vsub.f32 q1, q1, q6\n"
571 "vmul.f32 q0, q0, q7\n"
572 "vmul.f32 q1, q1, q7\n"
573 "vadd.f32 q0, q0, q4\n"
574 "vadd.f32 q1, q1, q4\n"
575 "vmul.f32 q0, q0, q8\n"
576 "vmul.f32 q1, q1, q8\n"
577 "vcvt.s32.f32 q0, q0\n"
578 "vcvt.s32.f32 q1, q1\n"
579 "vqmovn.s32 d0, q0\n"
580 "vqmovn.s32 d1, q1\n"
581 "vqmovun.s16 d0, q0\n"
582
583 "vst1.32 {d0[0]}, [%[output]]!\n"
584 "vst1.8 {d0[4]}, [%[output]]!\n"
585 "pld [%[output]]\n"
586 : [count] "+r"(params_count_copy), [input] "+r"(input),
587 [output] "+r"(output)
588 : [input_range_min] "r"(params.input_range_min),
589 [output_range_min] "r"(params.output_range_min),
590 [input_range_offset] "r"(params.input_range_offset),
591 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
592 [input_range_scale] "r"(params.input_range_scale)
593 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
594 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
595 }
596
597 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)598 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 6>::Transform(
599 const int32_t* input, const Requantize& params, uint8_t* output) {
600 #ifdef DEBUG
601 #ifdef DEBUG_METAGEMM_VERBOSE
602 std::cout << __FILE__ << "(" << __LINE__
603 << ") Requantize<int32_t, uint8_t, Requantize, 16, 6>::Transform()"
604 << std::endl
605 << std::flush;
606 #endif
607 #endif
608 int params_count_copy = params.count;
609 asm volatile(
610
611 // Requantize::Prepare
612 "vdup.32 q4, %[input_range_min]\n"
613 "vdup.32 q5, %[output_range_min]\n"
614 "vdup.32 q6, %[input_range_offset]\n"
615 "vdup.32 q7, %[input_range_scale]\n"
616 "vdup.32 q8, %[one_over_output_range_scale]\n"
617 "vsub.f32 q4, q4, q5\n"
618
619 // Reduce count by leftovers.
620 "subs %[count], %[count], #6\n"
621 "beq 2f\n"
622
623 "1:"
624 "subs %[count], %[count], #16\n"
625
626 // Requantize::Transform
627 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
628 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
629 "pld [%[input], #64]\n"
630 "vcvt.f32.s32 q0, q0\n"
631 "vcvt.f32.s32 q1, q1\n"
632 "vcvt.f32.s32 q2, q2\n"
633 "vcvt.f32.s32 q3, q3\n"
634 "vsub.f32 q0, q0, q6\n"
635 "vsub.f32 q1, q1, q6\n"
636 "vsub.f32 q2, q2, q6\n"
637 "vsub.f32 q3, q3, q6\n"
638 "vmul.f32 q0, q0, q7\n"
639 "vmul.f32 q1, q1, q7\n"
640 "vmul.f32 q2, q2, q7\n"
641 "vmul.f32 q3, q3, q7\n"
642 "vadd.f32 q0, q0, q4\n"
643 "vadd.f32 q1, q1, q4\n"
644 "vadd.f32 q2, q2, q4\n"
645 "vadd.f32 q3, q3, q4\n"
646 "vmul.f32 q0, q0, q8\n"
647 "vmul.f32 q1, q1, q8\n"
648 "vmul.f32 q2, q2, q8\n"
649 "vmul.f32 q3, q3, q8\n"
650 "vcvt.s32.f32 q0, q0\n"
651 "vcvt.s32.f32 q1, q1\n"
652 "vcvt.s32.f32 q2, q2\n"
653 "vcvt.s32.f32 q3, q3\n"
654 "vqmovn.s32 d0, q0\n"
655 "vqmovn.s32 d1, q1\n"
656 "vqmovn.s32 d4, q2\n"
657 "vqmovn.s32 d5, q3\n"
658 "vqmovun.s16 d0, q0\n"
659 "vqmovun.s16 d1, q2\n"
660
661 "vst1.32 {d0, d1}, [%[output]]!\n"
662 "pld [%[output]]\n"
663
664 "bne 1b\n"
665 "2:"
666
667 // Handle leftovers.
668
669 // Requantize::Transform
670 "vld1.32 {d0, d1, d2}, [%[input]]!\n"
671 "pld [%[input], #64]\n"
672 "vcvt.f32.s32 q0, q0\n"
673 "vcvt.f32.s32 q1, q1\n"
674 "vsub.f32 q0, q0, q6\n"
675 "vsub.f32 q1, q1, q6\n"
676 "vmul.f32 q0, q0, q7\n"
677 "vmul.f32 q1, q1, q7\n"
678 "vadd.f32 q0, q0, q4\n"
679 "vadd.f32 q1, q1, q4\n"
680 "vmul.f32 q0, q0, q8\n"
681 "vmul.f32 q1, q1, q8\n"
682 "vcvt.s32.f32 q0, q0\n"
683 "vcvt.s32.f32 q1, q1\n"
684 "vqmovn.s32 d0, q0\n"
685 "vqmovn.s32 d1, q1\n"
686 "vqmovun.s16 d0, q0\n"
687
688 "vst1.32 {d0[0]}, [%[output]]!\n"
689 "vst1.16 {d0[2]}, [%[output]]!\n"
690 "pld [%[output]]\n"
691 : [count] "+r"(params_count_copy), [input] "+r"(input),
692 [output] "+r"(output)
693 : [input_range_min] "r"(params.input_range_min),
694 [output_range_min] "r"(params.output_range_min),
695 [input_range_offset] "r"(params.input_range_offset),
696 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
697 [input_range_scale] "r"(params.input_range_scale)
698 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
699 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
700 }
701
702 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)703 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 7>::Transform(
704 const int32_t* input, const Requantize& params, uint8_t* output) {
705 #ifdef DEBUG
706 #ifdef DEBUG_METAGEMM_VERBOSE
707 std::cout << __FILE__ << "(" << __LINE__
708 << ") Requantize<int32_t, uint8_t, Requantize, 16, 7>::Transform()"
709 << std::endl
710 << std::flush;
711 #endif
712 #endif
713 int params_count_copy = params.count;
714 asm volatile(
715
716 // Requantize::Prepare
717 "vdup.32 q4, %[input_range_min]\n"
718 "vdup.32 q5, %[output_range_min]\n"
719 "vdup.32 q6, %[input_range_offset]\n"
720 "vdup.32 q7, %[input_range_scale]\n"
721 "vdup.32 q8, %[one_over_output_range_scale]\n"
722 "vsub.f32 q4, q4, q5\n"
723
724 // Reduce count by leftovers.
725 "subs %[count], %[count], #7\n"
726 "beq 2f\n"
727
728 "1:"
729 "subs %[count], %[count], #16\n"
730
731 // Requantize::Transform
732 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
733 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
734 "pld [%[input], #64]\n"
735 "vcvt.f32.s32 q0, q0\n"
736 "vcvt.f32.s32 q1, q1\n"
737 "vcvt.f32.s32 q2, q2\n"
738 "vcvt.f32.s32 q3, q3\n"
739 "vsub.f32 q0, q0, q6\n"
740 "vsub.f32 q1, q1, q6\n"
741 "vsub.f32 q2, q2, q6\n"
742 "vsub.f32 q3, q3, q6\n"
743 "vmul.f32 q0, q0, q7\n"
744 "vmul.f32 q1, q1, q7\n"
745 "vmul.f32 q2, q2, q7\n"
746 "vmul.f32 q3, q3, q7\n"
747 "vadd.f32 q0, q0, q4\n"
748 "vadd.f32 q1, q1, q4\n"
749 "vadd.f32 q2, q2, q4\n"
750 "vadd.f32 q3, q3, q4\n"
751 "vmul.f32 q0, q0, q8\n"
752 "vmul.f32 q1, q1, q8\n"
753 "vmul.f32 q2, q2, q8\n"
754 "vmul.f32 q3, q3, q8\n"
755 "vcvt.s32.f32 q0, q0\n"
756 "vcvt.s32.f32 q1, q1\n"
757 "vcvt.s32.f32 q2, q2\n"
758 "vcvt.s32.f32 q3, q3\n"
759 "vqmovn.s32 d0, q0\n"
760 "vqmovn.s32 d1, q1\n"
761 "vqmovn.s32 d4, q2\n"
762 "vqmovn.s32 d5, q3\n"
763 "vqmovun.s16 d0, q0\n"
764 "vqmovun.s16 d1, q2\n"
765
766 "vst1.32 {d0, d1}, [%[output]]!\n"
767 "pld [%[output]]\n"
768
769 "bne 1b\n"
770 "2:"
771
772 // Handle leftovers.
773
774 // Requantize::Transform
775 "vld1.32 {d0, d1, d2}, [%[input]]!\n"
776 "vld1.32 {d3[0]}, [%[input]]!\n"
777 "pld [%[input], #64]\n"
778 "vcvt.f32.s32 q0, q0\n"
779 "vcvt.f32.s32 q1, q1\n"
780 "vsub.f32 q0, q0, q6\n"
781 "vsub.f32 q1, q1, q6\n"
782 "vmul.f32 q0, q0, q7\n"
783 "vmul.f32 q1, q1, q7\n"
784 "vadd.f32 q0, q0, q4\n"
785 "vadd.f32 q1, q1, q4\n"
786 "vmul.f32 q0, q0, q8\n"
787 "vmul.f32 q1, q1, q8\n"
788 "vcvt.s32.f32 q0, q0\n"
789 "vcvt.s32.f32 q1, q1\n"
790 "vqmovn.s32 d0, q0\n"
791 "vqmovn.s32 d1, q1\n"
792 "vqmovun.s16 d0, q0\n"
793
794 "vst1.32 {d0[0]}, [%[output]]!\n"
795 "vst1.16 {d0[2]}, [%[output]]!\n"
796 "vst1.8 {d0[6]}, [%[output]]!\n"
797 "pld [%[output]]\n"
798 : [count] "+r"(params_count_copy), [input] "+r"(input),
799 [output] "+r"(output)
800 : [input_range_min] "r"(params.input_range_min),
801 [output_range_min] "r"(params.output_range_min),
802 [input_range_offset] "r"(params.input_range_offset),
803 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
804 [input_range_scale] "r"(params.input_range_scale)
805 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
806 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
807 }
808
809 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)810 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 8>::Transform(
811 const int32_t* input, const Requantize& params, uint8_t* output) {
812 #ifdef DEBUG
813 #ifdef DEBUG_METAGEMM_VERBOSE
814 std::cout << __FILE__ << "(" << __LINE__
815 << ") Requantize<int32_t, uint8_t, Requantize, 16, 8>::Transform()"
816 << std::endl
817 << std::flush;
818 #endif
819 #endif
820 int params_count_copy = params.count;
821 asm volatile(
822
823 // Requantize::Prepare
824 "vdup.32 q4, %[input_range_min]\n"
825 "vdup.32 q5, %[output_range_min]\n"
826 "vdup.32 q6, %[input_range_offset]\n"
827 "vdup.32 q7, %[input_range_scale]\n"
828 "vdup.32 q8, %[one_over_output_range_scale]\n"
829 "vsub.f32 q4, q4, q5\n"
830
831 // Reduce count by leftovers.
832 "subs %[count], %[count], #8\n"
833 "beq 2f\n"
834
835 "1:"
836 "subs %[count], %[count], #16\n"
837
838 // Requantize::Transform
839 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
840 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
841 "pld [%[input], #64]\n"
842 "vcvt.f32.s32 q0, q0\n"
843 "vcvt.f32.s32 q1, q1\n"
844 "vcvt.f32.s32 q2, q2\n"
845 "vcvt.f32.s32 q3, q3\n"
846 "vsub.f32 q0, q0, q6\n"
847 "vsub.f32 q1, q1, q6\n"
848 "vsub.f32 q2, q2, q6\n"
849 "vsub.f32 q3, q3, q6\n"
850 "vmul.f32 q0, q0, q7\n"
851 "vmul.f32 q1, q1, q7\n"
852 "vmul.f32 q2, q2, q7\n"
853 "vmul.f32 q3, q3, q7\n"
854 "vadd.f32 q0, q0, q4\n"
855 "vadd.f32 q1, q1, q4\n"
856 "vadd.f32 q2, q2, q4\n"
857 "vadd.f32 q3, q3, q4\n"
858 "vmul.f32 q0, q0, q8\n"
859 "vmul.f32 q1, q1, q8\n"
860 "vmul.f32 q2, q2, q8\n"
861 "vmul.f32 q3, q3, q8\n"
862 "vcvt.s32.f32 q0, q0\n"
863 "vcvt.s32.f32 q1, q1\n"
864 "vcvt.s32.f32 q2, q2\n"
865 "vcvt.s32.f32 q3, q3\n"
866 "vqmovn.s32 d0, q0\n"
867 "vqmovn.s32 d1, q1\n"
868 "vqmovn.s32 d4, q2\n"
869 "vqmovn.s32 d5, q3\n"
870 "vqmovun.s16 d0, q0\n"
871 "vqmovun.s16 d1, q2\n"
872
873 "vst1.32 {d0, d1}, [%[output]]!\n"
874 "pld [%[output]]\n"
875
876 "bne 1b\n"
877 "2:"
878
879 // Handle leftovers.
880
881 // Requantize::Transform
882 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
883 "pld [%[input], #64]\n"
884 "vcvt.f32.s32 q0, q0\n"
885 "vcvt.f32.s32 q1, q1\n"
886 "vsub.f32 q0, q0, q6\n"
887 "vsub.f32 q1, q1, q6\n"
888 "vmul.f32 q0, q0, q7\n"
889 "vmul.f32 q1, q1, q7\n"
890 "vadd.f32 q0, q0, q4\n"
891 "vadd.f32 q1, q1, q4\n"
892 "vmul.f32 q0, q0, q8\n"
893 "vmul.f32 q1, q1, q8\n"
894 "vcvt.s32.f32 q0, q0\n"
895 "vcvt.s32.f32 q1, q1\n"
896 "vqmovn.s32 d0, q0\n"
897 "vqmovn.s32 d1, q1\n"
898 "vqmovun.s16 d0, q0\n"
899
900 "vst1.32 {d0}, [%[output]]!\n"
901 "pld [%[output]]\n"
902 : [count] "+r"(params_count_copy), [input] "+r"(input),
903 [output] "+r"(output)
904 : [input_range_min] "r"(params.input_range_min),
905 [output_range_min] "r"(params.output_range_min),
906 [input_range_offset] "r"(params.input_range_offset),
907 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
908 [input_range_scale] "r"(params.input_range_scale)
909 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
910 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
911 }
912
913 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)914 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 9>::Transform(
915 const int32_t* input, const Requantize& params, uint8_t* output) {
916 #ifdef DEBUG
917 #ifdef DEBUG_METAGEMM_VERBOSE
918 std::cout << __FILE__ << "(" << __LINE__
919 << ") Requantize<int32_t, uint8_t, Requantize, 16, 9>::Transform()"
920 << std::endl
921 << std::flush;
922 #endif
923 #endif
924 int params_count_copy = params.count;
925 asm volatile(
926
927 // Requantize::Prepare
928 "vdup.32 q4, %[input_range_min]\n"
929 "vdup.32 q5, %[output_range_min]\n"
930 "vdup.32 q6, %[input_range_offset]\n"
931 "vdup.32 q7, %[input_range_scale]\n"
932 "vdup.32 q8, %[one_over_output_range_scale]\n"
933 "vsub.f32 q4, q4, q5\n"
934
935 // Reduce count by leftovers.
936 "subs %[count], %[count], #9\n"
937 "beq 2f\n"
938
939 "1:"
940 "subs %[count], %[count], #16\n"
941
942 // Requantize::Transform
943 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
944 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
945 "pld [%[input], #64]\n"
946 "vcvt.f32.s32 q0, q0\n"
947 "vcvt.f32.s32 q1, q1\n"
948 "vcvt.f32.s32 q2, q2\n"
949 "vcvt.f32.s32 q3, q3\n"
950 "vsub.f32 q0, q0, q6\n"
951 "vsub.f32 q1, q1, q6\n"
952 "vsub.f32 q2, q2, q6\n"
953 "vsub.f32 q3, q3, q6\n"
954 "vmul.f32 q0, q0, q7\n"
955 "vmul.f32 q1, q1, q7\n"
956 "vmul.f32 q2, q2, q7\n"
957 "vmul.f32 q3, q3, q7\n"
958 "vadd.f32 q0, q0, q4\n"
959 "vadd.f32 q1, q1, q4\n"
960 "vadd.f32 q2, q2, q4\n"
961 "vadd.f32 q3, q3, q4\n"
962 "vmul.f32 q0, q0, q8\n"
963 "vmul.f32 q1, q1, q8\n"
964 "vmul.f32 q2, q2, q8\n"
965 "vmul.f32 q3, q3, q8\n"
966 "vcvt.s32.f32 q0, q0\n"
967 "vcvt.s32.f32 q1, q1\n"
968 "vcvt.s32.f32 q2, q2\n"
969 "vcvt.s32.f32 q3, q3\n"
970 "vqmovn.s32 d0, q0\n"
971 "vqmovn.s32 d1, q1\n"
972 "vqmovn.s32 d4, q2\n"
973 "vqmovn.s32 d5, q3\n"
974 "vqmovun.s16 d0, q0\n"
975 "vqmovun.s16 d1, q2\n"
976
977 "vst1.32 {d0, d1}, [%[output]]!\n"
978 "pld [%[output]]\n"
979
980 "bne 1b\n"
981 "2:"
982
983 // Handle leftovers.
984
985 // Requantize::Transform
986 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
987 "vld1.32 {d4[0]}, [%[input]]!\n"
988 "pld [%[input], #64]\n"
989 "vcvt.f32.s32 q0, q0\n"
990 "vcvt.f32.s32 q1, q1\n"
991 "vcvt.f32.s32 q2, q2\n"
992 "vsub.f32 q0, q0, q6\n"
993 "vsub.f32 q1, q1, q6\n"
994 "vsub.f32 q2, q2, q6\n"
995 "vmul.f32 q0, q0, q7\n"
996 "vmul.f32 q1, q1, q7\n"
997 "vmul.f32 q2, q2, q7\n"
998 "vadd.f32 q0, q0, q4\n"
999 "vadd.f32 q1, q1, q4\n"
1000 "vadd.f32 q2, q2, q4\n"
1001 "vmul.f32 q0, q0, q8\n"
1002 "vmul.f32 q1, q1, q8\n"
1003 "vmul.f32 q2, q2, q8\n"
1004 "vcvt.s32.f32 q0, q0\n"
1005 "vcvt.s32.f32 q1, q1\n"
1006 "vcvt.s32.f32 q2, q2\n"
1007 "vqmovn.s32 d0, q0\n"
1008 "vqmovn.s32 d1, q1\n"
1009 "vqmovn.s32 d4, q2\n"
1010 "vqmovun.s16 d0, q0\n"
1011 "vqmovun.s16 d1, q2\n"
1012
1013 "vst1.32 {d0}, [%[output]]!\n"
1014 "vst1.8 {d1[0]}, [%[output]]!\n"
1015 "pld [%[output]]\n"
1016 : [count] "+r"(params_count_copy), [input] "+r"(input),
1017 [output] "+r"(output)
1018 : [input_range_min] "r"(params.input_range_min),
1019 [output_range_min] "r"(params.output_range_min),
1020 [input_range_offset] "r"(params.input_range_offset),
1021 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
1022 [input_range_scale] "r"(params.input_range_scale)
1023 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1024 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
1025 }
1026
1027 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)1028 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 10>::Transform(
1029 const int32_t* input, const Requantize& params, uint8_t* output) {
1030 #ifdef DEBUG
1031 #ifdef DEBUG_METAGEMM_VERBOSE
1032 std::cout << __FILE__ << "(" << __LINE__
1033 << ") Requantize<int32_t, uint8_t, Requantize, 16, 10>::Transform()"
1034 << std::endl
1035 << std::flush;
1036 #endif
1037 #endif
1038 int params_count_copy = params.count;
1039 asm volatile(
1040
1041 // Requantize::Prepare
1042 "vdup.32 q4, %[input_range_min]\n"
1043 "vdup.32 q5, %[output_range_min]\n"
1044 "vdup.32 q6, %[input_range_offset]\n"
1045 "vdup.32 q7, %[input_range_scale]\n"
1046 "vdup.32 q8, %[one_over_output_range_scale]\n"
1047 "vsub.f32 q4, q4, q5\n"
1048
1049 // Reduce count by leftovers.
1050 "subs %[count], %[count], #10\n"
1051 "beq 2f\n"
1052
1053 "1:"
1054 "subs %[count], %[count], #16\n"
1055
1056 // Requantize::Transform
1057 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1058 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1059 "pld [%[input], #64]\n"
1060 "vcvt.f32.s32 q0, q0\n"
1061 "vcvt.f32.s32 q1, q1\n"
1062 "vcvt.f32.s32 q2, q2\n"
1063 "vcvt.f32.s32 q3, q3\n"
1064 "vsub.f32 q0, q0, q6\n"
1065 "vsub.f32 q1, q1, q6\n"
1066 "vsub.f32 q2, q2, q6\n"
1067 "vsub.f32 q3, q3, q6\n"
1068 "vmul.f32 q0, q0, q7\n"
1069 "vmul.f32 q1, q1, q7\n"
1070 "vmul.f32 q2, q2, q7\n"
1071 "vmul.f32 q3, q3, q7\n"
1072 "vadd.f32 q0, q0, q4\n"
1073 "vadd.f32 q1, q1, q4\n"
1074 "vadd.f32 q2, q2, q4\n"
1075 "vadd.f32 q3, q3, q4\n"
1076 "vmul.f32 q0, q0, q8\n"
1077 "vmul.f32 q1, q1, q8\n"
1078 "vmul.f32 q2, q2, q8\n"
1079 "vmul.f32 q3, q3, q8\n"
1080 "vcvt.s32.f32 q0, q0\n"
1081 "vcvt.s32.f32 q1, q1\n"
1082 "vcvt.s32.f32 q2, q2\n"
1083 "vcvt.s32.f32 q3, q3\n"
1084 "vqmovn.s32 d0, q0\n"
1085 "vqmovn.s32 d1, q1\n"
1086 "vqmovn.s32 d4, q2\n"
1087 "vqmovn.s32 d5, q3\n"
1088 "vqmovun.s16 d0, q0\n"
1089 "vqmovun.s16 d1, q2\n"
1090
1091 "vst1.32 {d0, d1}, [%[output]]!\n"
1092 "pld [%[output]]\n"
1093
1094 "bne 1b\n"
1095 "2:"
1096
1097 // Handle leftovers.
1098
1099 // Requantize::Transform
1100 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1101 "vld1.32 {d4}, [%[input]]!\n"
1102 "pld [%[input], #64]\n"
1103 "vcvt.f32.s32 q0, q0\n"
1104 "vcvt.f32.s32 q1, q1\n"
1105 "vcvt.f32.s32 q2, q2\n"
1106 "vsub.f32 q0, q0, q6\n"
1107 "vsub.f32 q1, q1, q6\n"
1108 "vsub.f32 q2, q2, q6\n"
1109 "vmul.f32 q0, q0, q7\n"
1110 "vmul.f32 q1, q1, q7\n"
1111 "vmul.f32 q2, q2, q7\n"
1112 "vadd.f32 q0, q0, q4\n"
1113 "vadd.f32 q1, q1, q4\n"
1114 "vadd.f32 q2, q2, q4\n"
1115 "vmul.f32 q0, q0, q8\n"
1116 "vmul.f32 q1, q1, q8\n"
1117 "vmul.f32 q2, q2, q8\n"
1118 "vcvt.s32.f32 q0, q0\n"
1119 "vcvt.s32.f32 q1, q1\n"
1120 "vcvt.s32.f32 q2, q2\n"
1121 "vqmovn.s32 d0, q0\n"
1122 "vqmovn.s32 d1, q1\n"
1123 "vqmovn.s32 d4, q2\n"
1124 "vqmovun.s16 d0, q0\n"
1125 "vqmovun.s16 d1, q2\n"
1126
1127 "vst1.32 {d0}, [%[output]]!\n"
1128 "vst1.16 {d1[0]}, [%[output]]!\n"
1129 "pld [%[output]]\n"
1130 : [count] "+r"(params_count_copy), [input] "+r"(input),
1131 [output] "+r"(output)
1132 : [input_range_min] "r"(params.input_range_min),
1133 [output_range_min] "r"(params.output_range_min),
1134 [input_range_offset] "r"(params.input_range_offset),
1135 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
1136 [input_range_scale] "r"(params.input_range_scale)
1137 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1138 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
1139 }
1140
1141 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)1142 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 11>::Transform(
1143 const int32_t* input, const Requantize& params, uint8_t* output) {
1144 #ifdef DEBUG
1145 #ifdef DEBUG_METAGEMM_VERBOSE
1146 std::cout << __FILE__ << "(" << __LINE__
1147 << ") Requantize<int32_t, uint8_t, Requantize, 16, 11>::Transform()"
1148 << std::endl
1149 << std::flush;
1150 #endif
1151 #endif
1152 int params_count_copy = params.count;
1153 asm volatile(
1154
1155 // Requantize::Prepare
1156 "vdup.32 q4, %[input_range_min]\n"
1157 "vdup.32 q5, %[output_range_min]\n"
1158 "vdup.32 q6, %[input_range_offset]\n"
1159 "vdup.32 q7, %[input_range_scale]\n"
1160 "vdup.32 q8, %[one_over_output_range_scale]\n"
1161 "vsub.f32 q4, q4, q5\n"
1162
1163 // Reduce count by leftovers.
1164 "subs %[count], %[count], #11\n"
1165 "beq 2f\n"
1166
1167 "1:"
1168 "subs %[count], %[count], #16\n"
1169
1170 // Requantize::Transform
1171 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1172 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1173 "pld [%[input], #64]\n"
1174 "vcvt.f32.s32 q0, q0\n"
1175 "vcvt.f32.s32 q1, q1\n"
1176 "vcvt.f32.s32 q2, q2\n"
1177 "vcvt.f32.s32 q3, q3\n"
1178 "vsub.f32 q0, q0, q6\n"
1179 "vsub.f32 q1, q1, q6\n"
1180 "vsub.f32 q2, q2, q6\n"
1181 "vsub.f32 q3, q3, q6\n"
1182 "vmul.f32 q0, q0, q7\n"
1183 "vmul.f32 q1, q1, q7\n"
1184 "vmul.f32 q2, q2, q7\n"
1185 "vmul.f32 q3, q3, q7\n"
1186 "vadd.f32 q0, q0, q4\n"
1187 "vadd.f32 q1, q1, q4\n"
1188 "vadd.f32 q2, q2, q4\n"
1189 "vadd.f32 q3, q3, q4\n"
1190 "vmul.f32 q0, q0, q8\n"
1191 "vmul.f32 q1, q1, q8\n"
1192 "vmul.f32 q2, q2, q8\n"
1193 "vmul.f32 q3, q3, q8\n"
1194 "vcvt.s32.f32 q0, q0\n"
1195 "vcvt.s32.f32 q1, q1\n"
1196 "vcvt.s32.f32 q2, q2\n"
1197 "vcvt.s32.f32 q3, q3\n"
1198 "vqmovn.s32 d0, q0\n"
1199 "vqmovn.s32 d1, q1\n"
1200 "vqmovn.s32 d4, q2\n"
1201 "vqmovn.s32 d5, q3\n"
1202 "vqmovun.s16 d0, q0\n"
1203 "vqmovun.s16 d1, q2\n"
1204
1205 "vst1.32 {d0, d1}, [%[output]]!\n"
1206 "pld [%[output]]\n"
1207
1208 "bne 1b\n"
1209 "2:"
1210
1211 // Handle leftovers.
1212
1213 // Requantize::Transform
1214 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1215 "vld1.32 {d4}, [%[input]]!\n"
1216 "vld1.32 {d5[0]}, [%[input]]!\n"
1217 "pld [%[input], #64]\n"
1218 "vcvt.f32.s32 q0, q0\n"
1219 "vcvt.f32.s32 q1, q1\n"
1220 "vcvt.f32.s32 q2, q2\n"
1221 "vsub.f32 q0, q0, q6\n"
1222 "vsub.f32 q1, q1, q6\n"
1223 "vsub.f32 q2, q2, q6\n"
1224 "vmul.f32 q0, q0, q7\n"
1225 "vmul.f32 q1, q1, q7\n"
1226 "vmul.f32 q2, q2, q7\n"
1227 "vadd.f32 q0, q0, q4\n"
1228 "vadd.f32 q1, q1, q4\n"
1229 "vadd.f32 q2, q2, q4\n"
1230 "vmul.f32 q0, q0, q8\n"
1231 "vmul.f32 q1, q1, q8\n"
1232 "vmul.f32 q2, q2, q8\n"
1233 "vcvt.s32.f32 q0, q0\n"
1234 "vcvt.s32.f32 q1, q1\n"
1235 "vcvt.s32.f32 q2, q2\n"
1236 "vqmovn.s32 d0, q0\n"
1237 "vqmovn.s32 d1, q1\n"
1238 "vqmovn.s32 d4, q2\n"
1239 "vqmovun.s16 d0, q0\n"
1240 "vqmovun.s16 d1, q2\n"
1241
1242 "vst1.32 {d0}, [%[output]]!\n"
1243 "vst1.16 {d1[0]}, [%[output]]!\n"
1244 "vst1.8 {d1[2]}, [%[output]]!\n"
1245 "pld [%[output]]\n"
1246 : [count] "+r"(params_count_copy), [input] "+r"(input),
1247 [output] "+r"(output)
1248 : [input_range_min] "r"(params.input_range_min),
1249 [output_range_min] "r"(params.output_range_min),
1250 [input_range_offset] "r"(params.input_range_offset),
1251 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
1252 [input_range_scale] "r"(params.input_range_scale)
1253 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1254 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
1255 }
1256
1257 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)1258 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 12>::Transform(
1259 const int32_t* input, const Requantize& params, uint8_t* output) {
1260 #ifdef DEBUG
1261 #ifdef DEBUG_METAGEMM_VERBOSE
1262 std::cout << __FILE__ << "(" << __LINE__
1263 << ") Requantize<int32_t, uint8_t, Requantize, 16, 12>::Transform()"
1264 << std::endl
1265 << std::flush;
1266 #endif
1267 #endif
1268 int params_count_copy = params.count;
1269 asm volatile(
1270
1271 // Requantize::Prepare
1272 "vdup.32 q4, %[input_range_min]\n"
1273 "vdup.32 q5, %[output_range_min]\n"
1274 "vdup.32 q6, %[input_range_offset]\n"
1275 "vdup.32 q7, %[input_range_scale]\n"
1276 "vdup.32 q8, %[one_over_output_range_scale]\n"
1277 "vsub.f32 q4, q4, q5\n"
1278
1279 // Reduce count by leftovers.
1280 "subs %[count], %[count], #12\n"
1281 "beq 2f\n"
1282
1283 "1:"
1284 "subs %[count], %[count], #16\n"
1285
1286 // Requantize::Transform
1287 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1288 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1289 "pld [%[input], #64]\n"
1290 "vcvt.f32.s32 q0, q0\n"
1291 "vcvt.f32.s32 q1, q1\n"
1292 "vcvt.f32.s32 q2, q2\n"
1293 "vcvt.f32.s32 q3, q3\n"
1294 "vsub.f32 q0, q0, q6\n"
1295 "vsub.f32 q1, q1, q6\n"
1296 "vsub.f32 q2, q2, q6\n"
1297 "vsub.f32 q3, q3, q6\n"
1298 "vmul.f32 q0, q0, q7\n"
1299 "vmul.f32 q1, q1, q7\n"
1300 "vmul.f32 q2, q2, q7\n"
1301 "vmul.f32 q3, q3, q7\n"
1302 "vadd.f32 q0, q0, q4\n"
1303 "vadd.f32 q1, q1, q4\n"
1304 "vadd.f32 q2, q2, q4\n"
1305 "vadd.f32 q3, q3, q4\n"
1306 "vmul.f32 q0, q0, q8\n"
1307 "vmul.f32 q1, q1, q8\n"
1308 "vmul.f32 q2, q2, q8\n"
1309 "vmul.f32 q3, q3, q8\n"
1310 "vcvt.s32.f32 q0, q0\n"
1311 "vcvt.s32.f32 q1, q1\n"
1312 "vcvt.s32.f32 q2, q2\n"
1313 "vcvt.s32.f32 q3, q3\n"
1314 "vqmovn.s32 d0, q0\n"
1315 "vqmovn.s32 d1, q1\n"
1316 "vqmovn.s32 d4, q2\n"
1317 "vqmovn.s32 d5, q3\n"
1318 "vqmovun.s16 d0, q0\n"
1319 "vqmovun.s16 d1, q2\n"
1320
1321 "vst1.32 {d0, d1}, [%[output]]!\n"
1322 "pld [%[output]]\n"
1323
1324 "bne 1b\n"
1325 "2:"
1326
1327 // Handle leftovers.
1328
1329 // Requantize::Transform
1330 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1331 "vld1.32 {d4, d5}, [%[input]]!\n"
1332 "pld [%[input], #64]\n"
1333 "vcvt.f32.s32 q0, q0\n"
1334 "vcvt.f32.s32 q1, q1\n"
1335 "vcvt.f32.s32 q2, q2\n"
1336 "vsub.f32 q0, q0, q6\n"
1337 "vsub.f32 q1, q1, q6\n"
1338 "vsub.f32 q2, q2, q6\n"
1339 "vmul.f32 q0, q0, q7\n"
1340 "vmul.f32 q1, q1, q7\n"
1341 "vmul.f32 q2, q2, q7\n"
1342 "vadd.f32 q0, q0, q4\n"
1343 "vadd.f32 q1, q1, q4\n"
1344 "vadd.f32 q2, q2, q4\n"
1345 "vmul.f32 q0, q0, q8\n"
1346 "vmul.f32 q1, q1, q8\n"
1347 "vmul.f32 q2, q2, q8\n"
1348 "vcvt.s32.f32 q0, q0\n"
1349 "vcvt.s32.f32 q1, q1\n"
1350 "vcvt.s32.f32 q2, q2\n"
1351 "vqmovn.s32 d0, q0\n"
1352 "vqmovn.s32 d1, q1\n"
1353 "vqmovn.s32 d4, q2\n"
1354 "vqmovun.s16 d0, q0\n"
1355 "vqmovun.s16 d1, q2\n"
1356
1357 "vst1.32 {d0}, [%[output]]!\n"
1358 "vst1.32 {d1[0]}, [%[output]]!\n"
1359 "pld [%[output]]\n"
1360 : [count] "+r"(params_count_copy), [input] "+r"(input),
1361 [output] "+r"(output)
1362 : [input_range_min] "r"(params.input_range_min),
1363 [output_range_min] "r"(params.output_range_min),
1364 [input_range_offset] "r"(params.input_range_offset),
1365 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
1366 [input_range_scale] "r"(params.input_range_scale)
1367 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1368 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
1369 }
1370
1371 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)1372 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 13>::Transform(
1373 const int32_t* input, const Requantize& params, uint8_t* output) {
1374 #ifdef DEBUG
1375 #ifdef DEBUG_METAGEMM_VERBOSE
1376 std::cout << __FILE__ << "(" << __LINE__
1377 << ") Requantize<int32_t, uint8_t, Requantize, 16, 13>::Transform()"
1378 << std::endl
1379 << std::flush;
1380 #endif
1381 #endif
1382 int params_count_copy = params.count;
1383 asm volatile(
1384
1385 // Requantize::Prepare
1386 "vdup.32 q4, %[input_range_min]\n"
1387 "vdup.32 q5, %[output_range_min]\n"
1388 "vdup.32 q6, %[input_range_offset]\n"
1389 "vdup.32 q7, %[input_range_scale]\n"
1390 "vdup.32 q8, %[one_over_output_range_scale]\n"
1391 "vsub.f32 q4, q4, q5\n"
1392
1393 // Reduce count by leftovers.
1394 "subs %[count], %[count], #13\n"
1395 "beq 2f\n"
1396
1397 "1:"
1398 "subs %[count], %[count], #16\n"
1399
1400 // Requantize::Transform
1401 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1402 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1403 "pld [%[input], #64]\n"
1404 "vcvt.f32.s32 q0, q0\n"
1405 "vcvt.f32.s32 q1, q1\n"
1406 "vcvt.f32.s32 q2, q2\n"
1407 "vcvt.f32.s32 q3, q3\n"
1408 "vsub.f32 q0, q0, q6\n"
1409 "vsub.f32 q1, q1, q6\n"
1410 "vsub.f32 q2, q2, q6\n"
1411 "vsub.f32 q3, q3, q6\n"
1412 "vmul.f32 q0, q0, q7\n"
1413 "vmul.f32 q1, q1, q7\n"
1414 "vmul.f32 q2, q2, q7\n"
1415 "vmul.f32 q3, q3, q7\n"
1416 "vadd.f32 q0, q0, q4\n"
1417 "vadd.f32 q1, q1, q4\n"
1418 "vadd.f32 q2, q2, q4\n"
1419 "vadd.f32 q3, q3, q4\n"
1420 "vmul.f32 q0, q0, q8\n"
1421 "vmul.f32 q1, q1, q8\n"
1422 "vmul.f32 q2, q2, q8\n"
1423 "vmul.f32 q3, q3, q8\n"
1424 "vcvt.s32.f32 q0, q0\n"
1425 "vcvt.s32.f32 q1, q1\n"
1426 "vcvt.s32.f32 q2, q2\n"
1427 "vcvt.s32.f32 q3, q3\n"
1428 "vqmovn.s32 d0, q0\n"
1429 "vqmovn.s32 d1, q1\n"
1430 "vqmovn.s32 d4, q2\n"
1431 "vqmovn.s32 d5, q3\n"
1432 "vqmovun.s16 d0, q0\n"
1433 "vqmovun.s16 d1, q2\n"
1434
1435 "vst1.32 {d0, d1}, [%[output]]!\n"
1436 "pld [%[output]]\n"
1437
1438 "bne 1b\n"
1439 "2:"
1440
1441 // Handle leftovers.
1442
1443 // Requantize::Transform
1444 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1445 "vld1.32 {d4, d5}, [%[input]]!\n"
1446 "vld1.32 {d6[0]}, [%[input]]!\n"
1447 "pld [%[input], #64]\n"
1448 "vcvt.f32.s32 q0, q0\n"
1449 "vcvt.f32.s32 q1, q1\n"
1450 "vcvt.f32.s32 q2, q2\n"
1451 "vcvt.f32.s32 q3, q3\n"
1452 "vsub.f32 q0, q0, q6\n"
1453 "vsub.f32 q1, q1, q6\n"
1454 "vsub.f32 q2, q2, q6\n"
1455 "vsub.f32 q3, q3, q6\n"
1456 "vmul.f32 q0, q0, q7\n"
1457 "vmul.f32 q1, q1, q7\n"
1458 "vmul.f32 q2, q2, q7\n"
1459 "vmul.f32 q3, q3, q7\n"
1460 "vadd.f32 q0, q0, q4\n"
1461 "vadd.f32 q1, q1, q4\n"
1462 "vadd.f32 q2, q2, q4\n"
1463 "vadd.f32 q3, q3, q4\n"
1464 "vmul.f32 q0, q0, q8\n"
1465 "vmul.f32 q1, q1, q8\n"
1466 "vmul.f32 q2, q2, q8\n"
1467 "vmul.f32 q3, q3, q8\n"
1468 "vcvt.s32.f32 q0, q0\n"
1469 "vcvt.s32.f32 q1, q1\n"
1470 "vcvt.s32.f32 q2, q2\n"
1471 "vcvt.s32.f32 q3, q3\n"
1472 "vqmovn.s32 d0, q0\n"
1473 "vqmovn.s32 d1, q1\n"
1474 "vqmovn.s32 d4, q2\n"
1475 "vqmovn.s32 d5, q3\n"
1476 "vqmovun.s16 d0, q0\n"
1477 "vqmovun.s16 d1, q2\n"
1478
1479 "vst1.32 {d0}, [%[output]]!\n"
1480 "vst1.32 {d1[0]}, [%[output]]!\n"
1481 "vst1.8 {d1[4]}, [%[output]]!\n"
1482 "pld [%[output]]\n"
1483 : [count] "+r"(params_count_copy), [input] "+r"(input),
1484 [output] "+r"(output)
1485 : [input_range_min] "r"(params.input_range_min),
1486 [output_range_min] "r"(params.output_range_min),
1487 [input_range_offset] "r"(params.input_range_offset),
1488 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
1489 [input_range_scale] "r"(params.input_range_scale)
1490 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1491 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
1492 }
1493
1494 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)1495 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 14>::Transform(
1496 const int32_t* input, const Requantize& params, uint8_t* output) {
1497 #ifdef DEBUG
1498 #ifdef DEBUG_METAGEMM_VERBOSE
1499 std::cout << __FILE__ << "(" << __LINE__
1500 << ") Requantize<int32_t, uint8_t, Requantize, 16, 14>::Transform()"
1501 << std::endl
1502 << std::flush;
1503 #endif
1504 #endif
1505 int params_count_copy = params.count;
1506 asm volatile(
1507
1508 // Requantize::Prepare
1509 "vdup.32 q4, %[input_range_min]\n"
1510 "vdup.32 q5, %[output_range_min]\n"
1511 "vdup.32 q6, %[input_range_offset]\n"
1512 "vdup.32 q7, %[input_range_scale]\n"
1513 "vdup.32 q8, %[one_over_output_range_scale]\n"
1514 "vsub.f32 q4, q4, q5\n"
1515
1516 // Reduce count by leftovers.
1517 "subs %[count], %[count], #14\n"
1518 "beq 2f\n"
1519
1520 "1:"
1521 "subs %[count], %[count], #16\n"
1522
1523 // Requantize::Transform
1524 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1525 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1526 "pld [%[input], #64]\n"
1527 "vcvt.f32.s32 q0, q0\n"
1528 "vcvt.f32.s32 q1, q1\n"
1529 "vcvt.f32.s32 q2, q2\n"
1530 "vcvt.f32.s32 q3, q3\n"
1531 "vsub.f32 q0, q0, q6\n"
1532 "vsub.f32 q1, q1, q6\n"
1533 "vsub.f32 q2, q2, q6\n"
1534 "vsub.f32 q3, q3, q6\n"
1535 "vmul.f32 q0, q0, q7\n"
1536 "vmul.f32 q1, q1, q7\n"
1537 "vmul.f32 q2, q2, q7\n"
1538 "vmul.f32 q3, q3, q7\n"
1539 "vadd.f32 q0, q0, q4\n"
1540 "vadd.f32 q1, q1, q4\n"
1541 "vadd.f32 q2, q2, q4\n"
1542 "vadd.f32 q3, q3, q4\n"
1543 "vmul.f32 q0, q0, q8\n"
1544 "vmul.f32 q1, q1, q8\n"
1545 "vmul.f32 q2, q2, q8\n"
1546 "vmul.f32 q3, q3, q8\n"
1547 "vcvt.s32.f32 q0, q0\n"
1548 "vcvt.s32.f32 q1, q1\n"
1549 "vcvt.s32.f32 q2, q2\n"
1550 "vcvt.s32.f32 q3, q3\n"
1551 "vqmovn.s32 d0, q0\n"
1552 "vqmovn.s32 d1, q1\n"
1553 "vqmovn.s32 d4, q2\n"
1554 "vqmovn.s32 d5, q3\n"
1555 "vqmovun.s16 d0, q0\n"
1556 "vqmovun.s16 d1, q2\n"
1557
1558 "vst1.32 {d0, d1}, [%[output]]!\n"
1559 "pld [%[output]]\n"
1560
1561 "bne 1b\n"
1562 "2:"
1563
1564 // Handle leftovers.
1565
1566 // Requantize::Transform
1567 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1568 "vld1.32 {d4, d5, d6}, [%[input]]!\n"
1569 "pld [%[input], #64]\n"
1570 "vcvt.f32.s32 q0, q0\n"
1571 "vcvt.f32.s32 q1, q1\n"
1572 "vcvt.f32.s32 q2, q2\n"
1573 "vcvt.f32.s32 q3, q3\n"
1574 "vsub.f32 q0, q0, q6\n"
1575 "vsub.f32 q1, q1, q6\n"
1576 "vsub.f32 q2, q2, q6\n"
1577 "vsub.f32 q3, q3, q6\n"
1578 "vmul.f32 q0, q0, q7\n"
1579 "vmul.f32 q1, q1, q7\n"
1580 "vmul.f32 q2, q2, q7\n"
1581 "vmul.f32 q3, q3, q7\n"
1582 "vadd.f32 q0, q0, q4\n"
1583 "vadd.f32 q1, q1, q4\n"
1584 "vadd.f32 q2, q2, q4\n"
1585 "vadd.f32 q3, q3, q4\n"
1586 "vmul.f32 q0, q0, q8\n"
1587 "vmul.f32 q1, q1, q8\n"
1588 "vmul.f32 q2, q2, q8\n"
1589 "vmul.f32 q3, q3, q8\n"
1590 "vcvt.s32.f32 q0, q0\n"
1591 "vcvt.s32.f32 q1, q1\n"
1592 "vcvt.s32.f32 q2, q2\n"
1593 "vcvt.s32.f32 q3, q3\n"
1594 "vqmovn.s32 d0, q0\n"
1595 "vqmovn.s32 d1, q1\n"
1596 "vqmovn.s32 d4, q2\n"
1597 "vqmovn.s32 d5, q3\n"
1598 "vqmovun.s16 d0, q0\n"
1599 "vqmovun.s16 d1, q2\n"
1600
1601 "vst1.32 {d0}, [%[output]]!\n"
1602 "vst1.32 {d1[0]}, [%[output]]!\n"
1603 "vst1.16 {d1[2]}, [%[output]]!\n"
1604 "pld [%[output]]\n"
1605 : [count] "+r"(params_count_copy), [input] "+r"(input),
1606 [output] "+r"(output)
1607 : [input_range_min] "r"(params.input_range_min),
1608 [output_range_min] "r"(params.output_range_min),
1609 [input_range_offset] "r"(params.input_range_offset),
1610 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
1611 [input_range_scale] "r"(params.input_range_scale)
1612 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1613 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
1614 }
1615
1616 template <>
Transform(const int32_t * input,const Requantize & params,uint8_t * output)1617 inline void Transform1DKernel<int32_t, uint8_t, Requantize, 16, 15>::Transform(
1618 const int32_t* input, const Requantize& params, uint8_t* output) {
1619 #ifdef DEBUG
1620 #ifdef DEBUG_METAGEMM_VERBOSE
1621 std::cout << __FILE__ << "(" << __LINE__
1622 << ") Requantize<int32_t, uint8_t, Requantize, 16, 15>::Transform()"
1623 << std::endl
1624 << std::flush;
1625 #endif
1626 #endif
1627 int params_count_copy = params.count;
1628 asm volatile(
1629
1630 // Requantize::Prepare
1631 "vdup.32 q4, %[input_range_min]\n"
1632 "vdup.32 q5, %[output_range_min]\n"
1633 "vdup.32 q6, %[input_range_offset]\n"
1634 "vdup.32 q7, %[input_range_scale]\n"
1635 "vdup.32 q8, %[one_over_output_range_scale]\n"
1636 "vsub.f32 q4, q4, q5\n"
1637
1638 // Reduce count by leftovers.
1639 "subs %[count], %[count], #15\n"
1640 "beq 2f\n"
1641
1642 "1:"
1643 "subs %[count], %[count], #16\n"
1644
1645 // Requantize::Transform
1646 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1647 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1648 "pld [%[input], #64]\n"
1649 "vcvt.f32.s32 q0, q0\n"
1650 "vcvt.f32.s32 q1, q1\n"
1651 "vcvt.f32.s32 q2, q2\n"
1652 "vcvt.f32.s32 q3, q3\n"
1653 "vsub.f32 q0, q0, q6\n"
1654 "vsub.f32 q1, q1, q6\n"
1655 "vsub.f32 q2, q2, q6\n"
1656 "vsub.f32 q3, q3, q6\n"
1657 "vmul.f32 q0, q0, q7\n"
1658 "vmul.f32 q1, q1, q7\n"
1659 "vmul.f32 q2, q2, q7\n"
1660 "vmul.f32 q3, q3, q7\n"
1661 "vadd.f32 q0, q0, q4\n"
1662 "vadd.f32 q1, q1, q4\n"
1663 "vadd.f32 q2, q2, q4\n"
1664 "vadd.f32 q3, q3, q4\n"
1665 "vmul.f32 q0, q0, q8\n"
1666 "vmul.f32 q1, q1, q8\n"
1667 "vmul.f32 q2, q2, q8\n"
1668 "vmul.f32 q3, q3, q8\n"
1669 "vcvt.s32.f32 q0, q0\n"
1670 "vcvt.s32.f32 q1, q1\n"
1671 "vcvt.s32.f32 q2, q2\n"
1672 "vcvt.s32.f32 q3, q3\n"
1673 "vqmovn.s32 d0, q0\n"
1674 "vqmovn.s32 d1, q1\n"
1675 "vqmovn.s32 d4, q2\n"
1676 "vqmovn.s32 d5, q3\n"
1677 "vqmovun.s16 d0, q0\n"
1678 "vqmovun.s16 d1, q2\n"
1679
1680 "vst1.32 {d0, d1}, [%[output]]!\n"
1681 "pld [%[output]]\n"
1682
1683 "bne 1b\n"
1684 "2:"
1685
1686 // Handle leftovers.
1687
1688 // Requantize::Transform
1689 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1690 "vld1.32 {d4, d5, d6}, [%[input]]!\n"
1691 "vld1.32 {d7[0]}, [%[input]]!\n"
1692 "pld [%[input], #64]\n"
1693 "vcvt.f32.s32 q0, q0\n"
1694 "vcvt.f32.s32 q1, q1\n"
1695 "vcvt.f32.s32 q2, q2\n"
1696 "vcvt.f32.s32 q3, q3\n"
1697 "vsub.f32 q0, q0, q6\n"
1698 "vsub.f32 q1, q1, q6\n"
1699 "vsub.f32 q2, q2, q6\n"
1700 "vsub.f32 q3, q3, q6\n"
1701 "vmul.f32 q0, q0, q7\n"
1702 "vmul.f32 q1, q1, q7\n"
1703 "vmul.f32 q2, q2, q7\n"
1704 "vmul.f32 q3, q3, q7\n"
1705 "vadd.f32 q0, q0, q4\n"
1706 "vadd.f32 q1, q1, q4\n"
1707 "vadd.f32 q2, q2, q4\n"
1708 "vadd.f32 q3, q3, q4\n"
1709 "vmul.f32 q0, q0, q8\n"
1710 "vmul.f32 q1, q1, q8\n"
1711 "vmul.f32 q2, q2, q8\n"
1712 "vmul.f32 q3, q3, q8\n"
1713 "vcvt.s32.f32 q0, q0\n"
1714 "vcvt.s32.f32 q1, q1\n"
1715 "vcvt.s32.f32 q2, q2\n"
1716 "vcvt.s32.f32 q3, q3\n"
1717 "vqmovn.s32 d0, q0\n"
1718 "vqmovn.s32 d1, q1\n"
1719 "vqmovn.s32 d4, q2\n"
1720 "vqmovn.s32 d5, q3\n"
1721 "vqmovun.s16 d0, q0\n"
1722 "vqmovun.s16 d1, q2\n"
1723
1724 "vst1.32 {d0}, [%[output]]!\n"
1725 "vst1.32 {d1[0]}, [%[output]]!\n"
1726 "vst1.16 {d1[2]}, [%[output]]!\n"
1727 "vst1.8 {d1[6]}, [%[output]]!\n"
1728 "pld [%[output]]\n"
1729 : [count] "+r"(params_count_copy), [input] "+r"(input),
1730 [output] "+r"(output)
1731 : [input_range_min] "r"(params.input_range_min),
1732 [output_range_min] "r"(params.output_range_min),
1733 [input_range_offset] "r"(params.input_range_offset),
1734 [one_over_output_range_scale] "r"(params.one_over_output_range_scale),
1735 [input_range_scale] "r"(params.input_range_scale)
1736 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1737 "d11", "d12", "d13", "d14", "d15", "d16", "d17", "cc", "memory");
1738 }
1739
1740 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)1741 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 0>::Transform(
1742 const float* input, const Quantize& params, uint8_t* output) {
1743 #ifdef DEBUG
1744 #ifdef DEBUG_METAGEMM_VERBOSE
1745 std::cout << __FILE__ << "(" << __LINE__
1746 << ") Quantize<float, uint8_t, Quantize, 16, 0>::Transform()"
1747 << std::endl
1748 << std::flush;
1749 #endif
1750 #endif
1751 int params_count_copy = params.count;
1752 asm volatile(
1753
1754 // Quantize::Prepare
1755 "vdup.32 q4, %[range_min]\n"
1756 "vdup.32 q5, %[range_offset]\n"
1757 "vdup.32 q6, %[range_scale]\n"
1758
1759 "1:"
1760 "subs %[count], %[count], #16\n"
1761
1762 // Quantize::Transform
1763 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1764 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1765 "pld [%[input], #64]\n"
1766 "vsub.f32 q0, q0, q4\n"
1767 "vsub.f32 q1, q1, q4\n"
1768 "vsub.f32 q2, q2, q4\n"
1769 "vsub.f32 q3, q3, q4\n"
1770 "vmul.f32 q0, q0, q6\n"
1771 "vmul.f32 q1, q1, q6\n"
1772 "vmul.f32 q2, q2, q6\n"
1773 "vmul.f32 q3, q3, q6\n"
1774 "vadd.f32 q0, q0, q5\n"
1775 "vadd.f32 q1, q1, q5\n"
1776 "vadd.f32 q2, q2, q5\n"
1777 "vadd.f32 q3, q3, q5\n"
1778 "vcvt.s32.f32 q0, q0\n"
1779 "vcvt.s32.f32 q1, q1\n"
1780 "vcvt.s32.f32 q2, q2\n"
1781 "vcvt.s32.f32 q3, q3\n"
1782 "vqmovn.s32 d0, q0\n"
1783 "vqmovn.s32 d1, q1\n"
1784 "vqmovn.s32 d4, q2\n"
1785 "vqmovn.s32 d5, q3\n"
1786 "vqmovun.s16 d0, q0\n"
1787 "vqmovun.s16 d1, q2\n"
1788
1789 "vst1.32 {d0, d1}, [%[output]]!\n"
1790 "pld [%[output]]\n"
1791
1792 "bne 1b\n"
1793 : [count] "+r"(params_count_copy), [input] "+r"(input),
1794 [output] "+r"(output)
1795 : [range_offset] "r"(params.range_offset),
1796 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
1797 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1798 "d11", "d12", "d13", "cc", "memory");
1799 }
1800
1801 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)1802 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 1>::Transform(
1803 const float* input, const Quantize& params, uint8_t* output) {
1804 #ifdef DEBUG
1805 #ifdef DEBUG_METAGEMM_VERBOSE
1806 std::cout << __FILE__ << "(" << __LINE__
1807 << ") Quantize<float, uint8_t, Quantize, 16, 1>::Transform()"
1808 << std::endl
1809 << std::flush;
1810 #endif
1811 #endif
1812 int params_count_copy = params.count;
1813 asm volatile(
1814
1815 // Quantize::Prepare
1816 "vdup.32 q4, %[range_min]\n"
1817 "vdup.32 q5, %[range_offset]\n"
1818 "vdup.32 q6, %[range_scale]\n"
1819
1820 // Reduce count by leftovers.
1821 "subs %[count], %[count], #1\n"
1822 "beq 2f\n"
1823
1824 "1:"
1825 "subs %[count], %[count], #16\n"
1826
1827 // Quantize::Transform
1828 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1829 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1830 "pld [%[input], #64]\n"
1831 "vsub.f32 q0, q0, q4\n"
1832 "vsub.f32 q1, q1, q4\n"
1833 "vsub.f32 q2, q2, q4\n"
1834 "vsub.f32 q3, q3, q4\n"
1835 "vmul.f32 q0, q0, q6\n"
1836 "vmul.f32 q1, q1, q6\n"
1837 "vmul.f32 q2, q2, q6\n"
1838 "vmul.f32 q3, q3, q6\n"
1839 "vadd.f32 q0, q0, q5\n"
1840 "vadd.f32 q1, q1, q5\n"
1841 "vadd.f32 q2, q2, q5\n"
1842 "vadd.f32 q3, q3, q5\n"
1843 "vcvt.s32.f32 q0, q0\n"
1844 "vcvt.s32.f32 q1, q1\n"
1845 "vcvt.s32.f32 q2, q2\n"
1846 "vcvt.s32.f32 q3, q3\n"
1847 "vqmovn.s32 d0, q0\n"
1848 "vqmovn.s32 d1, q1\n"
1849 "vqmovn.s32 d4, q2\n"
1850 "vqmovn.s32 d5, q3\n"
1851 "vqmovun.s16 d0, q0\n"
1852 "vqmovun.s16 d1, q2\n"
1853
1854 "vst1.32 {d0, d1}, [%[output]]!\n"
1855 "pld [%[output]]\n"
1856
1857 "bne 1b\n"
1858 "2:"
1859
1860 // Handle leftovers.
1861
1862 // Quantize::Transform
1863 "vld1.32 {d0[0]}, [%[input]]!\n"
1864 "pld [%[input], #64]\n"
1865 "vsub.f32 q0, q0, q4\n"
1866 "vmul.f32 q0, q0, q6\n"
1867 "vadd.f32 q0, q0, q5\n"
1868 "vcvt.s32.f32 q0, q0\n"
1869 "vqmovn.s32 d0, q0\n"
1870 "vqmovun.s16 d0, q0\n"
1871
1872 "vst1.8 {d0[0]}, [%[output]]!\n"
1873 "pld [%[output]]\n"
1874 : [count] "+r"(params_count_copy), [input] "+r"(input),
1875 [output] "+r"(output)
1876 : [range_offset] "r"(params.range_offset),
1877 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
1878 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1879 "d11", "d12", "d13", "cc", "memory");
1880 }
1881
1882 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)1883 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 2>::Transform(
1884 const float* input, const Quantize& params, uint8_t* output) {
1885 #ifdef DEBUG
1886 #ifdef DEBUG_METAGEMM_VERBOSE
1887 std::cout << __FILE__ << "(" << __LINE__
1888 << ") Quantize<float, uint8_t, Quantize, 16, 2>::Transform()"
1889 << std::endl
1890 << std::flush;
1891 #endif
1892 #endif
1893 int params_count_copy = params.count;
1894 asm volatile(
1895
1896 // Quantize::Prepare
1897 "vdup.32 q4, %[range_min]\n"
1898 "vdup.32 q5, %[range_offset]\n"
1899 "vdup.32 q6, %[range_scale]\n"
1900
1901 // Reduce count by leftovers.
1902 "subs %[count], %[count], #2\n"
1903 "beq 2f\n"
1904
1905 "1:"
1906 "subs %[count], %[count], #16\n"
1907
1908 // Quantize::Transform
1909 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1910 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1911 "pld [%[input], #64]\n"
1912 "vsub.f32 q0, q0, q4\n"
1913 "vsub.f32 q1, q1, q4\n"
1914 "vsub.f32 q2, q2, q4\n"
1915 "vsub.f32 q3, q3, q4\n"
1916 "vmul.f32 q0, q0, q6\n"
1917 "vmul.f32 q1, q1, q6\n"
1918 "vmul.f32 q2, q2, q6\n"
1919 "vmul.f32 q3, q3, q6\n"
1920 "vadd.f32 q0, q0, q5\n"
1921 "vadd.f32 q1, q1, q5\n"
1922 "vadd.f32 q2, q2, q5\n"
1923 "vadd.f32 q3, q3, q5\n"
1924 "vcvt.s32.f32 q0, q0\n"
1925 "vcvt.s32.f32 q1, q1\n"
1926 "vcvt.s32.f32 q2, q2\n"
1927 "vcvt.s32.f32 q3, q3\n"
1928 "vqmovn.s32 d0, q0\n"
1929 "vqmovn.s32 d1, q1\n"
1930 "vqmovn.s32 d4, q2\n"
1931 "vqmovn.s32 d5, q3\n"
1932 "vqmovun.s16 d0, q0\n"
1933 "vqmovun.s16 d1, q2\n"
1934
1935 "vst1.32 {d0, d1}, [%[output]]!\n"
1936 "pld [%[output]]\n"
1937
1938 "bne 1b\n"
1939 "2:"
1940
1941 // Handle leftovers.
1942
1943 // Quantize::Transform
1944 "vld1.32 {d0}, [%[input]]!\n"
1945 "pld [%[input], #64]\n"
1946 "vsub.f32 q0, q0, q4\n"
1947 "vmul.f32 q0, q0, q6\n"
1948 "vadd.f32 q0, q0, q5\n"
1949 "vcvt.s32.f32 q0, q0\n"
1950 "vqmovn.s32 d0, q0\n"
1951 "vqmovun.s16 d0, q0\n"
1952
1953 "vst1.16 {d0[0]}, [%[output]]!\n"
1954 "pld [%[output]]\n"
1955 : [count] "+r"(params_count_copy), [input] "+r"(input),
1956 [output] "+r"(output)
1957 : [range_offset] "r"(params.range_offset),
1958 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
1959 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
1960 "d11", "d12", "d13", "cc", "memory");
1961 }
1962
1963 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)1964 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 3>::Transform(
1965 const float* input, const Quantize& params, uint8_t* output) {
1966 #ifdef DEBUG
1967 #ifdef DEBUG_METAGEMM_VERBOSE
1968 std::cout << __FILE__ << "(" << __LINE__
1969 << ") Quantize<float, uint8_t, Quantize, 16, 3>::Transform()"
1970 << std::endl
1971 << std::flush;
1972 #endif
1973 #endif
1974 int params_count_copy = params.count;
1975 asm volatile(
1976
1977 // Quantize::Prepare
1978 "vdup.32 q4, %[range_min]\n"
1979 "vdup.32 q5, %[range_offset]\n"
1980 "vdup.32 q6, %[range_scale]\n"
1981
1982 // Reduce count by leftovers.
1983 "subs %[count], %[count], #3\n"
1984 "beq 2f\n"
1985
1986 "1:"
1987 "subs %[count], %[count], #16\n"
1988
1989 // Quantize::Transform
1990 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
1991 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
1992 "pld [%[input], #64]\n"
1993 "vsub.f32 q0, q0, q4\n"
1994 "vsub.f32 q1, q1, q4\n"
1995 "vsub.f32 q2, q2, q4\n"
1996 "vsub.f32 q3, q3, q4\n"
1997 "vmul.f32 q0, q0, q6\n"
1998 "vmul.f32 q1, q1, q6\n"
1999 "vmul.f32 q2, q2, q6\n"
2000 "vmul.f32 q3, q3, q6\n"
2001 "vadd.f32 q0, q0, q5\n"
2002 "vadd.f32 q1, q1, q5\n"
2003 "vadd.f32 q2, q2, q5\n"
2004 "vadd.f32 q3, q3, q5\n"
2005 "vcvt.s32.f32 q0, q0\n"
2006 "vcvt.s32.f32 q1, q1\n"
2007 "vcvt.s32.f32 q2, q2\n"
2008 "vcvt.s32.f32 q3, q3\n"
2009 "vqmovn.s32 d0, q0\n"
2010 "vqmovn.s32 d1, q1\n"
2011 "vqmovn.s32 d4, q2\n"
2012 "vqmovn.s32 d5, q3\n"
2013 "vqmovun.s16 d0, q0\n"
2014 "vqmovun.s16 d1, q2\n"
2015
2016 "vst1.32 {d0, d1}, [%[output]]!\n"
2017 "pld [%[output]]\n"
2018
2019 "bne 1b\n"
2020 "2:"
2021
2022 // Handle leftovers.
2023
2024 // Quantize::Transform
2025 "vld1.32 {d0}, [%[input]]!\n"
2026 "vld1.32 {d1[0]}, [%[input]]!\n"
2027 "pld [%[input], #64]\n"
2028 "vsub.f32 q0, q0, q4\n"
2029 "vmul.f32 q0, q0, q6\n"
2030 "vadd.f32 q0, q0, q5\n"
2031 "vcvt.s32.f32 q0, q0\n"
2032 "vqmovn.s32 d0, q0\n"
2033 "vqmovun.s16 d0, q0\n"
2034
2035 "vst1.16 {d0[0]}, [%[output]]!\n"
2036 "vst1.8 {d0[2]}, [%[output]]!\n"
2037 "pld [%[output]]\n"
2038 : [count] "+r"(params_count_copy), [input] "+r"(input),
2039 [output] "+r"(output)
2040 : [range_offset] "r"(params.range_offset),
2041 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2042 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2043 "d11", "d12", "d13", "cc", "memory");
2044 }
2045
2046 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2047 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 4>::Transform(
2048 const float* input, const Quantize& params, uint8_t* output) {
2049 #ifdef DEBUG
2050 #ifdef DEBUG_METAGEMM_VERBOSE
2051 std::cout << __FILE__ << "(" << __LINE__
2052 << ") Quantize<float, uint8_t, Quantize, 16, 4>::Transform()"
2053 << std::endl
2054 << std::flush;
2055 #endif
2056 #endif
2057 int params_count_copy = params.count;
2058 asm volatile(
2059
2060 // Quantize::Prepare
2061 "vdup.32 q4, %[range_min]\n"
2062 "vdup.32 q5, %[range_offset]\n"
2063 "vdup.32 q6, %[range_scale]\n"
2064
2065 // Reduce count by leftovers.
2066 "subs %[count], %[count], #4\n"
2067 "beq 2f\n"
2068
2069 "1:"
2070 "subs %[count], %[count], #16\n"
2071
2072 // Quantize::Transform
2073 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2074 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2075 "pld [%[input], #64]\n"
2076 "vsub.f32 q0, q0, q4\n"
2077 "vsub.f32 q1, q1, q4\n"
2078 "vsub.f32 q2, q2, q4\n"
2079 "vsub.f32 q3, q3, q4\n"
2080 "vmul.f32 q0, q0, q6\n"
2081 "vmul.f32 q1, q1, q6\n"
2082 "vmul.f32 q2, q2, q6\n"
2083 "vmul.f32 q3, q3, q6\n"
2084 "vadd.f32 q0, q0, q5\n"
2085 "vadd.f32 q1, q1, q5\n"
2086 "vadd.f32 q2, q2, q5\n"
2087 "vadd.f32 q3, q3, q5\n"
2088 "vcvt.s32.f32 q0, q0\n"
2089 "vcvt.s32.f32 q1, q1\n"
2090 "vcvt.s32.f32 q2, q2\n"
2091 "vcvt.s32.f32 q3, q3\n"
2092 "vqmovn.s32 d0, q0\n"
2093 "vqmovn.s32 d1, q1\n"
2094 "vqmovn.s32 d4, q2\n"
2095 "vqmovn.s32 d5, q3\n"
2096 "vqmovun.s16 d0, q0\n"
2097 "vqmovun.s16 d1, q2\n"
2098
2099 "vst1.32 {d0, d1}, [%[output]]!\n"
2100 "pld [%[output]]\n"
2101
2102 "bne 1b\n"
2103 "2:"
2104
2105 // Handle leftovers.
2106
2107 // Quantize::Transform
2108 "vld1.32 {d0, d1}, [%[input]]!\n"
2109 "pld [%[input], #64]\n"
2110 "vsub.f32 q0, q0, q4\n"
2111 "vmul.f32 q0, q0, q6\n"
2112 "vadd.f32 q0, q0, q5\n"
2113 "vcvt.s32.f32 q0, q0\n"
2114 "vqmovn.s32 d0, q0\n"
2115 "vqmovun.s16 d0, q0\n"
2116
2117 "vst1.32 {d0[0]}, [%[output]]!\n"
2118 "pld [%[output]]\n"
2119 : [count] "+r"(params_count_copy), [input] "+r"(input),
2120 [output] "+r"(output)
2121 : [range_offset] "r"(params.range_offset),
2122 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2123 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2124 "d11", "d12", "d13", "cc", "memory");
2125 }
2126
2127 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2128 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 5>::Transform(
2129 const float* input, const Quantize& params, uint8_t* output) {
2130 #ifdef DEBUG
2131 #ifdef DEBUG_METAGEMM_VERBOSE
2132 std::cout << __FILE__ << "(" << __LINE__
2133 << ") Quantize<float, uint8_t, Quantize, 16, 5>::Transform()"
2134 << std::endl
2135 << std::flush;
2136 #endif
2137 #endif
2138 int params_count_copy = params.count;
2139 asm volatile(
2140
2141 // Quantize::Prepare
2142 "vdup.32 q4, %[range_min]\n"
2143 "vdup.32 q5, %[range_offset]\n"
2144 "vdup.32 q6, %[range_scale]\n"
2145
2146 // Reduce count by leftovers.
2147 "subs %[count], %[count], #5\n"
2148 "beq 2f\n"
2149
2150 "1:"
2151 "subs %[count], %[count], #16\n"
2152
2153 // Quantize::Transform
2154 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2155 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2156 "pld [%[input], #64]\n"
2157 "vsub.f32 q0, q0, q4\n"
2158 "vsub.f32 q1, q1, q4\n"
2159 "vsub.f32 q2, q2, q4\n"
2160 "vsub.f32 q3, q3, q4\n"
2161 "vmul.f32 q0, q0, q6\n"
2162 "vmul.f32 q1, q1, q6\n"
2163 "vmul.f32 q2, q2, q6\n"
2164 "vmul.f32 q3, q3, q6\n"
2165 "vadd.f32 q0, q0, q5\n"
2166 "vadd.f32 q1, q1, q5\n"
2167 "vadd.f32 q2, q2, q5\n"
2168 "vadd.f32 q3, q3, q5\n"
2169 "vcvt.s32.f32 q0, q0\n"
2170 "vcvt.s32.f32 q1, q1\n"
2171 "vcvt.s32.f32 q2, q2\n"
2172 "vcvt.s32.f32 q3, q3\n"
2173 "vqmovn.s32 d0, q0\n"
2174 "vqmovn.s32 d1, q1\n"
2175 "vqmovn.s32 d4, q2\n"
2176 "vqmovn.s32 d5, q3\n"
2177 "vqmovun.s16 d0, q0\n"
2178 "vqmovun.s16 d1, q2\n"
2179
2180 "vst1.32 {d0, d1}, [%[output]]!\n"
2181 "pld [%[output]]\n"
2182
2183 "bne 1b\n"
2184 "2:"
2185
2186 // Handle leftovers.
2187
2188 // Quantize::Transform
2189 "vld1.32 {d0, d1}, [%[input]]!\n"
2190 "vld1.32 {d2[0]}, [%[input]]!\n"
2191 "pld [%[input], #64]\n"
2192 "vsub.f32 q0, q0, q4\n"
2193 "vsub.f32 q1, q1, q4\n"
2194 "vmul.f32 q0, q0, q6\n"
2195 "vmul.f32 q1, q1, q6\n"
2196 "vadd.f32 q0, q0, q5\n"
2197 "vadd.f32 q1, q1, q5\n"
2198 "vcvt.s32.f32 q0, q0\n"
2199 "vcvt.s32.f32 q1, q1\n"
2200 "vqmovn.s32 d0, q0\n"
2201 "vqmovn.s32 d1, q1\n"
2202 "vqmovun.s16 d0, q0\n"
2203
2204 "vst1.32 {d0[0]}, [%[output]]!\n"
2205 "vst1.8 {d0[4]}, [%[output]]!\n"
2206 "pld [%[output]]\n"
2207 : [count] "+r"(params_count_copy), [input] "+r"(input),
2208 [output] "+r"(output)
2209 : [range_offset] "r"(params.range_offset),
2210 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2211 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2212 "d11", "d12", "d13", "cc", "memory");
2213 }
2214
2215 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2216 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 6>::Transform(
2217 const float* input, const Quantize& params, uint8_t* output) {
2218 #ifdef DEBUG
2219 #ifdef DEBUG_METAGEMM_VERBOSE
2220 std::cout << __FILE__ << "(" << __LINE__
2221 << ") Quantize<float, uint8_t, Quantize, 16, 6>::Transform()"
2222 << std::endl
2223 << std::flush;
2224 #endif
2225 #endif
2226 int params_count_copy = params.count;
2227 asm volatile(
2228
2229 // Quantize::Prepare
2230 "vdup.32 q4, %[range_min]\n"
2231 "vdup.32 q5, %[range_offset]\n"
2232 "vdup.32 q6, %[range_scale]\n"
2233
2234 // Reduce count by leftovers.
2235 "subs %[count], %[count], #6\n"
2236 "beq 2f\n"
2237
2238 "1:"
2239 "subs %[count], %[count], #16\n"
2240
2241 // Quantize::Transform
2242 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2243 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2244 "pld [%[input], #64]\n"
2245 "vsub.f32 q0, q0, q4\n"
2246 "vsub.f32 q1, q1, q4\n"
2247 "vsub.f32 q2, q2, q4\n"
2248 "vsub.f32 q3, q3, q4\n"
2249 "vmul.f32 q0, q0, q6\n"
2250 "vmul.f32 q1, q1, q6\n"
2251 "vmul.f32 q2, q2, q6\n"
2252 "vmul.f32 q3, q3, q6\n"
2253 "vadd.f32 q0, q0, q5\n"
2254 "vadd.f32 q1, q1, q5\n"
2255 "vadd.f32 q2, q2, q5\n"
2256 "vadd.f32 q3, q3, q5\n"
2257 "vcvt.s32.f32 q0, q0\n"
2258 "vcvt.s32.f32 q1, q1\n"
2259 "vcvt.s32.f32 q2, q2\n"
2260 "vcvt.s32.f32 q3, q3\n"
2261 "vqmovn.s32 d0, q0\n"
2262 "vqmovn.s32 d1, q1\n"
2263 "vqmovn.s32 d4, q2\n"
2264 "vqmovn.s32 d5, q3\n"
2265 "vqmovun.s16 d0, q0\n"
2266 "vqmovun.s16 d1, q2\n"
2267
2268 "vst1.32 {d0, d1}, [%[output]]!\n"
2269 "pld [%[output]]\n"
2270
2271 "bne 1b\n"
2272 "2:"
2273
2274 // Handle leftovers.
2275
2276 // Quantize::Transform
2277 "vld1.32 {d0, d1, d2}, [%[input]]!\n"
2278 "pld [%[input], #64]\n"
2279 "vsub.f32 q0, q0, q4\n"
2280 "vsub.f32 q1, q1, q4\n"
2281 "vmul.f32 q0, q0, q6\n"
2282 "vmul.f32 q1, q1, q6\n"
2283 "vadd.f32 q0, q0, q5\n"
2284 "vadd.f32 q1, q1, q5\n"
2285 "vcvt.s32.f32 q0, q0\n"
2286 "vcvt.s32.f32 q1, q1\n"
2287 "vqmovn.s32 d0, q0\n"
2288 "vqmovn.s32 d1, q1\n"
2289 "vqmovun.s16 d0, q0\n"
2290
2291 "vst1.32 {d0[0]}, [%[output]]!\n"
2292 "vst1.16 {d0[2]}, [%[output]]!\n"
2293 "pld [%[output]]\n"
2294 : [count] "+r"(params_count_copy), [input] "+r"(input),
2295 [output] "+r"(output)
2296 : [range_offset] "r"(params.range_offset),
2297 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2298 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2299 "d11", "d12", "d13", "cc", "memory");
2300 }
2301
2302 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2303 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 7>::Transform(
2304 const float* input, const Quantize& params, uint8_t* output) {
2305 #ifdef DEBUG
2306 #ifdef DEBUG_METAGEMM_VERBOSE
2307 std::cout << __FILE__ << "(" << __LINE__
2308 << ") Quantize<float, uint8_t, Quantize, 16, 7>::Transform()"
2309 << std::endl
2310 << std::flush;
2311 #endif
2312 #endif
2313 int params_count_copy = params.count;
2314 asm volatile(
2315
2316 // Quantize::Prepare
2317 "vdup.32 q4, %[range_min]\n"
2318 "vdup.32 q5, %[range_offset]\n"
2319 "vdup.32 q6, %[range_scale]\n"
2320
2321 // Reduce count by leftovers.
2322 "subs %[count], %[count], #7\n"
2323 "beq 2f\n"
2324
2325 "1:"
2326 "subs %[count], %[count], #16\n"
2327
2328 // Quantize::Transform
2329 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2330 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2331 "pld [%[input], #64]\n"
2332 "vsub.f32 q0, q0, q4\n"
2333 "vsub.f32 q1, q1, q4\n"
2334 "vsub.f32 q2, q2, q4\n"
2335 "vsub.f32 q3, q3, q4\n"
2336 "vmul.f32 q0, q0, q6\n"
2337 "vmul.f32 q1, q1, q6\n"
2338 "vmul.f32 q2, q2, q6\n"
2339 "vmul.f32 q3, q3, q6\n"
2340 "vadd.f32 q0, q0, q5\n"
2341 "vadd.f32 q1, q1, q5\n"
2342 "vadd.f32 q2, q2, q5\n"
2343 "vadd.f32 q3, q3, q5\n"
2344 "vcvt.s32.f32 q0, q0\n"
2345 "vcvt.s32.f32 q1, q1\n"
2346 "vcvt.s32.f32 q2, q2\n"
2347 "vcvt.s32.f32 q3, q3\n"
2348 "vqmovn.s32 d0, q0\n"
2349 "vqmovn.s32 d1, q1\n"
2350 "vqmovn.s32 d4, q2\n"
2351 "vqmovn.s32 d5, q3\n"
2352 "vqmovun.s16 d0, q0\n"
2353 "vqmovun.s16 d1, q2\n"
2354
2355 "vst1.32 {d0, d1}, [%[output]]!\n"
2356 "pld [%[output]]\n"
2357
2358 "bne 1b\n"
2359 "2:"
2360
2361 // Handle leftovers.
2362
2363 // Quantize::Transform
2364 "vld1.32 {d0, d1, d2}, [%[input]]!\n"
2365 "vld1.32 {d3[0]}, [%[input]]!\n"
2366 "pld [%[input], #64]\n"
2367 "vsub.f32 q0, q0, q4\n"
2368 "vsub.f32 q1, q1, q4\n"
2369 "vmul.f32 q0, q0, q6\n"
2370 "vmul.f32 q1, q1, q6\n"
2371 "vadd.f32 q0, q0, q5\n"
2372 "vadd.f32 q1, q1, q5\n"
2373 "vcvt.s32.f32 q0, q0\n"
2374 "vcvt.s32.f32 q1, q1\n"
2375 "vqmovn.s32 d0, q0\n"
2376 "vqmovn.s32 d1, q1\n"
2377 "vqmovun.s16 d0, q0\n"
2378
2379 "vst1.32 {d0[0]}, [%[output]]!\n"
2380 "vst1.16 {d0[2]}, [%[output]]!\n"
2381 "vst1.8 {d0[6]}, [%[output]]!\n"
2382 "pld [%[output]]\n"
2383 : [count] "+r"(params_count_copy), [input] "+r"(input),
2384 [output] "+r"(output)
2385 : [range_offset] "r"(params.range_offset),
2386 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2387 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2388 "d11", "d12", "d13", "cc", "memory");
2389 }
2390
2391 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2392 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 8>::Transform(
2393 const float* input, const Quantize& params, uint8_t* output) {
2394 #ifdef DEBUG
2395 #ifdef DEBUG_METAGEMM_VERBOSE
2396 std::cout << __FILE__ << "(" << __LINE__
2397 << ") Quantize<float, uint8_t, Quantize, 16, 8>::Transform()"
2398 << std::endl
2399 << std::flush;
2400 #endif
2401 #endif
2402 int params_count_copy = params.count;
2403 asm volatile(
2404
2405 // Quantize::Prepare
2406 "vdup.32 q4, %[range_min]\n"
2407 "vdup.32 q5, %[range_offset]\n"
2408 "vdup.32 q6, %[range_scale]\n"
2409
2410 // Reduce count by leftovers.
2411 "subs %[count], %[count], #8\n"
2412 "beq 2f\n"
2413
2414 "1:"
2415 "subs %[count], %[count], #16\n"
2416
2417 // Quantize::Transform
2418 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2419 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2420 "pld [%[input], #64]\n"
2421 "vsub.f32 q0, q0, q4\n"
2422 "vsub.f32 q1, q1, q4\n"
2423 "vsub.f32 q2, q2, q4\n"
2424 "vsub.f32 q3, q3, q4\n"
2425 "vmul.f32 q0, q0, q6\n"
2426 "vmul.f32 q1, q1, q6\n"
2427 "vmul.f32 q2, q2, q6\n"
2428 "vmul.f32 q3, q3, q6\n"
2429 "vadd.f32 q0, q0, q5\n"
2430 "vadd.f32 q1, q1, q5\n"
2431 "vadd.f32 q2, q2, q5\n"
2432 "vadd.f32 q3, q3, q5\n"
2433 "vcvt.s32.f32 q0, q0\n"
2434 "vcvt.s32.f32 q1, q1\n"
2435 "vcvt.s32.f32 q2, q2\n"
2436 "vcvt.s32.f32 q3, q3\n"
2437 "vqmovn.s32 d0, q0\n"
2438 "vqmovn.s32 d1, q1\n"
2439 "vqmovn.s32 d4, q2\n"
2440 "vqmovn.s32 d5, q3\n"
2441 "vqmovun.s16 d0, q0\n"
2442 "vqmovun.s16 d1, q2\n"
2443
2444 "vst1.32 {d0, d1}, [%[output]]!\n"
2445 "pld [%[output]]\n"
2446
2447 "bne 1b\n"
2448 "2:"
2449
2450 // Handle leftovers.
2451
2452 // Quantize::Transform
2453 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2454 "pld [%[input], #64]\n"
2455 "vsub.f32 q0, q0, q4\n"
2456 "vsub.f32 q1, q1, q4\n"
2457 "vmul.f32 q0, q0, q6\n"
2458 "vmul.f32 q1, q1, q6\n"
2459 "vadd.f32 q0, q0, q5\n"
2460 "vadd.f32 q1, q1, q5\n"
2461 "vcvt.s32.f32 q0, q0\n"
2462 "vcvt.s32.f32 q1, q1\n"
2463 "vqmovn.s32 d0, q0\n"
2464 "vqmovn.s32 d1, q1\n"
2465 "vqmovun.s16 d0, q0\n"
2466
2467 "vst1.32 {d0}, [%[output]]!\n"
2468 "pld [%[output]]\n"
2469 : [count] "+r"(params_count_copy), [input] "+r"(input),
2470 [output] "+r"(output)
2471 : [range_offset] "r"(params.range_offset),
2472 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2473 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2474 "d11", "d12", "d13", "cc", "memory");
2475 }
2476
2477 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2478 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 9>::Transform(
2479 const float* input, const Quantize& params, uint8_t* output) {
2480 #ifdef DEBUG
2481 #ifdef DEBUG_METAGEMM_VERBOSE
2482 std::cout << __FILE__ << "(" << __LINE__
2483 << ") Quantize<float, uint8_t, Quantize, 16, 9>::Transform()"
2484 << std::endl
2485 << std::flush;
2486 #endif
2487 #endif
2488 int params_count_copy = params.count;
2489 asm volatile(
2490
2491 // Quantize::Prepare
2492 "vdup.32 q4, %[range_min]\n"
2493 "vdup.32 q5, %[range_offset]\n"
2494 "vdup.32 q6, %[range_scale]\n"
2495
2496 // Reduce count by leftovers.
2497 "subs %[count], %[count], #9\n"
2498 "beq 2f\n"
2499
2500 "1:"
2501 "subs %[count], %[count], #16\n"
2502
2503 // Quantize::Transform
2504 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2505 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2506 "pld [%[input], #64]\n"
2507 "vsub.f32 q0, q0, q4\n"
2508 "vsub.f32 q1, q1, q4\n"
2509 "vsub.f32 q2, q2, q4\n"
2510 "vsub.f32 q3, q3, q4\n"
2511 "vmul.f32 q0, q0, q6\n"
2512 "vmul.f32 q1, q1, q6\n"
2513 "vmul.f32 q2, q2, q6\n"
2514 "vmul.f32 q3, q3, q6\n"
2515 "vadd.f32 q0, q0, q5\n"
2516 "vadd.f32 q1, q1, q5\n"
2517 "vadd.f32 q2, q2, q5\n"
2518 "vadd.f32 q3, q3, q5\n"
2519 "vcvt.s32.f32 q0, q0\n"
2520 "vcvt.s32.f32 q1, q1\n"
2521 "vcvt.s32.f32 q2, q2\n"
2522 "vcvt.s32.f32 q3, q3\n"
2523 "vqmovn.s32 d0, q0\n"
2524 "vqmovn.s32 d1, q1\n"
2525 "vqmovn.s32 d4, q2\n"
2526 "vqmovn.s32 d5, q3\n"
2527 "vqmovun.s16 d0, q0\n"
2528 "vqmovun.s16 d1, q2\n"
2529
2530 "vst1.32 {d0, d1}, [%[output]]!\n"
2531 "pld [%[output]]\n"
2532
2533 "bne 1b\n"
2534 "2:"
2535
2536 // Handle leftovers.
2537
2538 // Quantize::Transform
2539 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2540 "vld1.32 {d4[0]}, [%[input]]!\n"
2541 "pld [%[input], #64]\n"
2542 "vsub.f32 q0, q0, q4\n"
2543 "vsub.f32 q1, q1, q4\n"
2544 "vsub.f32 q2, q2, q4\n"
2545 "vmul.f32 q0, q0, q6\n"
2546 "vmul.f32 q1, q1, q6\n"
2547 "vmul.f32 q2, q2, q6\n"
2548 "vadd.f32 q0, q0, q5\n"
2549 "vadd.f32 q1, q1, q5\n"
2550 "vadd.f32 q2, q2, q5\n"
2551 "vcvt.s32.f32 q0, q0\n"
2552 "vcvt.s32.f32 q1, q1\n"
2553 "vcvt.s32.f32 q2, q2\n"
2554 "vqmovn.s32 d0, q0\n"
2555 "vqmovn.s32 d1, q1\n"
2556 "vqmovn.s32 d4, q2\n"
2557 "vqmovun.s16 d0, q0\n"
2558 "vqmovun.s16 d1, q2\n"
2559
2560 "vst1.32 {d0}, [%[output]]!\n"
2561 "vst1.8 {d1[0]}, [%[output]]!\n"
2562 "pld [%[output]]\n"
2563 : [count] "+r"(params_count_copy), [input] "+r"(input),
2564 [output] "+r"(output)
2565 : [range_offset] "r"(params.range_offset),
2566 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2567 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2568 "d11", "d12", "d13", "cc", "memory");
2569 }
2570
2571 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2572 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 10>::Transform(
2573 const float* input, const Quantize& params, uint8_t* output) {
2574 #ifdef DEBUG
2575 #ifdef DEBUG_METAGEMM_VERBOSE
2576 std::cout << __FILE__ << "(" << __LINE__
2577 << ") Quantize<float, uint8_t, Quantize, 16, 10>::Transform()"
2578 << std::endl
2579 << std::flush;
2580 #endif
2581 #endif
2582 int params_count_copy = params.count;
2583 asm volatile(
2584
2585 // Quantize::Prepare
2586 "vdup.32 q4, %[range_min]\n"
2587 "vdup.32 q5, %[range_offset]\n"
2588 "vdup.32 q6, %[range_scale]\n"
2589
2590 // Reduce count by leftovers.
2591 "subs %[count], %[count], #10\n"
2592 "beq 2f\n"
2593
2594 "1:"
2595 "subs %[count], %[count], #16\n"
2596
2597 // Quantize::Transform
2598 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2599 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2600 "pld [%[input], #64]\n"
2601 "vsub.f32 q0, q0, q4\n"
2602 "vsub.f32 q1, q1, q4\n"
2603 "vsub.f32 q2, q2, q4\n"
2604 "vsub.f32 q3, q3, q4\n"
2605 "vmul.f32 q0, q0, q6\n"
2606 "vmul.f32 q1, q1, q6\n"
2607 "vmul.f32 q2, q2, q6\n"
2608 "vmul.f32 q3, q3, q6\n"
2609 "vadd.f32 q0, q0, q5\n"
2610 "vadd.f32 q1, q1, q5\n"
2611 "vadd.f32 q2, q2, q5\n"
2612 "vadd.f32 q3, q3, q5\n"
2613 "vcvt.s32.f32 q0, q0\n"
2614 "vcvt.s32.f32 q1, q1\n"
2615 "vcvt.s32.f32 q2, q2\n"
2616 "vcvt.s32.f32 q3, q3\n"
2617 "vqmovn.s32 d0, q0\n"
2618 "vqmovn.s32 d1, q1\n"
2619 "vqmovn.s32 d4, q2\n"
2620 "vqmovn.s32 d5, q3\n"
2621 "vqmovun.s16 d0, q0\n"
2622 "vqmovun.s16 d1, q2\n"
2623
2624 "vst1.32 {d0, d1}, [%[output]]!\n"
2625 "pld [%[output]]\n"
2626
2627 "bne 1b\n"
2628 "2:"
2629
2630 // Handle leftovers.
2631
2632 // Quantize::Transform
2633 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2634 "vld1.32 {d4}, [%[input]]!\n"
2635 "pld [%[input], #64]\n"
2636 "vsub.f32 q0, q0, q4\n"
2637 "vsub.f32 q1, q1, q4\n"
2638 "vsub.f32 q2, q2, q4\n"
2639 "vmul.f32 q0, q0, q6\n"
2640 "vmul.f32 q1, q1, q6\n"
2641 "vmul.f32 q2, q2, q6\n"
2642 "vadd.f32 q0, q0, q5\n"
2643 "vadd.f32 q1, q1, q5\n"
2644 "vadd.f32 q2, q2, q5\n"
2645 "vcvt.s32.f32 q0, q0\n"
2646 "vcvt.s32.f32 q1, q1\n"
2647 "vcvt.s32.f32 q2, q2\n"
2648 "vqmovn.s32 d0, q0\n"
2649 "vqmovn.s32 d1, q1\n"
2650 "vqmovn.s32 d4, q2\n"
2651 "vqmovun.s16 d0, q0\n"
2652 "vqmovun.s16 d1, q2\n"
2653
2654 "vst1.32 {d0}, [%[output]]!\n"
2655 "vst1.16 {d1[0]}, [%[output]]!\n"
2656 "pld [%[output]]\n"
2657 : [count] "+r"(params_count_copy), [input] "+r"(input),
2658 [output] "+r"(output)
2659 : [range_offset] "r"(params.range_offset),
2660 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2661 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2662 "d11", "d12", "d13", "cc", "memory");
2663 }
2664
2665 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2666 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 11>::Transform(
2667 const float* input, const Quantize& params, uint8_t* output) {
2668 #ifdef DEBUG
2669 #ifdef DEBUG_METAGEMM_VERBOSE
2670 std::cout << __FILE__ << "(" << __LINE__
2671 << ") Quantize<float, uint8_t, Quantize, 16, 11>::Transform()"
2672 << std::endl
2673 << std::flush;
2674 #endif
2675 #endif
2676 int params_count_copy = params.count;
2677 asm volatile(
2678
2679 // Quantize::Prepare
2680 "vdup.32 q4, %[range_min]\n"
2681 "vdup.32 q5, %[range_offset]\n"
2682 "vdup.32 q6, %[range_scale]\n"
2683
2684 // Reduce count by leftovers.
2685 "subs %[count], %[count], #11\n"
2686 "beq 2f\n"
2687
2688 "1:"
2689 "subs %[count], %[count], #16\n"
2690
2691 // Quantize::Transform
2692 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2693 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2694 "pld [%[input], #64]\n"
2695 "vsub.f32 q0, q0, q4\n"
2696 "vsub.f32 q1, q1, q4\n"
2697 "vsub.f32 q2, q2, q4\n"
2698 "vsub.f32 q3, q3, q4\n"
2699 "vmul.f32 q0, q0, q6\n"
2700 "vmul.f32 q1, q1, q6\n"
2701 "vmul.f32 q2, q2, q6\n"
2702 "vmul.f32 q3, q3, q6\n"
2703 "vadd.f32 q0, q0, q5\n"
2704 "vadd.f32 q1, q1, q5\n"
2705 "vadd.f32 q2, q2, q5\n"
2706 "vadd.f32 q3, q3, q5\n"
2707 "vcvt.s32.f32 q0, q0\n"
2708 "vcvt.s32.f32 q1, q1\n"
2709 "vcvt.s32.f32 q2, q2\n"
2710 "vcvt.s32.f32 q3, q3\n"
2711 "vqmovn.s32 d0, q0\n"
2712 "vqmovn.s32 d1, q1\n"
2713 "vqmovn.s32 d4, q2\n"
2714 "vqmovn.s32 d5, q3\n"
2715 "vqmovun.s16 d0, q0\n"
2716 "vqmovun.s16 d1, q2\n"
2717
2718 "vst1.32 {d0, d1}, [%[output]]!\n"
2719 "pld [%[output]]\n"
2720
2721 "bne 1b\n"
2722 "2:"
2723
2724 // Handle leftovers.
2725
2726 // Quantize::Transform
2727 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2728 "vld1.32 {d4}, [%[input]]!\n"
2729 "vld1.32 {d5[0]}, [%[input]]!\n"
2730 "pld [%[input], #64]\n"
2731 "vsub.f32 q0, q0, q4\n"
2732 "vsub.f32 q1, q1, q4\n"
2733 "vsub.f32 q2, q2, q4\n"
2734 "vmul.f32 q0, q0, q6\n"
2735 "vmul.f32 q1, q1, q6\n"
2736 "vmul.f32 q2, q2, q6\n"
2737 "vadd.f32 q0, q0, q5\n"
2738 "vadd.f32 q1, q1, q5\n"
2739 "vadd.f32 q2, q2, q5\n"
2740 "vcvt.s32.f32 q0, q0\n"
2741 "vcvt.s32.f32 q1, q1\n"
2742 "vcvt.s32.f32 q2, q2\n"
2743 "vqmovn.s32 d0, q0\n"
2744 "vqmovn.s32 d1, q1\n"
2745 "vqmovn.s32 d4, q2\n"
2746 "vqmovun.s16 d0, q0\n"
2747 "vqmovun.s16 d1, q2\n"
2748
2749 "vst1.32 {d0}, [%[output]]!\n"
2750 "vst1.16 {d1[0]}, [%[output]]!\n"
2751 "vst1.8 {d1[2]}, [%[output]]!\n"
2752 "pld [%[output]]\n"
2753 : [count] "+r"(params_count_copy), [input] "+r"(input),
2754 [output] "+r"(output)
2755 : [range_offset] "r"(params.range_offset),
2756 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2757 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2758 "d11", "d12", "d13", "cc", "memory");
2759 }
2760
2761 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2762 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 12>::Transform(
2763 const float* input, const Quantize& params, uint8_t* output) {
2764 #ifdef DEBUG
2765 #ifdef DEBUG_METAGEMM_VERBOSE
2766 std::cout << __FILE__ << "(" << __LINE__
2767 << ") Quantize<float, uint8_t, Quantize, 16, 12>::Transform()"
2768 << std::endl
2769 << std::flush;
2770 #endif
2771 #endif
2772 int params_count_copy = params.count;
2773 asm volatile(
2774
2775 // Quantize::Prepare
2776 "vdup.32 q4, %[range_min]\n"
2777 "vdup.32 q5, %[range_offset]\n"
2778 "vdup.32 q6, %[range_scale]\n"
2779
2780 // Reduce count by leftovers.
2781 "subs %[count], %[count], #12\n"
2782 "beq 2f\n"
2783
2784 "1:"
2785 "subs %[count], %[count], #16\n"
2786
2787 // Quantize::Transform
2788 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2789 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2790 "pld [%[input], #64]\n"
2791 "vsub.f32 q0, q0, q4\n"
2792 "vsub.f32 q1, q1, q4\n"
2793 "vsub.f32 q2, q2, q4\n"
2794 "vsub.f32 q3, q3, q4\n"
2795 "vmul.f32 q0, q0, q6\n"
2796 "vmul.f32 q1, q1, q6\n"
2797 "vmul.f32 q2, q2, q6\n"
2798 "vmul.f32 q3, q3, q6\n"
2799 "vadd.f32 q0, q0, q5\n"
2800 "vadd.f32 q1, q1, q5\n"
2801 "vadd.f32 q2, q2, q5\n"
2802 "vadd.f32 q3, q3, q5\n"
2803 "vcvt.s32.f32 q0, q0\n"
2804 "vcvt.s32.f32 q1, q1\n"
2805 "vcvt.s32.f32 q2, q2\n"
2806 "vcvt.s32.f32 q3, q3\n"
2807 "vqmovn.s32 d0, q0\n"
2808 "vqmovn.s32 d1, q1\n"
2809 "vqmovn.s32 d4, q2\n"
2810 "vqmovn.s32 d5, q3\n"
2811 "vqmovun.s16 d0, q0\n"
2812 "vqmovun.s16 d1, q2\n"
2813
2814 "vst1.32 {d0, d1}, [%[output]]!\n"
2815 "pld [%[output]]\n"
2816
2817 "bne 1b\n"
2818 "2:"
2819
2820 // Handle leftovers.
2821
2822 // Quantize::Transform
2823 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2824 "vld1.32 {d4, d5}, [%[input]]!\n"
2825 "pld [%[input], #64]\n"
2826 "vsub.f32 q0, q0, q4\n"
2827 "vsub.f32 q1, q1, q4\n"
2828 "vsub.f32 q2, q2, q4\n"
2829 "vmul.f32 q0, q0, q6\n"
2830 "vmul.f32 q1, q1, q6\n"
2831 "vmul.f32 q2, q2, q6\n"
2832 "vadd.f32 q0, q0, q5\n"
2833 "vadd.f32 q1, q1, q5\n"
2834 "vadd.f32 q2, q2, q5\n"
2835 "vcvt.s32.f32 q0, q0\n"
2836 "vcvt.s32.f32 q1, q1\n"
2837 "vcvt.s32.f32 q2, q2\n"
2838 "vqmovn.s32 d0, q0\n"
2839 "vqmovn.s32 d1, q1\n"
2840 "vqmovn.s32 d4, q2\n"
2841 "vqmovun.s16 d0, q0\n"
2842 "vqmovun.s16 d1, q2\n"
2843
2844 "vst1.32 {d0}, [%[output]]!\n"
2845 "vst1.32 {d1[0]}, [%[output]]!\n"
2846 "pld [%[output]]\n"
2847 : [count] "+r"(params_count_copy), [input] "+r"(input),
2848 [output] "+r"(output)
2849 : [range_offset] "r"(params.range_offset),
2850 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2851 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2852 "d11", "d12", "d13", "cc", "memory");
2853 }
2854
2855 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2856 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 13>::Transform(
2857 const float* input, const Quantize& params, uint8_t* output) {
2858 #ifdef DEBUG
2859 #ifdef DEBUG_METAGEMM_VERBOSE
2860 std::cout << __FILE__ << "(" << __LINE__
2861 << ") Quantize<float, uint8_t, Quantize, 16, 13>::Transform()"
2862 << std::endl
2863 << std::flush;
2864 #endif
2865 #endif
2866 int params_count_copy = params.count;
2867 asm volatile(
2868
2869 // Quantize::Prepare
2870 "vdup.32 q4, %[range_min]\n"
2871 "vdup.32 q5, %[range_offset]\n"
2872 "vdup.32 q6, %[range_scale]\n"
2873
2874 // Reduce count by leftovers.
2875 "subs %[count], %[count], #13\n"
2876 "beq 2f\n"
2877
2878 "1:"
2879 "subs %[count], %[count], #16\n"
2880
2881 // Quantize::Transform
2882 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2883 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2884 "pld [%[input], #64]\n"
2885 "vsub.f32 q0, q0, q4\n"
2886 "vsub.f32 q1, q1, q4\n"
2887 "vsub.f32 q2, q2, q4\n"
2888 "vsub.f32 q3, q3, q4\n"
2889 "vmul.f32 q0, q0, q6\n"
2890 "vmul.f32 q1, q1, q6\n"
2891 "vmul.f32 q2, q2, q6\n"
2892 "vmul.f32 q3, q3, q6\n"
2893 "vadd.f32 q0, q0, q5\n"
2894 "vadd.f32 q1, q1, q5\n"
2895 "vadd.f32 q2, q2, q5\n"
2896 "vadd.f32 q3, q3, q5\n"
2897 "vcvt.s32.f32 q0, q0\n"
2898 "vcvt.s32.f32 q1, q1\n"
2899 "vcvt.s32.f32 q2, q2\n"
2900 "vcvt.s32.f32 q3, q3\n"
2901 "vqmovn.s32 d0, q0\n"
2902 "vqmovn.s32 d1, q1\n"
2903 "vqmovn.s32 d4, q2\n"
2904 "vqmovn.s32 d5, q3\n"
2905 "vqmovun.s16 d0, q0\n"
2906 "vqmovun.s16 d1, q2\n"
2907
2908 "vst1.32 {d0, d1}, [%[output]]!\n"
2909 "pld [%[output]]\n"
2910
2911 "bne 1b\n"
2912 "2:"
2913
2914 // Handle leftovers.
2915
2916 // Quantize::Transform
2917 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2918 "vld1.32 {d4, d5}, [%[input]]!\n"
2919 "vld1.32 {d6[0]}, [%[input]]!\n"
2920 "pld [%[input], #64]\n"
2921 "vsub.f32 q0, q0, q4\n"
2922 "vsub.f32 q1, q1, q4\n"
2923 "vsub.f32 q2, q2, q4\n"
2924 "vsub.f32 q3, q3, q4\n"
2925 "vmul.f32 q0, q0, q6\n"
2926 "vmul.f32 q1, q1, q6\n"
2927 "vmul.f32 q2, q2, q6\n"
2928 "vmul.f32 q3, q3, q6\n"
2929 "vadd.f32 q0, q0, q5\n"
2930 "vadd.f32 q1, q1, q5\n"
2931 "vadd.f32 q2, q2, q5\n"
2932 "vadd.f32 q3, q3, q5\n"
2933 "vcvt.s32.f32 q0, q0\n"
2934 "vcvt.s32.f32 q1, q1\n"
2935 "vcvt.s32.f32 q2, q2\n"
2936 "vcvt.s32.f32 q3, q3\n"
2937 "vqmovn.s32 d0, q0\n"
2938 "vqmovn.s32 d1, q1\n"
2939 "vqmovn.s32 d4, q2\n"
2940 "vqmovn.s32 d5, q3\n"
2941 "vqmovun.s16 d0, q0\n"
2942 "vqmovun.s16 d1, q2\n"
2943
2944 "vst1.32 {d0}, [%[output]]!\n"
2945 "vst1.32 {d1[0]}, [%[output]]!\n"
2946 "vst1.8 {d1[4]}, [%[output]]!\n"
2947 "pld [%[output]]\n"
2948 : [count] "+r"(params_count_copy), [input] "+r"(input),
2949 [output] "+r"(output)
2950 : [range_offset] "r"(params.range_offset),
2951 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
2952 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
2953 "d11", "d12", "d13", "cc", "memory");
2954 }
2955
2956 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)2957 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 14>::Transform(
2958 const float* input, const Quantize& params, uint8_t* output) {
2959 #ifdef DEBUG
2960 #ifdef DEBUG_METAGEMM_VERBOSE
2961 std::cout << __FILE__ << "(" << __LINE__
2962 << ") Quantize<float, uint8_t, Quantize, 16, 14>::Transform()"
2963 << std::endl
2964 << std::flush;
2965 #endif
2966 #endif
2967 int params_count_copy = params.count;
2968 asm volatile(
2969
2970 // Quantize::Prepare
2971 "vdup.32 q4, %[range_min]\n"
2972 "vdup.32 q5, %[range_offset]\n"
2973 "vdup.32 q6, %[range_scale]\n"
2974
2975 // Reduce count by leftovers.
2976 "subs %[count], %[count], #14\n"
2977 "beq 2f\n"
2978
2979 "1:"
2980 "subs %[count], %[count], #16\n"
2981
2982 // Quantize::Transform
2983 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
2984 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
2985 "pld [%[input], #64]\n"
2986 "vsub.f32 q0, q0, q4\n"
2987 "vsub.f32 q1, q1, q4\n"
2988 "vsub.f32 q2, q2, q4\n"
2989 "vsub.f32 q3, q3, q4\n"
2990 "vmul.f32 q0, q0, q6\n"
2991 "vmul.f32 q1, q1, q6\n"
2992 "vmul.f32 q2, q2, q6\n"
2993 "vmul.f32 q3, q3, q6\n"
2994 "vadd.f32 q0, q0, q5\n"
2995 "vadd.f32 q1, q1, q5\n"
2996 "vadd.f32 q2, q2, q5\n"
2997 "vadd.f32 q3, q3, q5\n"
2998 "vcvt.s32.f32 q0, q0\n"
2999 "vcvt.s32.f32 q1, q1\n"
3000 "vcvt.s32.f32 q2, q2\n"
3001 "vcvt.s32.f32 q3, q3\n"
3002 "vqmovn.s32 d0, q0\n"
3003 "vqmovn.s32 d1, q1\n"
3004 "vqmovn.s32 d4, q2\n"
3005 "vqmovn.s32 d5, q3\n"
3006 "vqmovun.s16 d0, q0\n"
3007 "vqmovun.s16 d1, q2\n"
3008
3009 "vst1.32 {d0, d1}, [%[output]]!\n"
3010 "pld [%[output]]\n"
3011
3012 "bne 1b\n"
3013 "2:"
3014
3015 // Handle leftovers.
3016
3017 // Quantize::Transform
3018 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
3019 "vld1.32 {d4, d5, d6}, [%[input]]!\n"
3020 "pld [%[input], #64]\n"
3021 "vsub.f32 q0, q0, q4\n"
3022 "vsub.f32 q1, q1, q4\n"
3023 "vsub.f32 q2, q2, q4\n"
3024 "vsub.f32 q3, q3, q4\n"
3025 "vmul.f32 q0, q0, q6\n"
3026 "vmul.f32 q1, q1, q6\n"
3027 "vmul.f32 q2, q2, q6\n"
3028 "vmul.f32 q3, q3, q6\n"
3029 "vadd.f32 q0, q0, q5\n"
3030 "vadd.f32 q1, q1, q5\n"
3031 "vadd.f32 q2, q2, q5\n"
3032 "vadd.f32 q3, q3, q5\n"
3033 "vcvt.s32.f32 q0, q0\n"
3034 "vcvt.s32.f32 q1, q1\n"
3035 "vcvt.s32.f32 q2, q2\n"
3036 "vcvt.s32.f32 q3, q3\n"
3037 "vqmovn.s32 d0, q0\n"
3038 "vqmovn.s32 d1, q1\n"
3039 "vqmovn.s32 d4, q2\n"
3040 "vqmovn.s32 d5, q3\n"
3041 "vqmovun.s16 d0, q0\n"
3042 "vqmovun.s16 d1, q2\n"
3043
3044 "vst1.32 {d0}, [%[output]]!\n"
3045 "vst1.32 {d1[0]}, [%[output]]!\n"
3046 "vst1.16 {d1[2]}, [%[output]]!\n"
3047 "pld [%[output]]\n"
3048 : [count] "+r"(params_count_copy), [input] "+r"(input),
3049 [output] "+r"(output)
3050 : [range_offset] "r"(params.range_offset),
3051 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3052 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3053 "d11", "d12", "d13", "cc", "memory");
3054 }
3055
3056 template <>
Transform(const float * input,const Quantize & params,uint8_t * output)3057 inline void Transform1DKernel<float, uint8_t, Quantize, 16, 15>::Transform(
3058 const float* input, const Quantize& params, uint8_t* output) {
3059 #ifdef DEBUG
3060 #ifdef DEBUG_METAGEMM_VERBOSE
3061 std::cout << __FILE__ << "(" << __LINE__
3062 << ") Quantize<float, uint8_t, Quantize, 16, 15>::Transform()"
3063 << std::endl
3064 << std::flush;
3065 #endif
3066 #endif
3067 int params_count_copy = params.count;
3068 asm volatile(
3069
3070 // Quantize::Prepare
3071 "vdup.32 q4, %[range_min]\n"
3072 "vdup.32 q5, %[range_offset]\n"
3073 "vdup.32 q6, %[range_scale]\n"
3074
3075 // Reduce count by leftovers.
3076 "subs %[count], %[count], #15\n"
3077 "beq 2f\n"
3078
3079 "1:"
3080 "subs %[count], %[count], #16\n"
3081
3082 // Quantize::Transform
3083 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
3084 "vld1.32 {d4, d5, d6, d7}, [%[input]]!\n"
3085 "pld [%[input], #64]\n"
3086 "vsub.f32 q0, q0, q4\n"
3087 "vsub.f32 q1, q1, q4\n"
3088 "vsub.f32 q2, q2, q4\n"
3089 "vsub.f32 q3, q3, q4\n"
3090 "vmul.f32 q0, q0, q6\n"
3091 "vmul.f32 q1, q1, q6\n"
3092 "vmul.f32 q2, q2, q6\n"
3093 "vmul.f32 q3, q3, q6\n"
3094 "vadd.f32 q0, q0, q5\n"
3095 "vadd.f32 q1, q1, q5\n"
3096 "vadd.f32 q2, q2, q5\n"
3097 "vadd.f32 q3, q3, q5\n"
3098 "vcvt.s32.f32 q0, q0\n"
3099 "vcvt.s32.f32 q1, q1\n"
3100 "vcvt.s32.f32 q2, q2\n"
3101 "vcvt.s32.f32 q3, q3\n"
3102 "vqmovn.s32 d0, q0\n"
3103 "vqmovn.s32 d1, q1\n"
3104 "vqmovn.s32 d4, q2\n"
3105 "vqmovn.s32 d5, q3\n"
3106 "vqmovun.s16 d0, q0\n"
3107 "vqmovun.s16 d1, q2\n"
3108
3109 "vst1.32 {d0, d1}, [%[output]]!\n"
3110 "pld [%[output]]\n"
3111
3112 "bne 1b\n"
3113 "2:"
3114
3115 // Handle leftovers.
3116
3117 // Quantize::Transform
3118 "vld1.32 {d0, d1, d2, d3}, [%[input]]!\n"
3119 "vld1.32 {d4, d5, d6}, [%[input]]!\n"
3120 "vld1.32 {d7[0]}, [%[input]]!\n"
3121 "pld [%[input], #64]\n"
3122 "vsub.f32 q0, q0, q4\n"
3123 "vsub.f32 q1, q1, q4\n"
3124 "vsub.f32 q2, q2, q4\n"
3125 "vsub.f32 q3, q3, q4\n"
3126 "vmul.f32 q0, q0, q6\n"
3127 "vmul.f32 q1, q1, q6\n"
3128 "vmul.f32 q2, q2, q6\n"
3129 "vmul.f32 q3, q3, q6\n"
3130 "vadd.f32 q0, q0, q5\n"
3131 "vadd.f32 q1, q1, q5\n"
3132 "vadd.f32 q2, q2, q5\n"
3133 "vadd.f32 q3, q3, q5\n"
3134 "vcvt.s32.f32 q0, q0\n"
3135 "vcvt.s32.f32 q1, q1\n"
3136 "vcvt.s32.f32 q2, q2\n"
3137 "vcvt.s32.f32 q3, q3\n"
3138 "vqmovn.s32 d0, q0\n"
3139 "vqmovn.s32 d1, q1\n"
3140 "vqmovn.s32 d4, q2\n"
3141 "vqmovn.s32 d5, q3\n"
3142 "vqmovun.s16 d0, q0\n"
3143 "vqmovun.s16 d1, q2\n"
3144
3145 "vst1.32 {d0}, [%[output]]!\n"
3146 "vst1.32 {d1[0]}, [%[output]]!\n"
3147 "vst1.16 {d1[2]}, [%[output]]!\n"
3148 "vst1.8 {d1[6]}, [%[output]]!\n"
3149 "pld [%[output]]\n"
3150 : [count] "+r"(params_count_copy), [input] "+r"(input),
3151 [output] "+r"(output)
3152 : [range_offset] "r"(params.range_offset),
3153 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3154 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3155 "d11", "d12", "d13", "cc", "memory");
3156 }
3157
3158 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3159 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 0>::Transform(
3160 const uint8_t* input, const Dequantize& params, float* output) {
3161 #ifdef DEBUG
3162 #ifdef DEBUG_METAGEMM_VERBOSE
3163 std::cout << __FILE__ << "(" << __LINE__
3164 << ") Dequantize<uint8_t, float, Dequantize, 16, 0>::Transform()"
3165 << std::endl
3166 << std::flush;
3167 #endif
3168 #endif
3169 int params_count_copy = params.count;
3170 asm volatile(
3171
3172 // Dequantize::Prepare
3173 "vdup.32 q4, %[range_min]\n"
3174 "vdup.32 q5, %[range_offset]\n"
3175 "vdup.32 q6, %[range_scale]\n"
3176
3177 "1:"
3178 "subs %[count], %[count], #16\n"
3179
3180 // Dequantize::Transform
3181 "vld1.32 {d0, d1}, [%[input]]!\n"
3182 "pld [%[input], #32]\n"
3183 "vmovl.u8 q1, d1\n"
3184 "vmovl.u8 q0, d0\n"
3185 "vmovl.s16 q3, d3\n"
3186 "vmovl.s16 q2, d2\n"
3187 "vmovl.s16 q1, d1\n"
3188 "vmovl.s16 q0, d0\n"
3189 "vcvt.f32.s32 q0, q0\n"
3190 "vcvt.f32.s32 q1, q1\n"
3191 "vcvt.f32.s32 q2, q2\n"
3192 "vcvt.f32.s32 q3, q3\n"
3193 "vsub.f32 q0, q0, q5\n"
3194 "vsub.f32 q1, q1, q5\n"
3195 "vsub.f32 q2, q2, q5\n"
3196 "vsub.f32 q3, q3, q5\n"
3197 "vmul.f32 q0, q0, q6\n"
3198 "vmul.f32 q1, q1, q6\n"
3199 "vmul.f32 q2, q2, q6\n"
3200 "vmul.f32 q3, q3, q6\n"
3201 "vadd.f32 q0, q0, q4\n"
3202 "vadd.f32 q1, q1, q4\n"
3203 "vadd.f32 q2, q2, q4\n"
3204 "vadd.f32 q3, q3, q4\n"
3205
3206 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3207 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3208 "pld [%[output]]\n"
3209
3210 "bne 1b\n"
3211 : [count] "+r"(params_count_copy), [input] "+r"(input),
3212 [output] "+r"(output)
3213 : [range_offset] "r"(params.range_offset),
3214 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3215 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3216 "d11", "d12", "d13", "cc", "memory");
3217 }
3218
3219 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3220 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 1>::Transform(
3221 const uint8_t* input, const Dequantize& params, float* output) {
3222 #ifdef DEBUG
3223 #ifdef DEBUG_METAGEMM_VERBOSE
3224 std::cout << __FILE__ << "(" << __LINE__
3225 << ") Dequantize<uint8_t, float, Dequantize, 16, 1>::Transform()"
3226 << std::endl
3227 << std::flush;
3228 #endif
3229 #endif
3230 int params_count_copy = params.count;
3231 asm volatile(
3232
3233 // Dequantize::Prepare
3234 "vdup.32 q4, %[range_min]\n"
3235 "vdup.32 q5, %[range_offset]\n"
3236 "vdup.32 q6, %[range_scale]\n"
3237
3238 // Reduce count by leftovers.
3239 "subs %[count], %[count], #1\n"
3240 "beq 2f\n"
3241
3242 "1:"
3243 "subs %[count], %[count], #16\n"
3244
3245 // Dequantize::Transform
3246 "vld1.32 {d0, d1}, [%[input]]!\n"
3247 "pld [%[input], #32]\n"
3248 "vmovl.u8 q1, d1\n"
3249 "vmovl.u8 q0, d0\n"
3250 "vmovl.s16 q3, d3\n"
3251 "vmovl.s16 q2, d2\n"
3252 "vmovl.s16 q1, d1\n"
3253 "vmovl.s16 q0, d0\n"
3254 "vcvt.f32.s32 q0, q0\n"
3255 "vcvt.f32.s32 q1, q1\n"
3256 "vcvt.f32.s32 q2, q2\n"
3257 "vcvt.f32.s32 q3, q3\n"
3258 "vsub.f32 q0, q0, q5\n"
3259 "vsub.f32 q1, q1, q5\n"
3260 "vsub.f32 q2, q2, q5\n"
3261 "vsub.f32 q3, q3, q5\n"
3262 "vmul.f32 q0, q0, q6\n"
3263 "vmul.f32 q1, q1, q6\n"
3264 "vmul.f32 q2, q2, q6\n"
3265 "vmul.f32 q3, q3, q6\n"
3266 "vadd.f32 q0, q0, q4\n"
3267 "vadd.f32 q1, q1, q4\n"
3268 "vadd.f32 q2, q2, q4\n"
3269 "vadd.f32 q3, q3, q4\n"
3270
3271 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3272 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3273 "pld [%[output]]\n"
3274
3275 "bne 1b\n"
3276 "2:"
3277
3278 // Handle leftovers.
3279
3280 // Dequantize::Transform
3281 "vld1.8 {d0[0]}, [%[input]]!\n"
3282 "pld [%[input], #32]\n"
3283 "vmovl.u8 q0, d0\n"
3284 "vmovl.s16 q0, d0\n"
3285 "vcvt.f32.s32 q0, q0\n"
3286 "vsub.f32 q0, q0, q5\n"
3287 "vmul.f32 q0, q0, q6\n"
3288 "vadd.f32 q0, q0, q4\n"
3289
3290 "vst1.32 {d0[0]}, [%[output]]!\n"
3291 "pld [%[output]]\n"
3292 : [count] "+r"(params_count_copy), [input] "+r"(input),
3293 [output] "+r"(output)
3294 : [range_offset] "r"(params.range_offset),
3295 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3296 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3297 "d11", "d12", "d13", "cc", "memory");
3298 }
3299
3300 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3301 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 2>::Transform(
3302 const uint8_t* input, const Dequantize& params, float* output) {
3303 #ifdef DEBUG
3304 #ifdef DEBUG_METAGEMM_VERBOSE
3305 std::cout << __FILE__ << "(" << __LINE__
3306 << ") Dequantize<uint8_t, float, Dequantize, 16, 2>::Transform()"
3307 << std::endl
3308 << std::flush;
3309 #endif
3310 #endif
3311 int params_count_copy = params.count;
3312 asm volatile(
3313
3314 // Dequantize::Prepare
3315 "vdup.32 q4, %[range_min]\n"
3316 "vdup.32 q5, %[range_offset]\n"
3317 "vdup.32 q6, %[range_scale]\n"
3318
3319 // Reduce count by leftovers.
3320 "subs %[count], %[count], #2\n"
3321 "beq 2f\n"
3322
3323 "1:"
3324 "subs %[count], %[count], #16\n"
3325
3326 // Dequantize::Transform
3327 "vld1.32 {d0, d1}, [%[input]]!\n"
3328 "pld [%[input], #32]\n"
3329 "vmovl.u8 q1, d1\n"
3330 "vmovl.u8 q0, d0\n"
3331 "vmovl.s16 q3, d3\n"
3332 "vmovl.s16 q2, d2\n"
3333 "vmovl.s16 q1, d1\n"
3334 "vmovl.s16 q0, d0\n"
3335 "vcvt.f32.s32 q0, q0\n"
3336 "vcvt.f32.s32 q1, q1\n"
3337 "vcvt.f32.s32 q2, q2\n"
3338 "vcvt.f32.s32 q3, q3\n"
3339 "vsub.f32 q0, q0, q5\n"
3340 "vsub.f32 q1, q1, q5\n"
3341 "vsub.f32 q2, q2, q5\n"
3342 "vsub.f32 q3, q3, q5\n"
3343 "vmul.f32 q0, q0, q6\n"
3344 "vmul.f32 q1, q1, q6\n"
3345 "vmul.f32 q2, q2, q6\n"
3346 "vmul.f32 q3, q3, q6\n"
3347 "vadd.f32 q0, q0, q4\n"
3348 "vadd.f32 q1, q1, q4\n"
3349 "vadd.f32 q2, q2, q4\n"
3350 "vadd.f32 q3, q3, q4\n"
3351
3352 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3353 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3354 "pld [%[output]]\n"
3355
3356 "bne 1b\n"
3357 "2:"
3358
3359 // Handle leftovers.
3360
3361 // Dequantize::Transform
3362 "vld1.16 {d0[0]}, [%[input]]!\n"
3363 "pld [%[input], #32]\n"
3364 "vmovl.u8 q0, d0\n"
3365 "vmovl.s16 q0, d0\n"
3366 "vcvt.f32.s32 q0, q0\n"
3367 "vsub.f32 q0, q0, q5\n"
3368 "vmul.f32 q0, q0, q6\n"
3369 "vadd.f32 q0, q0, q4\n"
3370
3371 "vst1.32 {d0}, [%[output]]!\n"
3372 "pld [%[output]]\n"
3373 : [count] "+r"(params_count_copy), [input] "+r"(input),
3374 [output] "+r"(output)
3375 : [range_offset] "r"(params.range_offset),
3376 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3377 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3378 "d11", "d12", "d13", "cc", "memory");
3379 }
3380
3381 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3382 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 3>::Transform(
3383 const uint8_t* input, const Dequantize& params, float* output) {
3384 #ifdef DEBUG
3385 #ifdef DEBUG_METAGEMM_VERBOSE
3386 std::cout << __FILE__ << "(" << __LINE__
3387 << ") Dequantize<uint8_t, float, Dequantize, 16, 3>::Transform()"
3388 << std::endl
3389 << std::flush;
3390 #endif
3391 #endif
3392 int params_count_copy = params.count;
3393 asm volatile(
3394
3395 // Dequantize::Prepare
3396 "vdup.32 q4, %[range_min]\n"
3397 "vdup.32 q5, %[range_offset]\n"
3398 "vdup.32 q6, %[range_scale]\n"
3399
3400 // Reduce count by leftovers.
3401 "subs %[count], %[count], #3\n"
3402 "beq 2f\n"
3403
3404 "1:"
3405 "subs %[count], %[count], #16\n"
3406
3407 // Dequantize::Transform
3408 "vld1.32 {d0, d1}, [%[input]]!\n"
3409 "pld [%[input], #32]\n"
3410 "vmovl.u8 q1, d1\n"
3411 "vmovl.u8 q0, d0\n"
3412 "vmovl.s16 q3, d3\n"
3413 "vmovl.s16 q2, d2\n"
3414 "vmovl.s16 q1, d1\n"
3415 "vmovl.s16 q0, d0\n"
3416 "vcvt.f32.s32 q0, q0\n"
3417 "vcvt.f32.s32 q1, q1\n"
3418 "vcvt.f32.s32 q2, q2\n"
3419 "vcvt.f32.s32 q3, q3\n"
3420 "vsub.f32 q0, q0, q5\n"
3421 "vsub.f32 q1, q1, q5\n"
3422 "vsub.f32 q2, q2, q5\n"
3423 "vsub.f32 q3, q3, q5\n"
3424 "vmul.f32 q0, q0, q6\n"
3425 "vmul.f32 q1, q1, q6\n"
3426 "vmul.f32 q2, q2, q6\n"
3427 "vmul.f32 q3, q3, q6\n"
3428 "vadd.f32 q0, q0, q4\n"
3429 "vadd.f32 q1, q1, q4\n"
3430 "vadd.f32 q2, q2, q4\n"
3431 "vadd.f32 q3, q3, q4\n"
3432
3433 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3434 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3435 "pld [%[output]]\n"
3436
3437 "bne 1b\n"
3438 "2:"
3439
3440 // Handle leftovers.
3441
3442 // Dequantize::Transform
3443 "vld1.16 {d0[0]}, [%[input]]!\n"
3444 "vld1.8 {d0[2]}, [%[input]]!\n"
3445 "pld [%[input], #32]\n"
3446 "vmovl.u8 q0, d0\n"
3447 "vmovl.s16 q0, d0\n"
3448 "vcvt.f32.s32 q0, q0\n"
3449 "vsub.f32 q0, q0, q5\n"
3450 "vmul.f32 q0, q0, q6\n"
3451 "vadd.f32 q0, q0, q4\n"
3452
3453 "vst1.32 {d0}, [%[output]]!\n"
3454 "vst1.32 {d1[0]}, [%[output]]!\n"
3455 "pld [%[output]]\n"
3456 : [count] "+r"(params_count_copy), [input] "+r"(input),
3457 [output] "+r"(output)
3458 : [range_offset] "r"(params.range_offset),
3459 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3460 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3461 "d11", "d12", "d13", "cc", "memory");
3462 }
3463
3464 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3465 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 4>::Transform(
3466 const uint8_t* input, const Dequantize& params, float* output) {
3467 #ifdef DEBUG
3468 #ifdef DEBUG_METAGEMM_VERBOSE
3469 std::cout << __FILE__ << "(" << __LINE__
3470 << ") Dequantize<uint8_t, float, Dequantize, 16, 4>::Transform()"
3471 << std::endl
3472 << std::flush;
3473 #endif
3474 #endif
3475 int params_count_copy = params.count;
3476 asm volatile(
3477
3478 // Dequantize::Prepare
3479 "vdup.32 q4, %[range_min]\n"
3480 "vdup.32 q5, %[range_offset]\n"
3481 "vdup.32 q6, %[range_scale]\n"
3482
3483 // Reduce count by leftovers.
3484 "subs %[count], %[count], #4\n"
3485 "beq 2f\n"
3486
3487 "1:"
3488 "subs %[count], %[count], #16\n"
3489
3490 // Dequantize::Transform
3491 "vld1.32 {d0, d1}, [%[input]]!\n"
3492 "pld [%[input], #32]\n"
3493 "vmovl.u8 q1, d1\n"
3494 "vmovl.u8 q0, d0\n"
3495 "vmovl.s16 q3, d3\n"
3496 "vmovl.s16 q2, d2\n"
3497 "vmovl.s16 q1, d1\n"
3498 "vmovl.s16 q0, d0\n"
3499 "vcvt.f32.s32 q0, q0\n"
3500 "vcvt.f32.s32 q1, q1\n"
3501 "vcvt.f32.s32 q2, q2\n"
3502 "vcvt.f32.s32 q3, q3\n"
3503 "vsub.f32 q0, q0, q5\n"
3504 "vsub.f32 q1, q1, q5\n"
3505 "vsub.f32 q2, q2, q5\n"
3506 "vsub.f32 q3, q3, q5\n"
3507 "vmul.f32 q0, q0, q6\n"
3508 "vmul.f32 q1, q1, q6\n"
3509 "vmul.f32 q2, q2, q6\n"
3510 "vmul.f32 q3, q3, q6\n"
3511 "vadd.f32 q0, q0, q4\n"
3512 "vadd.f32 q1, q1, q4\n"
3513 "vadd.f32 q2, q2, q4\n"
3514 "vadd.f32 q3, q3, q4\n"
3515
3516 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3517 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3518 "pld [%[output]]\n"
3519
3520 "bne 1b\n"
3521 "2:"
3522
3523 // Handle leftovers.
3524
3525 // Dequantize::Transform
3526 "vld1.32 {d0[0]}, [%[input]]!\n"
3527 "pld [%[input], #32]\n"
3528 "vmovl.u8 q0, d0\n"
3529 "vmovl.s16 q0, d0\n"
3530 "vcvt.f32.s32 q0, q0\n"
3531 "vsub.f32 q0, q0, q5\n"
3532 "vmul.f32 q0, q0, q6\n"
3533 "vadd.f32 q0, q0, q4\n"
3534
3535 "vst1.32 {d0, d1}, [%[output]]!\n"
3536 "pld [%[output]]\n"
3537 : [count] "+r"(params_count_copy), [input] "+r"(input),
3538 [output] "+r"(output)
3539 : [range_offset] "r"(params.range_offset),
3540 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3541 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3542 "d11", "d12", "d13", "cc", "memory");
3543 }
3544
3545 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3546 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 5>::Transform(
3547 const uint8_t* input, const Dequantize& params, float* output) {
3548 #ifdef DEBUG
3549 #ifdef DEBUG_METAGEMM_VERBOSE
3550 std::cout << __FILE__ << "(" << __LINE__
3551 << ") Dequantize<uint8_t, float, Dequantize, 16, 5>::Transform()"
3552 << std::endl
3553 << std::flush;
3554 #endif
3555 #endif
3556 int params_count_copy = params.count;
3557 asm volatile(
3558
3559 // Dequantize::Prepare
3560 "vdup.32 q4, %[range_min]\n"
3561 "vdup.32 q5, %[range_offset]\n"
3562 "vdup.32 q6, %[range_scale]\n"
3563
3564 // Reduce count by leftovers.
3565 "subs %[count], %[count], #5\n"
3566 "beq 2f\n"
3567
3568 "1:"
3569 "subs %[count], %[count], #16\n"
3570
3571 // Dequantize::Transform
3572 "vld1.32 {d0, d1}, [%[input]]!\n"
3573 "pld [%[input], #32]\n"
3574 "vmovl.u8 q1, d1\n"
3575 "vmovl.u8 q0, d0\n"
3576 "vmovl.s16 q3, d3\n"
3577 "vmovl.s16 q2, d2\n"
3578 "vmovl.s16 q1, d1\n"
3579 "vmovl.s16 q0, d0\n"
3580 "vcvt.f32.s32 q0, q0\n"
3581 "vcvt.f32.s32 q1, q1\n"
3582 "vcvt.f32.s32 q2, q2\n"
3583 "vcvt.f32.s32 q3, q3\n"
3584 "vsub.f32 q0, q0, q5\n"
3585 "vsub.f32 q1, q1, q5\n"
3586 "vsub.f32 q2, q2, q5\n"
3587 "vsub.f32 q3, q3, q5\n"
3588 "vmul.f32 q0, q0, q6\n"
3589 "vmul.f32 q1, q1, q6\n"
3590 "vmul.f32 q2, q2, q6\n"
3591 "vmul.f32 q3, q3, q6\n"
3592 "vadd.f32 q0, q0, q4\n"
3593 "vadd.f32 q1, q1, q4\n"
3594 "vadd.f32 q2, q2, q4\n"
3595 "vadd.f32 q3, q3, q4\n"
3596
3597 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3598 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3599 "pld [%[output]]\n"
3600
3601 "bne 1b\n"
3602 "2:"
3603
3604 // Handle leftovers.
3605
3606 // Dequantize::Transform
3607 "vld1.32 {d0[0]}, [%[input]]!\n"
3608 "vld1.8 {d0[4]}, [%[input]]!\n"
3609 "pld [%[input], #32]\n"
3610 "vmovl.u8 q0, d0\n"
3611 "vmovl.s16 q1, d1\n"
3612 "vmovl.s16 q0, d0\n"
3613 "vcvt.f32.s32 q0, q0\n"
3614 "vcvt.f32.s32 q1, q1\n"
3615 "vsub.f32 q0, q0, q5\n"
3616 "vsub.f32 q1, q1, q5\n"
3617 "vmul.f32 q0, q0, q6\n"
3618 "vmul.f32 q1, q1, q6\n"
3619 "vadd.f32 q0, q0, q4\n"
3620 "vadd.f32 q1, q1, q4\n"
3621
3622 "vst1.32 {d0, d1}, [%[output]]!\n"
3623 "vst1.32 {d2[0]}, [%[output]]!\n"
3624 "pld [%[output]]\n"
3625 : [count] "+r"(params_count_copy), [input] "+r"(input),
3626 [output] "+r"(output)
3627 : [range_offset] "r"(params.range_offset),
3628 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3629 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3630 "d11", "d12", "d13", "cc", "memory");
3631 }
3632
3633 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3634 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 6>::Transform(
3635 const uint8_t* input, const Dequantize& params, float* output) {
3636 #ifdef DEBUG
3637 #ifdef DEBUG_METAGEMM_VERBOSE
3638 std::cout << __FILE__ << "(" << __LINE__
3639 << ") Dequantize<uint8_t, float, Dequantize, 16, 6>::Transform()"
3640 << std::endl
3641 << std::flush;
3642 #endif
3643 #endif
3644 int params_count_copy = params.count;
3645 asm volatile(
3646
3647 // Dequantize::Prepare
3648 "vdup.32 q4, %[range_min]\n"
3649 "vdup.32 q5, %[range_offset]\n"
3650 "vdup.32 q6, %[range_scale]\n"
3651
3652 // Reduce count by leftovers.
3653 "subs %[count], %[count], #6\n"
3654 "beq 2f\n"
3655
3656 "1:"
3657 "subs %[count], %[count], #16\n"
3658
3659 // Dequantize::Transform
3660 "vld1.32 {d0, d1}, [%[input]]!\n"
3661 "pld [%[input], #32]\n"
3662 "vmovl.u8 q1, d1\n"
3663 "vmovl.u8 q0, d0\n"
3664 "vmovl.s16 q3, d3\n"
3665 "vmovl.s16 q2, d2\n"
3666 "vmovl.s16 q1, d1\n"
3667 "vmovl.s16 q0, d0\n"
3668 "vcvt.f32.s32 q0, q0\n"
3669 "vcvt.f32.s32 q1, q1\n"
3670 "vcvt.f32.s32 q2, q2\n"
3671 "vcvt.f32.s32 q3, q3\n"
3672 "vsub.f32 q0, q0, q5\n"
3673 "vsub.f32 q1, q1, q5\n"
3674 "vsub.f32 q2, q2, q5\n"
3675 "vsub.f32 q3, q3, q5\n"
3676 "vmul.f32 q0, q0, q6\n"
3677 "vmul.f32 q1, q1, q6\n"
3678 "vmul.f32 q2, q2, q6\n"
3679 "vmul.f32 q3, q3, q6\n"
3680 "vadd.f32 q0, q0, q4\n"
3681 "vadd.f32 q1, q1, q4\n"
3682 "vadd.f32 q2, q2, q4\n"
3683 "vadd.f32 q3, q3, q4\n"
3684
3685 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3686 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3687 "pld [%[output]]\n"
3688
3689 "bne 1b\n"
3690 "2:"
3691
3692 // Handle leftovers.
3693
3694 // Dequantize::Transform
3695 "vld1.32 {d0[0]}, [%[input]]!\n"
3696 "vld1.16 {d0[2]}, [%[input]]!\n"
3697 "pld [%[input], #32]\n"
3698 "vmovl.u8 q0, d0\n"
3699 "vmovl.s16 q1, d1\n"
3700 "vmovl.s16 q0, d0\n"
3701 "vcvt.f32.s32 q0, q0\n"
3702 "vcvt.f32.s32 q1, q1\n"
3703 "vsub.f32 q0, q0, q5\n"
3704 "vsub.f32 q1, q1, q5\n"
3705 "vmul.f32 q0, q0, q6\n"
3706 "vmul.f32 q1, q1, q6\n"
3707 "vadd.f32 q0, q0, q4\n"
3708 "vadd.f32 q1, q1, q4\n"
3709
3710 "vst1.32 {d0, d1, d2}, [%[output]]!\n"
3711 "pld [%[output]]\n"
3712 : [count] "+r"(params_count_copy), [input] "+r"(input),
3713 [output] "+r"(output)
3714 : [range_offset] "r"(params.range_offset),
3715 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3716 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3717 "d11", "d12", "d13", "cc", "memory");
3718 }
3719
3720 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3721 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 7>::Transform(
3722 const uint8_t* input, const Dequantize& params, float* output) {
3723 #ifdef DEBUG
3724 #ifdef DEBUG_METAGEMM_VERBOSE
3725 std::cout << __FILE__ << "(" << __LINE__
3726 << ") Dequantize<uint8_t, float, Dequantize, 16, 7>::Transform()"
3727 << std::endl
3728 << std::flush;
3729 #endif
3730 #endif
3731 int params_count_copy = params.count;
3732 asm volatile(
3733
3734 // Dequantize::Prepare
3735 "vdup.32 q4, %[range_min]\n"
3736 "vdup.32 q5, %[range_offset]\n"
3737 "vdup.32 q6, %[range_scale]\n"
3738
3739 // Reduce count by leftovers.
3740 "subs %[count], %[count], #7\n"
3741 "beq 2f\n"
3742
3743 "1:"
3744 "subs %[count], %[count], #16\n"
3745
3746 // Dequantize::Transform
3747 "vld1.32 {d0, d1}, [%[input]]!\n"
3748 "pld [%[input], #32]\n"
3749 "vmovl.u8 q1, d1\n"
3750 "vmovl.u8 q0, d0\n"
3751 "vmovl.s16 q3, d3\n"
3752 "vmovl.s16 q2, d2\n"
3753 "vmovl.s16 q1, d1\n"
3754 "vmovl.s16 q0, d0\n"
3755 "vcvt.f32.s32 q0, q0\n"
3756 "vcvt.f32.s32 q1, q1\n"
3757 "vcvt.f32.s32 q2, q2\n"
3758 "vcvt.f32.s32 q3, q3\n"
3759 "vsub.f32 q0, q0, q5\n"
3760 "vsub.f32 q1, q1, q5\n"
3761 "vsub.f32 q2, q2, q5\n"
3762 "vsub.f32 q3, q3, q5\n"
3763 "vmul.f32 q0, q0, q6\n"
3764 "vmul.f32 q1, q1, q6\n"
3765 "vmul.f32 q2, q2, q6\n"
3766 "vmul.f32 q3, q3, q6\n"
3767 "vadd.f32 q0, q0, q4\n"
3768 "vadd.f32 q1, q1, q4\n"
3769 "vadd.f32 q2, q2, q4\n"
3770 "vadd.f32 q3, q3, q4\n"
3771
3772 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3773 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3774 "pld [%[output]]\n"
3775
3776 "bne 1b\n"
3777 "2:"
3778
3779 // Handle leftovers.
3780
3781 // Dequantize::Transform
3782 "vld1.32 {d0[0]}, [%[input]]!\n"
3783 "vld1.16 {d0[2]}, [%[input]]!\n"
3784 "vld1.8 {d0[6]}, [%[input]]!\n"
3785 "pld [%[input], #32]\n"
3786 "vmovl.u8 q0, d0\n"
3787 "vmovl.s16 q1, d1\n"
3788 "vmovl.s16 q0, d0\n"
3789 "vcvt.f32.s32 q0, q0\n"
3790 "vcvt.f32.s32 q1, q1\n"
3791 "vsub.f32 q0, q0, q5\n"
3792 "vsub.f32 q1, q1, q5\n"
3793 "vmul.f32 q0, q0, q6\n"
3794 "vmul.f32 q1, q1, q6\n"
3795 "vadd.f32 q0, q0, q4\n"
3796 "vadd.f32 q1, q1, q4\n"
3797
3798 "vst1.32 {d0, d1, d2}, [%[output]]!\n"
3799 "vst1.32 {d3[0]}, [%[output]]!\n"
3800 "pld [%[output]]\n"
3801 : [count] "+r"(params_count_copy), [input] "+r"(input),
3802 [output] "+r"(output)
3803 : [range_offset] "r"(params.range_offset),
3804 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3805 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3806 "d11", "d12", "d13", "cc", "memory");
3807 }
3808
3809 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3810 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 8>::Transform(
3811 const uint8_t* input, const Dequantize& params, float* output) {
3812 #ifdef DEBUG
3813 #ifdef DEBUG_METAGEMM_VERBOSE
3814 std::cout << __FILE__ << "(" << __LINE__
3815 << ") Dequantize<uint8_t, float, Dequantize, 16, 8>::Transform()"
3816 << std::endl
3817 << std::flush;
3818 #endif
3819 #endif
3820 int params_count_copy = params.count;
3821 asm volatile(
3822
3823 // Dequantize::Prepare
3824 "vdup.32 q4, %[range_min]\n"
3825 "vdup.32 q5, %[range_offset]\n"
3826 "vdup.32 q6, %[range_scale]\n"
3827
3828 // Reduce count by leftovers.
3829 "subs %[count], %[count], #8\n"
3830 "beq 2f\n"
3831
3832 "1:"
3833 "subs %[count], %[count], #16\n"
3834
3835 // Dequantize::Transform
3836 "vld1.32 {d0, d1}, [%[input]]!\n"
3837 "pld [%[input], #32]\n"
3838 "vmovl.u8 q1, d1\n"
3839 "vmovl.u8 q0, d0\n"
3840 "vmovl.s16 q3, d3\n"
3841 "vmovl.s16 q2, d2\n"
3842 "vmovl.s16 q1, d1\n"
3843 "vmovl.s16 q0, d0\n"
3844 "vcvt.f32.s32 q0, q0\n"
3845 "vcvt.f32.s32 q1, q1\n"
3846 "vcvt.f32.s32 q2, q2\n"
3847 "vcvt.f32.s32 q3, q3\n"
3848 "vsub.f32 q0, q0, q5\n"
3849 "vsub.f32 q1, q1, q5\n"
3850 "vsub.f32 q2, q2, q5\n"
3851 "vsub.f32 q3, q3, q5\n"
3852 "vmul.f32 q0, q0, q6\n"
3853 "vmul.f32 q1, q1, q6\n"
3854 "vmul.f32 q2, q2, q6\n"
3855 "vmul.f32 q3, q3, q6\n"
3856 "vadd.f32 q0, q0, q4\n"
3857 "vadd.f32 q1, q1, q4\n"
3858 "vadd.f32 q2, q2, q4\n"
3859 "vadd.f32 q3, q3, q4\n"
3860
3861 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3862 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3863 "pld [%[output]]\n"
3864
3865 "bne 1b\n"
3866 "2:"
3867
3868 // Handle leftovers.
3869
3870 // Dequantize::Transform
3871 "vld1.32 {d0}, [%[input]]!\n"
3872 "pld [%[input], #32]\n"
3873 "vmovl.u8 q0, d0\n"
3874 "vmovl.s16 q1, d1\n"
3875 "vmovl.s16 q0, d0\n"
3876 "vcvt.f32.s32 q0, q0\n"
3877 "vcvt.f32.s32 q1, q1\n"
3878 "vsub.f32 q0, q0, q5\n"
3879 "vsub.f32 q1, q1, q5\n"
3880 "vmul.f32 q0, q0, q6\n"
3881 "vmul.f32 q1, q1, q6\n"
3882 "vadd.f32 q0, q0, q4\n"
3883 "vadd.f32 q1, q1, q4\n"
3884
3885 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3886 "pld [%[output]]\n"
3887 : [count] "+r"(params_count_copy), [input] "+r"(input),
3888 [output] "+r"(output)
3889 : [range_offset] "r"(params.range_offset),
3890 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3891 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3892 "d11", "d12", "d13", "cc", "memory");
3893 }
3894
3895 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3896 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 9>::Transform(
3897 const uint8_t* input, const Dequantize& params, float* output) {
3898 #ifdef DEBUG
3899 #ifdef DEBUG_METAGEMM_VERBOSE
3900 std::cout << __FILE__ << "(" << __LINE__
3901 << ") Dequantize<uint8_t, float, Dequantize, 16, 9>::Transform()"
3902 << std::endl
3903 << std::flush;
3904 #endif
3905 #endif
3906 int params_count_copy = params.count;
3907 asm volatile(
3908
3909 // Dequantize::Prepare
3910 "vdup.32 q4, %[range_min]\n"
3911 "vdup.32 q5, %[range_offset]\n"
3912 "vdup.32 q6, %[range_scale]\n"
3913
3914 // Reduce count by leftovers.
3915 "subs %[count], %[count], #9\n"
3916 "beq 2f\n"
3917
3918 "1:"
3919 "subs %[count], %[count], #16\n"
3920
3921 // Dequantize::Transform
3922 "vld1.32 {d0, d1}, [%[input]]!\n"
3923 "pld [%[input], #32]\n"
3924 "vmovl.u8 q1, d1\n"
3925 "vmovl.u8 q0, d0\n"
3926 "vmovl.s16 q3, d3\n"
3927 "vmovl.s16 q2, d2\n"
3928 "vmovl.s16 q1, d1\n"
3929 "vmovl.s16 q0, d0\n"
3930 "vcvt.f32.s32 q0, q0\n"
3931 "vcvt.f32.s32 q1, q1\n"
3932 "vcvt.f32.s32 q2, q2\n"
3933 "vcvt.f32.s32 q3, q3\n"
3934 "vsub.f32 q0, q0, q5\n"
3935 "vsub.f32 q1, q1, q5\n"
3936 "vsub.f32 q2, q2, q5\n"
3937 "vsub.f32 q3, q3, q5\n"
3938 "vmul.f32 q0, q0, q6\n"
3939 "vmul.f32 q1, q1, q6\n"
3940 "vmul.f32 q2, q2, q6\n"
3941 "vmul.f32 q3, q3, q6\n"
3942 "vadd.f32 q0, q0, q4\n"
3943 "vadd.f32 q1, q1, q4\n"
3944 "vadd.f32 q2, q2, q4\n"
3945 "vadd.f32 q3, q3, q4\n"
3946
3947 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3948 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
3949 "pld [%[output]]\n"
3950
3951 "bne 1b\n"
3952 "2:"
3953
3954 // Handle leftovers.
3955
3956 // Dequantize::Transform
3957 "vld1.32 {d0}, [%[input]]!\n"
3958 "vld1.8 {d1[0]}, [%[input]]!\n"
3959 "pld [%[input], #32]\n"
3960 "vmovl.u8 q1, d1\n"
3961 "vmovl.u8 q0, d0\n"
3962 "vmovl.s16 q2, d2\n"
3963 "vmovl.s16 q1, d1\n"
3964 "vmovl.s16 q0, d0\n"
3965 "vcvt.f32.s32 q0, q0\n"
3966 "vcvt.f32.s32 q1, q1\n"
3967 "vcvt.f32.s32 q2, q2\n"
3968 "vsub.f32 q0, q0, q5\n"
3969 "vsub.f32 q1, q1, q5\n"
3970 "vsub.f32 q2, q2, q5\n"
3971 "vmul.f32 q0, q0, q6\n"
3972 "vmul.f32 q1, q1, q6\n"
3973 "vmul.f32 q2, q2, q6\n"
3974 "vadd.f32 q0, q0, q4\n"
3975 "vadd.f32 q1, q1, q4\n"
3976 "vadd.f32 q2, q2, q4\n"
3977
3978 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
3979 "vst1.32 {d4[0]}, [%[output]]!\n"
3980 "pld [%[output]]\n"
3981 : [count] "+r"(params_count_copy), [input] "+r"(input),
3982 [output] "+r"(output)
3983 : [range_offset] "r"(params.range_offset),
3984 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
3985 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
3986 "d11", "d12", "d13", "cc", "memory");
3987 }
3988
3989 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)3990 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 10>::Transform(
3991 const uint8_t* input, const Dequantize& params, float* output) {
3992 #ifdef DEBUG
3993 #ifdef DEBUG_METAGEMM_VERBOSE
3994 std::cout << __FILE__ << "(" << __LINE__
3995 << ") Dequantize<uint8_t, float, Dequantize, 16, 10>::Transform()"
3996 << std::endl
3997 << std::flush;
3998 #endif
3999 #endif
4000 int params_count_copy = params.count;
4001 asm volatile(
4002
4003 // Dequantize::Prepare
4004 "vdup.32 q4, %[range_min]\n"
4005 "vdup.32 q5, %[range_offset]\n"
4006 "vdup.32 q6, %[range_scale]\n"
4007
4008 // Reduce count by leftovers.
4009 "subs %[count], %[count], #10\n"
4010 "beq 2f\n"
4011
4012 "1:"
4013 "subs %[count], %[count], #16\n"
4014
4015 // Dequantize::Transform
4016 "vld1.32 {d0, d1}, [%[input]]!\n"
4017 "pld [%[input], #32]\n"
4018 "vmovl.u8 q1, d1\n"
4019 "vmovl.u8 q0, d0\n"
4020 "vmovl.s16 q3, d3\n"
4021 "vmovl.s16 q2, d2\n"
4022 "vmovl.s16 q1, d1\n"
4023 "vmovl.s16 q0, d0\n"
4024 "vcvt.f32.s32 q0, q0\n"
4025 "vcvt.f32.s32 q1, q1\n"
4026 "vcvt.f32.s32 q2, q2\n"
4027 "vcvt.f32.s32 q3, q3\n"
4028 "vsub.f32 q0, q0, q5\n"
4029 "vsub.f32 q1, q1, q5\n"
4030 "vsub.f32 q2, q2, q5\n"
4031 "vsub.f32 q3, q3, q5\n"
4032 "vmul.f32 q0, q0, q6\n"
4033 "vmul.f32 q1, q1, q6\n"
4034 "vmul.f32 q2, q2, q6\n"
4035 "vmul.f32 q3, q3, q6\n"
4036 "vadd.f32 q0, q0, q4\n"
4037 "vadd.f32 q1, q1, q4\n"
4038 "vadd.f32 q2, q2, q4\n"
4039 "vadd.f32 q3, q3, q4\n"
4040
4041 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4042 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
4043 "pld [%[output]]\n"
4044
4045 "bne 1b\n"
4046 "2:"
4047
4048 // Handle leftovers.
4049
4050 // Dequantize::Transform
4051 "vld1.32 {d0}, [%[input]]!\n"
4052 "vld1.16 {d1[0]}, [%[input]]!\n"
4053 "pld [%[input], #32]\n"
4054 "vmovl.u8 q1, d1\n"
4055 "vmovl.u8 q0, d0\n"
4056 "vmovl.s16 q2, d2\n"
4057 "vmovl.s16 q1, d1\n"
4058 "vmovl.s16 q0, d0\n"
4059 "vcvt.f32.s32 q0, q0\n"
4060 "vcvt.f32.s32 q1, q1\n"
4061 "vcvt.f32.s32 q2, q2\n"
4062 "vsub.f32 q0, q0, q5\n"
4063 "vsub.f32 q1, q1, q5\n"
4064 "vsub.f32 q2, q2, q5\n"
4065 "vmul.f32 q0, q0, q6\n"
4066 "vmul.f32 q1, q1, q6\n"
4067 "vmul.f32 q2, q2, q6\n"
4068 "vadd.f32 q0, q0, q4\n"
4069 "vadd.f32 q1, q1, q4\n"
4070 "vadd.f32 q2, q2, q4\n"
4071
4072 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4073 "vst1.32 {d4}, [%[output]]!\n"
4074 "pld [%[output]]\n"
4075 : [count] "+r"(params_count_copy), [input] "+r"(input),
4076 [output] "+r"(output)
4077 : [range_offset] "r"(params.range_offset),
4078 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
4079 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
4080 "d11", "d12", "d13", "cc", "memory");
4081 }
4082
4083 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)4084 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 11>::Transform(
4085 const uint8_t* input, const Dequantize& params, float* output) {
4086 #ifdef DEBUG
4087 #ifdef DEBUG_METAGEMM_VERBOSE
4088 std::cout << __FILE__ << "(" << __LINE__
4089 << ") Dequantize<uint8_t, float, Dequantize, 16, 11>::Transform()"
4090 << std::endl
4091 << std::flush;
4092 #endif
4093 #endif
4094 int params_count_copy = params.count;
4095 asm volatile(
4096
4097 // Dequantize::Prepare
4098 "vdup.32 q4, %[range_min]\n"
4099 "vdup.32 q5, %[range_offset]\n"
4100 "vdup.32 q6, %[range_scale]\n"
4101
4102 // Reduce count by leftovers.
4103 "subs %[count], %[count], #11\n"
4104 "beq 2f\n"
4105
4106 "1:"
4107 "subs %[count], %[count], #16\n"
4108
4109 // Dequantize::Transform
4110 "vld1.32 {d0, d1}, [%[input]]!\n"
4111 "pld [%[input], #32]\n"
4112 "vmovl.u8 q1, d1\n"
4113 "vmovl.u8 q0, d0\n"
4114 "vmovl.s16 q3, d3\n"
4115 "vmovl.s16 q2, d2\n"
4116 "vmovl.s16 q1, d1\n"
4117 "vmovl.s16 q0, d0\n"
4118 "vcvt.f32.s32 q0, q0\n"
4119 "vcvt.f32.s32 q1, q1\n"
4120 "vcvt.f32.s32 q2, q2\n"
4121 "vcvt.f32.s32 q3, q3\n"
4122 "vsub.f32 q0, q0, q5\n"
4123 "vsub.f32 q1, q1, q5\n"
4124 "vsub.f32 q2, q2, q5\n"
4125 "vsub.f32 q3, q3, q5\n"
4126 "vmul.f32 q0, q0, q6\n"
4127 "vmul.f32 q1, q1, q6\n"
4128 "vmul.f32 q2, q2, q6\n"
4129 "vmul.f32 q3, q3, q6\n"
4130 "vadd.f32 q0, q0, q4\n"
4131 "vadd.f32 q1, q1, q4\n"
4132 "vadd.f32 q2, q2, q4\n"
4133 "vadd.f32 q3, q3, q4\n"
4134
4135 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4136 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
4137 "pld [%[output]]\n"
4138
4139 "bne 1b\n"
4140 "2:"
4141
4142 // Handle leftovers.
4143
4144 // Dequantize::Transform
4145 "vld1.32 {d0}, [%[input]]!\n"
4146 "vld1.16 {d1[0]}, [%[input]]!\n"
4147 "vld1.8 {d1[2]}, [%[input]]!\n"
4148 "pld [%[input], #32]\n"
4149 "vmovl.u8 q1, d1\n"
4150 "vmovl.u8 q0, d0\n"
4151 "vmovl.s16 q2, d2\n"
4152 "vmovl.s16 q1, d1\n"
4153 "vmovl.s16 q0, d0\n"
4154 "vcvt.f32.s32 q0, q0\n"
4155 "vcvt.f32.s32 q1, q1\n"
4156 "vcvt.f32.s32 q2, q2\n"
4157 "vsub.f32 q0, q0, q5\n"
4158 "vsub.f32 q1, q1, q5\n"
4159 "vsub.f32 q2, q2, q5\n"
4160 "vmul.f32 q0, q0, q6\n"
4161 "vmul.f32 q1, q1, q6\n"
4162 "vmul.f32 q2, q2, q6\n"
4163 "vadd.f32 q0, q0, q4\n"
4164 "vadd.f32 q1, q1, q4\n"
4165 "vadd.f32 q2, q2, q4\n"
4166
4167 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4168 "vst1.32 {d4}, [%[output]]!\n"
4169 "vst1.32 {d5[0]}, [%[output]]!\n"
4170 "pld [%[output]]\n"
4171 : [count] "+r"(params_count_copy), [input] "+r"(input),
4172 [output] "+r"(output)
4173 : [range_offset] "r"(params.range_offset),
4174 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
4175 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
4176 "d11", "d12", "d13", "cc", "memory");
4177 }
4178
4179 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)4180 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 12>::Transform(
4181 const uint8_t* input, const Dequantize& params, float* output) {
4182 #ifdef DEBUG
4183 #ifdef DEBUG_METAGEMM_VERBOSE
4184 std::cout << __FILE__ << "(" << __LINE__
4185 << ") Dequantize<uint8_t, float, Dequantize, 16, 12>::Transform()"
4186 << std::endl
4187 << std::flush;
4188 #endif
4189 #endif
4190 int params_count_copy = params.count;
4191 asm volatile(
4192
4193 // Dequantize::Prepare
4194 "vdup.32 q4, %[range_min]\n"
4195 "vdup.32 q5, %[range_offset]\n"
4196 "vdup.32 q6, %[range_scale]\n"
4197
4198 // Reduce count by leftovers.
4199 "subs %[count], %[count], #12\n"
4200 "beq 2f\n"
4201
4202 "1:"
4203 "subs %[count], %[count], #16\n"
4204
4205 // Dequantize::Transform
4206 "vld1.32 {d0, d1}, [%[input]]!\n"
4207 "pld [%[input], #32]\n"
4208 "vmovl.u8 q1, d1\n"
4209 "vmovl.u8 q0, d0\n"
4210 "vmovl.s16 q3, d3\n"
4211 "vmovl.s16 q2, d2\n"
4212 "vmovl.s16 q1, d1\n"
4213 "vmovl.s16 q0, d0\n"
4214 "vcvt.f32.s32 q0, q0\n"
4215 "vcvt.f32.s32 q1, q1\n"
4216 "vcvt.f32.s32 q2, q2\n"
4217 "vcvt.f32.s32 q3, q3\n"
4218 "vsub.f32 q0, q0, q5\n"
4219 "vsub.f32 q1, q1, q5\n"
4220 "vsub.f32 q2, q2, q5\n"
4221 "vsub.f32 q3, q3, q5\n"
4222 "vmul.f32 q0, q0, q6\n"
4223 "vmul.f32 q1, q1, q6\n"
4224 "vmul.f32 q2, q2, q6\n"
4225 "vmul.f32 q3, q3, q6\n"
4226 "vadd.f32 q0, q0, q4\n"
4227 "vadd.f32 q1, q1, q4\n"
4228 "vadd.f32 q2, q2, q4\n"
4229 "vadd.f32 q3, q3, q4\n"
4230
4231 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4232 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
4233 "pld [%[output]]\n"
4234
4235 "bne 1b\n"
4236 "2:"
4237
4238 // Handle leftovers.
4239
4240 // Dequantize::Transform
4241 "vld1.32 {d0}, [%[input]]!\n"
4242 "vld1.32 {d1[0]}, [%[input]]!\n"
4243 "pld [%[input], #32]\n"
4244 "vmovl.u8 q1, d1\n"
4245 "vmovl.u8 q0, d0\n"
4246 "vmovl.s16 q2, d2\n"
4247 "vmovl.s16 q1, d1\n"
4248 "vmovl.s16 q0, d0\n"
4249 "vcvt.f32.s32 q0, q0\n"
4250 "vcvt.f32.s32 q1, q1\n"
4251 "vcvt.f32.s32 q2, q2\n"
4252 "vsub.f32 q0, q0, q5\n"
4253 "vsub.f32 q1, q1, q5\n"
4254 "vsub.f32 q2, q2, q5\n"
4255 "vmul.f32 q0, q0, q6\n"
4256 "vmul.f32 q1, q1, q6\n"
4257 "vmul.f32 q2, q2, q6\n"
4258 "vadd.f32 q0, q0, q4\n"
4259 "vadd.f32 q1, q1, q4\n"
4260 "vadd.f32 q2, q2, q4\n"
4261
4262 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4263 "vst1.32 {d4, d5}, [%[output]]!\n"
4264 "pld [%[output]]\n"
4265 : [count] "+r"(params_count_copy), [input] "+r"(input),
4266 [output] "+r"(output)
4267 : [range_offset] "r"(params.range_offset),
4268 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
4269 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
4270 "d11", "d12", "d13", "cc", "memory");
4271 }
4272
4273 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)4274 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 13>::Transform(
4275 const uint8_t* input, const Dequantize& params, float* output) {
4276 #ifdef DEBUG
4277 #ifdef DEBUG_METAGEMM_VERBOSE
4278 std::cout << __FILE__ << "(" << __LINE__
4279 << ") Dequantize<uint8_t, float, Dequantize, 16, 13>::Transform()"
4280 << std::endl
4281 << std::flush;
4282 #endif
4283 #endif
4284 int params_count_copy = params.count;
4285 asm volatile(
4286
4287 // Dequantize::Prepare
4288 "vdup.32 q4, %[range_min]\n"
4289 "vdup.32 q5, %[range_offset]\n"
4290 "vdup.32 q6, %[range_scale]\n"
4291
4292 // Reduce count by leftovers.
4293 "subs %[count], %[count], #13\n"
4294 "beq 2f\n"
4295
4296 "1:"
4297 "subs %[count], %[count], #16\n"
4298
4299 // Dequantize::Transform
4300 "vld1.32 {d0, d1}, [%[input]]!\n"
4301 "pld [%[input], #32]\n"
4302 "vmovl.u8 q1, d1\n"
4303 "vmovl.u8 q0, d0\n"
4304 "vmovl.s16 q3, d3\n"
4305 "vmovl.s16 q2, d2\n"
4306 "vmovl.s16 q1, d1\n"
4307 "vmovl.s16 q0, d0\n"
4308 "vcvt.f32.s32 q0, q0\n"
4309 "vcvt.f32.s32 q1, q1\n"
4310 "vcvt.f32.s32 q2, q2\n"
4311 "vcvt.f32.s32 q3, q3\n"
4312 "vsub.f32 q0, q0, q5\n"
4313 "vsub.f32 q1, q1, q5\n"
4314 "vsub.f32 q2, q2, q5\n"
4315 "vsub.f32 q3, q3, q5\n"
4316 "vmul.f32 q0, q0, q6\n"
4317 "vmul.f32 q1, q1, q6\n"
4318 "vmul.f32 q2, q2, q6\n"
4319 "vmul.f32 q3, q3, q6\n"
4320 "vadd.f32 q0, q0, q4\n"
4321 "vadd.f32 q1, q1, q4\n"
4322 "vadd.f32 q2, q2, q4\n"
4323 "vadd.f32 q3, q3, q4\n"
4324
4325 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4326 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
4327 "pld [%[output]]\n"
4328
4329 "bne 1b\n"
4330 "2:"
4331
4332 // Handle leftovers.
4333
4334 // Dequantize::Transform
4335 "vld1.32 {d0}, [%[input]]!\n"
4336 "vld1.32 {d1[0]}, [%[input]]!\n"
4337 "vld1.8 {d1[4]}, [%[input]]!\n"
4338 "pld [%[input], #32]\n"
4339 "vmovl.u8 q1, d1\n"
4340 "vmovl.u8 q0, d0\n"
4341 "vmovl.s16 q3, d3\n"
4342 "vmovl.s16 q2, d2\n"
4343 "vmovl.s16 q1, d1\n"
4344 "vmovl.s16 q0, d0\n"
4345 "vcvt.f32.s32 q0, q0\n"
4346 "vcvt.f32.s32 q1, q1\n"
4347 "vcvt.f32.s32 q2, q2\n"
4348 "vcvt.f32.s32 q3, q3\n"
4349 "vsub.f32 q0, q0, q5\n"
4350 "vsub.f32 q1, q1, q5\n"
4351 "vsub.f32 q2, q2, q5\n"
4352 "vsub.f32 q3, q3, q5\n"
4353 "vmul.f32 q0, q0, q6\n"
4354 "vmul.f32 q1, q1, q6\n"
4355 "vmul.f32 q2, q2, q6\n"
4356 "vmul.f32 q3, q3, q6\n"
4357 "vadd.f32 q0, q0, q4\n"
4358 "vadd.f32 q1, q1, q4\n"
4359 "vadd.f32 q2, q2, q4\n"
4360 "vadd.f32 q3, q3, q4\n"
4361
4362 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4363 "vst1.32 {d4, d5}, [%[output]]!\n"
4364 "vst1.32 {d6[0]}, [%[output]]!\n"
4365 "pld [%[output]]\n"
4366 : [count] "+r"(params_count_copy), [input] "+r"(input),
4367 [output] "+r"(output)
4368 : [range_offset] "r"(params.range_offset),
4369 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
4370 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
4371 "d11", "d12", "d13", "cc", "memory");
4372 }
4373
4374 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)4375 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 14>::Transform(
4376 const uint8_t* input, const Dequantize& params, float* output) {
4377 #ifdef DEBUG
4378 #ifdef DEBUG_METAGEMM_VERBOSE
4379 std::cout << __FILE__ << "(" << __LINE__
4380 << ") Dequantize<uint8_t, float, Dequantize, 16, 14>::Transform()"
4381 << std::endl
4382 << std::flush;
4383 #endif
4384 #endif
4385 int params_count_copy = params.count;
4386 asm volatile(
4387
4388 // Dequantize::Prepare
4389 "vdup.32 q4, %[range_min]\n"
4390 "vdup.32 q5, %[range_offset]\n"
4391 "vdup.32 q6, %[range_scale]\n"
4392
4393 // Reduce count by leftovers.
4394 "subs %[count], %[count], #14\n"
4395 "beq 2f\n"
4396
4397 "1:"
4398 "subs %[count], %[count], #16\n"
4399
4400 // Dequantize::Transform
4401 "vld1.32 {d0, d1}, [%[input]]!\n"
4402 "pld [%[input], #32]\n"
4403 "vmovl.u8 q1, d1\n"
4404 "vmovl.u8 q0, d0\n"
4405 "vmovl.s16 q3, d3\n"
4406 "vmovl.s16 q2, d2\n"
4407 "vmovl.s16 q1, d1\n"
4408 "vmovl.s16 q0, d0\n"
4409 "vcvt.f32.s32 q0, q0\n"
4410 "vcvt.f32.s32 q1, q1\n"
4411 "vcvt.f32.s32 q2, q2\n"
4412 "vcvt.f32.s32 q3, q3\n"
4413 "vsub.f32 q0, q0, q5\n"
4414 "vsub.f32 q1, q1, q5\n"
4415 "vsub.f32 q2, q2, q5\n"
4416 "vsub.f32 q3, q3, q5\n"
4417 "vmul.f32 q0, q0, q6\n"
4418 "vmul.f32 q1, q1, q6\n"
4419 "vmul.f32 q2, q2, q6\n"
4420 "vmul.f32 q3, q3, q6\n"
4421 "vadd.f32 q0, q0, q4\n"
4422 "vadd.f32 q1, q1, q4\n"
4423 "vadd.f32 q2, q2, q4\n"
4424 "vadd.f32 q3, q3, q4\n"
4425
4426 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4427 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
4428 "pld [%[output]]\n"
4429
4430 "bne 1b\n"
4431 "2:"
4432
4433 // Handle leftovers.
4434
4435 // Dequantize::Transform
4436 "vld1.32 {d0}, [%[input]]!\n"
4437 "vld1.32 {d1[0]}, [%[input]]!\n"
4438 "vld1.16 {d1[2]}, [%[input]]!\n"
4439 "pld [%[input], #32]\n"
4440 "vmovl.u8 q1, d1\n"
4441 "vmovl.u8 q0, d0\n"
4442 "vmovl.s16 q3, d3\n"
4443 "vmovl.s16 q2, d2\n"
4444 "vmovl.s16 q1, d1\n"
4445 "vmovl.s16 q0, d0\n"
4446 "vcvt.f32.s32 q0, q0\n"
4447 "vcvt.f32.s32 q1, q1\n"
4448 "vcvt.f32.s32 q2, q2\n"
4449 "vcvt.f32.s32 q3, q3\n"
4450 "vsub.f32 q0, q0, q5\n"
4451 "vsub.f32 q1, q1, q5\n"
4452 "vsub.f32 q2, q2, q5\n"
4453 "vsub.f32 q3, q3, q5\n"
4454 "vmul.f32 q0, q0, q6\n"
4455 "vmul.f32 q1, q1, q6\n"
4456 "vmul.f32 q2, q2, q6\n"
4457 "vmul.f32 q3, q3, q6\n"
4458 "vadd.f32 q0, q0, q4\n"
4459 "vadd.f32 q1, q1, q4\n"
4460 "vadd.f32 q2, q2, q4\n"
4461 "vadd.f32 q3, q3, q4\n"
4462
4463 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4464 "vst1.32 {d4, d5, d6}, [%[output]]!\n"
4465 "pld [%[output]]\n"
4466 : [count] "+r"(params_count_copy), [input] "+r"(input),
4467 [output] "+r"(output)
4468 : [range_offset] "r"(params.range_offset),
4469 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
4470 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
4471 "d11", "d12", "d13", "cc", "memory");
4472 }
4473
4474 template <>
Transform(const uint8_t * input,const Dequantize & params,float * output)4475 inline void Transform1DKernel<uint8_t, float, Dequantize, 16, 15>::Transform(
4476 const uint8_t* input, const Dequantize& params, float* output) {
4477 #ifdef DEBUG
4478 #ifdef DEBUG_METAGEMM_VERBOSE
4479 std::cout << __FILE__ << "(" << __LINE__
4480 << ") Dequantize<uint8_t, float, Dequantize, 16, 15>::Transform()"
4481 << std::endl
4482 << std::flush;
4483 #endif
4484 #endif
4485 int params_count_copy = params.count;
4486 asm volatile(
4487
4488 // Dequantize::Prepare
4489 "vdup.32 q4, %[range_min]\n"
4490 "vdup.32 q5, %[range_offset]\n"
4491 "vdup.32 q6, %[range_scale]\n"
4492
4493 // Reduce count by leftovers.
4494 "subs %[count], %[count], #15\n"
4495 "beq 2f\n"
4496
4497 "1:"
4498 "subs %[count], %[count], #16\n"
4499
4500 // Dequantize::Transform
4501 "vld1.32 {d0, d1}, [%[input]]!\n"
4502 "pld [%[input], #32]\n"
4503 "vmovl.u8 q1, d1\n"
4504 "vmovl.u8 q0, d0\n"
4505 "vmovl.s16 q3, d3\n"
4506 "vmovl.s16 q2, d2\n"
4507 "vmovl.s16 q1, d1\n"
4508 "vmovl.s16 q0, d0\n"
4509 "vcvt.f32.s32 q0, q0\n"
4510 "vcvt.f32.s32 q1, q1\n"
4511 "vcvt.f32.s32 q2, q2\n"
4512 "vcvt.f32.s32 q3, q3\n"
4513 "vsub.f32 q0, q0, q5\n"
4514 "vsub.f32 q1, q1, q5\n"
4515 "vsub.f32 q2, q2, q5\n"
4516 "vsub.f32 q3, q3, q5\n"
4517 "vmul.f32 q0, q0, q6\n"
4518 "vmul.f32 q1, q1, q6\n"
4519 "vmul.f32 q2, q2, q6\n"
4520 "vmul.f32 q3, q3, q6\n"
4521 "vadd.f32 q0, q0, q4\n"
4522 "vadd.f32 q1, q1, q4\n"
4523 "vadd.f32 q2, q2, q4\n"
4524 "vadd.f32 q3, q3, q4\n"
4525
4526 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4527 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
4528 "pld [%[output]]\n"
4529
4530 "bne 1b\n"
4531 "2:"
4532
4533 // Handle leftovers.
4534
4535 // Dequantize::Transform
4536 "vld1.32 {d0}, [%[input]]!\n"
4537 "vld1.32 {d1[0]}, [%[input]]!\n"
4538 "vld1.16 {d1[2]}, [%[input]]!\n"
4539 "vld1.8 {d1[6]}, [%[input]]!\n"
4540 "pld [%[input], #32]\n"
4541 "vmovl.u8 q1, d1\n"
4542 "vmovl.u8 q0, d0\n"
4543 "vmovl.s16 q3, d3\n"
4544 "vmovl.s16 q2, d2\n"
4545 "vmovl.s16 q1, d1\n"
4546 "vmovl.s16 q0, d0\n"
4547 "vcvt.f32.s32 q0, q0\n"
4548 "vcvt.f32.s32 q1, q1\n"
4549 "vcvt.f32.s32 q2, q2\n"
4550 "vcvt.f32.s32 q3, q3\n"
4551 "vsub.f32 q0, q0, q5\n"
4552 "vsub.f32 q1, q1, q5\n"
4553 "vsub.f32 q2, q2, q5\n"
4554 "vsub.f32 q3, q3, q5\n"
4555 "vmul.f32 q0, q0, q6\n"
4556 "vmul.f32 q1, q1, q6\n"
4557 "vmul.f32 q2, q2, q6\n"
4558 "vmul.f32 q3, q3, q6\n"
4559 "vadd.f32 q0, q0, q4\n"
4560 "vadd.f32 q1, q1, q4\n"
4561 "vadd.f32 q2, q2, q4\n"
4562 "vadd.f32 q3, q3, q4\n"
4563
4564 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
4565 "vst1.32 {d4, d5, d6}, [%[output]]!\n"
4566 "vst1.32 {d7[0]}, [%[output]]!\n"
4567 "pld [%[output]]\n"
4568 : [count] "+r"(params_count_copy), [input] "+r"(input),
4569 [output] "+r"(output)
4570 : [range_offset] "r"(params.range_offset),
4571 [range_scale] "r"(params.range_scale), [range_min] "r"(params.range_min)
4572 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10",
4573 "d11", "d12", "d13", "cc", "memory");
4574 }
4575
4576 template <>
4577 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4578 0>::Transform(const uint8_t* input,
4579 const MinMax<uint8_t>& params,
4580 uint8_t* output) {
4581 #ifdef DEBUG
4582 #ifdef DEBUG_METAGEMM_VERBOSE
4583 std::cout << __FILE__ << "(" << __LINE__
4584 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4585 "0>::Transform()"
4586 << std::endl
4587 << std::flush;
4588 #endif
4589 #endif
4590 int params_count_copy = params.count;
4591 asm volatile(
4592
4593 // MinMax::Prepare
4594 "vdup.8 q4, %[min]\n"
4595 "vdup.8 q5, %[max]\n"
4596
4597 "1:"
4598 "subs %[count], %[count], #16\n"
4599
4600 // MinMax::Transform
4601 "vld1.32 {d0, d1}, [%[input]]!\n"
4602 "pld [%[input], #16]\n"
4603 "vmax.u8 q0, q0, q4\n"
4604 "vmin.u8 q0, q0, q5\n"
4605
4606 "vst1.32 {d0, d1}, [%[output]]!\n"
4607 "pld [%[output]]\n"
4608
4609 "bne 1b\n"
4610 : [count] "+r"(params_count_copy), [input] "+r"(input),
4611 [output] "+r"(output)
4612 : [max] "r"(params.max), [min] "r"(params.min)
4613 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
4614 }
4615
4616 template <>
4617 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4618 1>::Transform(const uint8_t* input,
4619 const MinMax<uint8_t>& params,
4620 uint8_t* output) {
4621 #ifdef DEBUG
4622 #ifdef DEBUG_METAGEMM_VERBOSE
4623 std::cout << __FILE__ << "(" << __LINE__
4624 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4625 "1>::Transform()"
4626 << std::endl
4627 << std::flush;
4628 #endif
4629 #endif
4630 int params_count_copy = params.count;
4631 asm volatile(
4632
4633 // MinMax::Prepare
4634 "vdup.8 q4, %[min]\n"
4635 "vdup.8 q5, %[max]\n"
4636
4637 // Reduce count by leftovers.
4638 "subs %[count], %[count], #1\n"
4639 "beq 2f\n"
4640
4641 "1:"
4642 "subs %[count], %[count], #16\n"
4643
4644 // MinMax::Transform
4645 "vld1.32 {d0, d1}, [%[input]]!\n"
4646 "pld [%[input], #16]\n"
4647 "vmax.u8 q0, q0, q4\n"
4648 "vmin.u8 q0, q0, q5\n"
4649
4650 "vst1.32 {d0, d1}, [%[output]]!\n"
4651 "pld [%[output]]\n"
4652
4653 "bne 1b\n"
4654 "2:"
4655
4656 // Handle leftovers.
4657
4658 // MinMax::Transform
4659 "vld1.8 {d0[0]}, [%[input]]!\n"
4660 "pld [%[input], #16]\n"
4661 "vmax.u8 q0, q0, q4\n"
4662 "vmin.u8 q0, q0, q5\n"
4663
4664 "vst1.8 {d0[0]}, [%[output]]!\n"
4665 "pld [%[output]]\n"
4666 : [count] "+r"(params_count_copy), [input] "+r"(input),
4667 [output] "+r"(output)
4668 : [max] "r"(params.max), [min] "r"(params.min)
4669 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
4670 }
4671
4672 template <>
4673 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4674 2>::Transform(const uint8_t* input,
4675 const MinMax<uint8_t>& params,
4676 uint8_t* output) {
4677 #ifdef DEBUG
4678 #ifdef DEBUG_METAGEMM_VERBOSE
4679 std::cout << __FILE__ << "(" << __LINE__
4680 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4681 "2>::Transform()"
4682 << std::endl
4683 << std::flush;
4684 #endif
4685 #endif
4686 int params_count_copy = params.count;
4687 asm volatile(
4688
4689 // MinMax::Prepare
4690 "vdup.8 q4, %[min]\n"
4691 "vdup.8 q5, %[max]\n"
4692
4693 // Reduce count by leftovers.
4694 "subs %[count], %[count], #2\n"
4695 "beq 2f\n"
4696
4697 "1:"
4698 "subs %[count], %[count], #16\n"
4699
4700 // MinMax::Transform
4701 "vld1.32 {d0, d1}, [%[input]]!\n"
4702 "pld [%[input], #16]\n"
4703 "vmax.u8 q0, q0, q4\n"
4704 "vmin.u8 q0, q0, q5\n"
4705
4706 "vst1.32 {d0, d1}, [%[output]]!\n"
4707 "pld [%[output]]\n"
4708
4709 "bne 1b\n"
4710 "2:"
4711
4712 // Handle leftovers.
4713
4714 // MinMax::Transform
4715 "vld1.16 {d0[0]}, [%[input]]!\n"
4716 "pld [%[input], #16]\n"
4717 "vmax.u8 q0, q0, q4\n"
4718 "vmin.u8 q0, q0, q5\n"
4719
4720 "vst1.16 {d0[0]}, [%[output]]!\n"
4721 "pld [%[output]]\n"
4722 : [count] "+r"(params_count_copy), [input] "+r"(input),
4723 [output] "+r"(output)
4724 : [max] "r"(params.max), [min] "r"(params.min)
4725 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
4726 }
4727
4728 template <>
4729 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4730 3>::Transform(const uint8_t* input,
4731 const MinMax<uint8_t>& params,
4732 uint8_t* output) {
4733 #ifdef DEBUG
4734 #ifdef DEBUG_METAGEMM_VERBOSE
4735 std::cout << __FILE__ << "(" << __LINE__
4736 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4737 "3>::Transform()"
4738 << std::endl
4739 << std::flush;
4740 #endif
4741 #endif
4742 int params_count_copy = params.count;
4743 asm volatile(
4744
4745 // MinMax::Prepare
4746 "vdup.8 q4, %[min]\n"
4747 "vdup.8 q5, %[max]\n"
4748
4749 // Reduce count by leftovers.
4750 "subs %[count], %[count], #3\n"
4751 "beq 2f\n"
4752
4753 "1:"
4754 "subs %[count], %[count], #16\n"
4755
4756 // MinMax::Transform
4757 "vld1.32 {d0, d1}, [%[input]]!\n"
4758 "pld [%[input], #16]\n"
4759 "vmax.u8 q0, q0, q4\n"
4760 "vmin.u8 q0, q0, q5\n"
4761
4762 "vst1.32 {d0, d1}, [%[output]]!\n"
4763 "pld [%[output]]\n"
4764
4765 "bne 1b\n"
4766 "2:"
4767
4768 // Handle leftovers.
4769
4770 // MinMax::Transform
4771 "vld1.16 {d0[0]}, [%[input]]!\n"
4772 "vld1.8 {d0[2]}, [%[input]]!\n"
4773 "pld [%[input], #16]\n"
4774 "vmax.u8 q0, q0, q4\n"
4775 "vmin.u8 q0, q0, q5\n"
4776
4777 "vst1.16 {d0[0]}, [%[output]]!\n"
4778 "vst1.8 {d0[2]}, [%[output]]!\n"
4779 "pld [%[output]]\n"
4780 : [count] "+r"(params_count_copy), [input] "+r"(input),
4781 [output] "+r"(output)
4782 : [max] "r"(params.max), [min] "r"(params.min)
4783 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
4784 }
4785
4786 template <>
4787 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4788 4>::Transform(const uint8_t* input,
4789 const MinMax<uint8_t>& params,
4790 uint8_t* output) {
4791 #ifdef DEBUG
4792 #ifdef DEBUG_METAGEMM_VERBOSE
4793 std::cout << __FILE__ << "(" << __LINE__
4794 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4795 "4>::Transform()"
4796 << std::endl
4797 << std::flush;
4798 #endif
4799 #endif
4800 int params_count_copy = params.count;
4801 asm volatile(
4802
4803 // MinMax::Prepare
4804 "vdup.8 q4, %[min]\n"
4805 "vdup.8 q5, %[max]\n"
4806
4807 // Reduce count by leftovers.
4808 "subs %[count], %[count], #4\n"
4809 "beq 2f\n"
4810
4811 "1:"
4812 "subs %[count], %[count], #16\n"
4813
4814 // MinMax::Transform
4815 "vld1.32 {d0, d1}, [%[input]]!\n"
4816 "pld [%[input], #16]\n"
4817 "vmax.u8 q0, q0, q4\n"
4818 "vmin.u8 q0, q0, q5\n"
4819
4820 "vst1.32 {d0, d1}, [%[output]]!\n"
4821 "pld [%[output]]\n"
4822
4823 "bne 1b\n"
4824 "2:"
4825
4826 // Handle leftovers.
4827
4828 // MinMax::Transform
4829 "vld1.32 {d0[0]}, [%[input]]!\n"
4830 "pld [%[input], #16]\n"
4831 "vmax.u8 q0, q0, q4\n"
4832 "vmin.u8 q0, q0, q5\n"
4833
4834 "vst1.32 {d0[0]}, [%[output]]!\n"
4835 "pld [%[output]]\n"
4836 : [count] "+r"(params_count_copy), [input] "+r"(input),
4837 [output] "+r"(output)
4838 : [max] "r"(params.max), [min] "r"(params.min)
4839 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
4840 }
4841
4842 template <>
4843 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4844 5>::Transform(const uint8_t* input,
4845 const MinMax<uint8_t>& params,
4846 uint8_t* output) {
4847 #ifdef DEBUG
4848 #ifdef DEBUG_METAGEMM_VERBOSE
4849 std::cout << __FILE__ << "(" << __LINE__
4850 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4851 "5>::Transform()"
4852 << std::endl
4853 << std::flush;
4854 #endif
4855 #endif
4856 int params_count_copy = params.count;
4857 asm volatile(
4858
4859 // MinMax::Prepare
4860 "vdup.8 q4, %[min]\n"
4861 "vdup.8 q5, %[max]\n"
4862
4863 // Reduce count by leftovers.
4864 "subs %[count], %[count], #5\n"
4865 "beq 2f\n"
4866
4867 "1:"
4868 "subs %[count], %[count], #16\n"
4869
4870 // MinMax::Transform
4871 "vld1.32 {d0, d1}, [%[input]]!\n"
4872 "pld [%[input], #16]\n"
4873 "vmax.u8 q0, q0, q4\n"
4874 "vmin.u8 q0, q0, q5\n"
4875
4876 "vst1.32 {d0, d1}, [%[output]]!\n"
4877 "pld [%[output]]\n"
4878
4879 "bne 1b\n"
4880 "2:"
4881
4882 // Handle leftovers.
4883
4884 // MinMax::Transform
4885 "vld1.32 {d0[0]}, [%[input]]!\n"
4886 "vld1.8 {d0[4]}, [%[input]]!\n"
4887 "pld [%[input], #16]\n"
4888 "vmax.u8 q0, q0, q4\n"
4889 "vmin.u8 q0, q0, q5\n"
4890
4891 "vst1.32 {d0[0]}, [%[output]]!\n"
4892 "vst1.8 {d0[4]}, [%[output]]!\n"
4893 "pld [%[output]]\n"
4894 : [count] "+r"(params_count_copy), [input] "+r"(input),
4895 [output] "+r"(output)
4896 : [max] "r"(params.max), [min] "r"(params.min)
4897 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
4898 }
4899
4900 template <>
4901 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4902 6>::Transform(const uint8_t* input,
4903 const MinMax<uint8_t>& params,
4904 uint8_t* output) {
4905 #ifdef DEBUG
4906 #ifdef DEBUG_METAGEMM_VERBOSE
4907 std::cout << __FILE__ << "(" << __LINE__
4908 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4909 "6>::Transform()"
4910 << std::endl
4911 << std::flush;
4912 #endif
4913 #endif
4914 int params_count_copy = params.count;
4915 asm volatile(
4916
4917 // MinMax::Prepare
4918 "vdup.8 q4, %[min]\n"
4919 "vdup.8 q5, %[max]\n"
4920
4921 // Reduce count by leftovers.
4922 "subs %[count], %[count], #6\n"
4923 "beq 2f\n"
4924
4925 "1:"
4926 "subs %[count], %[count], #16\n"
4927
4928 // MinMax::Transform
4929 "vld1.32 {d0, d1}, [%[input]]!\n"
4930 "pld [%[input], #16]\n"
4931 "vmax.u8 q0, q0, q4\n"
4932 "vmin.u8 q0, q0, q5\n"
4933
4934 "vst1.32 {d0, d1}, [%[output]]!\n"
4935 "pld [%[output]]\n"
4936
4937 "bne 1b\n"
4938 "2:"
4939
4940 // Handle leftovers.
4941
4942 // MinMax::Transform
4943 "vld1.32 {d0[0]}, [%[input]]!\n"
4944 "vld1.16 {d0[2]}, [%[input]]!\n"
4945 "pld [%[input], #16]\n"
4946 "vmax.u8 q0, q0, q4\n"
4947 "vmin.u8 q0, q0, q5\n"
4948
4949 "vst1.32 {d0[0]}, [%[output]]!\n"
4950 "vst1.16 {d0[2]}, [%[output]]!\n"
4951 "pld [%[output]]\n"
4952 : [count] "+r"(params_count_copy), [input] "+r"(input),
4953 [output] "+r"(output)
4954 : [max] "r"(params.max), [min] "r"(params.min)
4955 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
4956 }
4957
4958 template <>
4959 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)4960 7>::Transform(const uint8_t* input,
4961 const MinMax<uint8_t>& params,
4962 uint8_t* output) {
4963 #ifdef DEBUG
4964 #ifdef DEBUG_METAGEMM_VERBOSE
4965 std::cout << __FILE__ << "(" << __LINE__
4966 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
4967 "7>::Transform()"
4968 << std::endl
4969 << std::flush;
4970 #endif
4971 #endif
4972 int params_count_copy = params.count;
4973 asm volatile(
4974
4975 // MinMax::Prepare
4976 "vdup.8 q4, %[min]\n"
4977 "vdup.8 q5, %[max]\n"
4978
4979 // Reduce count by leftovers.
4980 "subs %[count], %[count], #7\n"
4981 "beq 2f\n"
4982
4983 "1:"
4984 "subs %[count], %[count], #16\n"
4985
4986 // MinMax::Transform
4987 "vld1.32 {d0, d1}, [%[input]]!\n"
4988 "pld [%[input], #16]\n"
4989 "vmax.u8 q0, q0, q4\n"
4990 "vmin.u8 q0, q0, q5\n"
4991
4992 "vst1.32 {d0, d1}, [%[output]]!\n"
4993 "pld [%[output]]\n"
4994
4995 "bne 1b\n"
4996 "2:"
4997
4998 // Handle leftovers.
4999
5000 // MinMax::Transform
5001 "vld1.32 {d0[0]}, [%[input]]!\n"
5002 "vld1.16 {d0[2]}, [%[input]]!\n"
5003 "vld1.8 {d0[6]}, [%[input]]!\n"
5004 "pld [%[input], #16]\n"
5005 "vmax.u8 q0, q0, q4\n"
5006 "vmin.u8 q0, q0, q5\n"
5007
5008 "vst1.32 {d0[0]}, [%[output]]!\n"
5009 "vst1.16 {d0[2]}, [%[output]]!\n"
5010 "vst1.8 {d0[6]}, [%[output]]!\n"
5011 "pld [%[output]]\n"
5012 : [count] "+r"(params_count_copy), [input] "+r"(input),
5013 [output] "+r"(output)
5014 : [max] "r"(params.max), [min] "r"(params.min)
5015 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5016 }
5017
5018 template <>
5019 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5020 8>::Transform(const uint8_t* input,
5021 const MinMax<uint8_t>& params,
5022 uint8_t* output) {
5023 #ifdef DEBUG
5024 #ifdef DEBUG_METAGEMM_VERBOSE
5025 std::cout << __FILE__ << "(" << __LINE__
5026 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5027 "8>::Transform()"
5028 << std::endl
5029 << std::flush;
5030 #endif
5031 #endif
5032 int params_count_copy = params.count;
5033 asm volatile(
5034
5035 // MinMax::Prepare
5036 "vdup.8 q4, %[min]\n"
5037 "vdup.8 q5, %[max]\n"
5038
5039 // Reduce count by leftovers.
5040 "subs %[count], %[count], #8\n"
5041 "beq 2f\n"
5042
5043 "1:"
5044 "subs %[count], %[count], #16\n"
5045
5046 // MinMax::Transform
5047 "vld1.32 {d0, d1}, [%[input]]!\n"
5048 "pld [%[input], #16]\n"
5049 "vmax.u8 q0, q0, q4\n"
5050 "vmin.u8 q0, q0, q5\n"
5051
5052 "vst1.32 {d0, d1}, [%[output]]!\n"
5053 "pld [%[output]]\n"
5054
5055 "bne 1b\n"
5056 "2:"
5057
5058 // Handle leftovers.
5059
5060 // MinMax::Transform
5061 "vld1.32 {d0}, [%[input]]!\n"
5062 "pld [%[input], #16]\n"
5063 "vmax.u8 q0, q0, q4\n"
5064 "vmin.u8 q0, q0, q5\n"
5065
5066 "vst1.32 {d0}, [%[output]]!\n"
5067 "pld [%[output]]\n"
5068 : [count] "+r"(params_count_copy), [input] "+r"(input),
5069 [output] "+r"(output)
5070 : [max] "r"(params.max), [min] "r"(params.min)
5071 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5072 }
5073
5074 template <>
5075 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5076 9>::Transform(const uint8_t* input,
5077 const MinMax<uint8_t>& params,
5078 uint8_t* output) {
5079 #ifdef DEBUG
5080 #ifdef DEBUG_METAGEMM_VERBOSE
5081 std::cout << __FILE__ << "(" << __LINE__
5082 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5083 "9>::Transform()"
5084 << std::endl
5085 << std::flush;
5086 #endif
5087 #endif
5088 int params_count_copy = params.count;
5089 asm volatile(
5090
5091 // MinMax::Prepare
5092 "vdup.8 q4, %[min]\n"
5093 "vdup.8 q5, %[max]\n"
5094
5095 // Reduce count by leftovers.
5096 "subs %[count], %[count], #9\n"
5097 "beq 2f\n"
5098
5099 "1:"
5100 "subs %[count], %[count], #16\n"
5101
5102 // MinMax::Transform
5103 "vld1.32 {d0, d1}, [%[input]]!\n"
5104 "pld [%[input], #16]\n"
5105 "vmax.u8 q0, q0, q4\n"
5106 "vmin.u8 q0, q0, q5\n"
5107
5108 "vst1.32 {d0, d1}, [%[output]]!\n"
5109 "pld [%[output]]\n"
5110
5111 "bne 1b\n"
5112 "2:"
5113
5114 // Handle leftovers.
5115
5116 // MinMax::Transform
5117 "vld1.32 {d0}, [%[input]]!\n"
5118 "vld1.8 {d1[0]}, [%[input]]!\n"
5119 "pld [%[input], #16]\n"
5120 "vmax.u8 q0, q0, q4\n"
5121 "vmin.u8 q0, q0, q5\n"
5122
5123 "vst1.32 {d0}, [%[output]]!\n"
5124 "vst1.8 {d1[0]}, [%[output]]!\n"
5125 "pld [%[output]]\n"
5126 : [count] "+r"(params_count_copy), [input] "+r"(input),
5127 [output] "+r"(output)
5128 : [max] "r"(params.max), [min] "r"(params.min)
5129 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5130 }
5131
5132 template <>
5133 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5134 10>::Transform(const uint8_t* input,
5135 const MinMax<uint8_t>& params,
5136 uint8_t* output) {
5137 #ifdef DEBUG
5138 #ifdef DEBUG_METAGEMM_VERBOSE
5139 std::cout << __FILE__ << "(" << __LINE__
5140 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5141 "10>::Transform()"
5142 << std::endl
5143 << std::flush;
5144 #endif
5145 #endif
5146 int params_count_copy = params.count;
5147 asm volatile(
5148
5149 // MinMax::Prepare
5150 "vdup.8 q4, %[min]\n"
5151 "vdup.8 q5, %[max]\n"
5152
5153 // Reduce count by leftovers.
5154 "subs %[count], %[count], #10\n"
5155 "beq 2f\n"
5156
5157 "1:"
5158 "subs %[count], %[count], #16\n"
5159
5160 // MinMax::Transform
5161 "vld1.32 {d0, d1}, [%[input]]!\n"
5162 "pld [%[input], #16]\n"
5163 "vmax.u8 q0, q0, q4\n"
5164 "vmin.u8 q0, q0, q5\n"
5165
5166 "vst1.32 {d0, d1}, [%[output]]!\n"
5167 "pld [%[output]]\n"
5168
5169 "bne 1b\n"
5170 "2:"
5171
5172 // Handle leftovers.
5173
5174 // MinMax::Transform
5175 "vld1.32 {d0}, [%[input]]!\n"
5176 "vld1.16 {d1[0]}, [%[input]]!\n"
5177 "pld [%[input], #16]\n"
5178 "vmax.u8 q0, q0, q4\n"
5179 "vmin.u8 q0, q0, q5\n"
5180
5181 "vst1.32 {d0}, [%[output]]!\n"
5182 "vst1.16 {d1[0]}, [%[output]]!\n"
5183 "pld [%[output]]\n"
5184 : [count] "+r"(params_count_copy), [input] "+r"(input),
5185 [output] "+r"(output)
5186 : [max] "r"(params.max), [min] "r"(params.min)
5187 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5188 }
5189
5190 template <>
5191 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5192 11>::Transform(const uint8_t* input,
5193 const MinMax<uint8_t>& params,
5194 uint8_t* output) {
5195 #ifdef DEBUG
5196 #ifdef DEBUG_METAGEMM_VERBOSE
5197 std::cout << __FILE__ << "(" << __LINE__
5198 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5199 "11>::Transform()"
5200 << std::endl
5201 << std::flush;
5202 #endif
5203 #endif
5204 int params_count_copy = params.count;
5205 asm volatile(
5206
5207 // MinMax::Prepare
5208 "vdup.8 q4, %[min]\n"
5209 "vdup.8 q5, %[max]\n"
5210
5211 // Reduce count by leftovers.
5212 "subs %[count], %[count], #11\n"
5213 "beq 2f\n"
5214
5215 "1:"
5216 "subs %[count], %[count], #16\n"
5217
5218 // MinMax::Transform
5219 "vld1.32 {d0, d1}, [%[input]]!\n"
5220 "pld [%[input], #16]\n"
5221 "vmax.u8 q0, q0, q4\n"
5222 "vmin.u8 q0, q0, q5\n"
5223
5224 "vst1.32 {d0, d1}, [%[output]]!\n"
5225 "pld [%[output]]\n"
5226
5227 "bne 1b\n"
5228 "2:"
5229
5230 // Handle leftovers.
5231
5232 // MinMax::Transform
5233 "vld1.32 {d0}, [%[input]]!\n"
5234 "vld1.16 {d1[0]}, [%[input]]!\n"
5235 "vld1.8 {d1[2]}, [%[input]]!\n"
5236 "pld [%[input], #16]\n"
5237 "vmax.u8 q0, q0, q4\n"
5238 "vmin.u8 q0, q0, q5\n"
5239
5240 "vst1.32 {d0}, [%[output]]!\n"
5241 "vst1.16 {d1[0]}, [%[output]]!\n"
5242 "vst1.8 {d1[2]}, [%[output]]!\n"
5243 "pld [%[output]]\n"
5244 : [count] "+r"(params_count_copy), [input] "+r"(input),
5245 [output] "+r"(output)
5246 : [max] "r"(params.max), [min] "r"(params.min)
5247 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5248 }
5249
5250 template <>
5251 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5252 12>::Transform(const uint8_t* input,
5253 const MinMax<uint8_t>& params,
5254 uint8_t* output) {
5255 #ifdef DEBUG
5256 #ifdef DEBUG_METAGEMM_VERBOSE
5257 std::cout << __FILE__ << "(" << __LINE__
5258 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5259 "12>::Transform()"
5260 << std::endl
5261 << std::flush;
5262 #endif
5263 #endif
5264 int params_count_copy = params.count;
5265 asm volatile(
5266
5267 // MinMax::Prepare
5268 "vdup.8 q4, %[min]\n"
5269 "vdup.8 q5, %[max]\n"
5270
5271 // Reduce count by leftovers.
5272 "subs %[count], %[count], #12\n"
5273 "beq 2f\n"
5274
5275 "1:"
5276 "subs %[count], %[count], #16\n"
5277
5278 // MinMax::Transform
5279 "vld1.32 {d0, d1}, [%[input]]!\n"
5280 "pld [%[input], #16]\n"
5281 "vmax.u8 q0, q0, q4\n"
5282 "vmin.u8 q0, q0, q5\n"
5283
5284 "vst1.32 {d0, d1}, [%[output]]!\n"
5285 "pld [%[output]]\n"
5286
5287 "bne 1b\n"
5288 "2:"
5289
5290 // Handle leftovers.
5291
5292 // MinMax::Transform
5293 "vld1.32 {d0}, [%[input]]!\n"
5294 "vld1.32 {d1[0]}, [%[input]]!\n"
5295 "pld [%[input], #16]\n"
5296 "vmax.u8 q0, q0, q4\n"
5297 "vmin.u8 q0, q0, q5\n"
5298
5299 "vst1.32 {d0}, [%[output]]!\n"
5300 "vst1.32 {d1[0]}, [%[output]]!\n"
5301 "pld [%[output]]\n"
5302 : [count] "+r"(params_count_copy), [input] "+r"(input),
5303 [output] "+r"(output)
5304 : [max] "r"(params.max), [min] "r"(params.min)
5305 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5306 }
5307
5308 template <>
5309 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5310 13>::Transform(const uint8_t* input,
5311 const MinMax<uint8_t>& params,
5312 uint8_t* output) {
5313 #ifdef DEBUG
5314 #ifdef DEBUG_METAGEMM_VERBOSE
5315 std::cout << __FILE__ << "(" << __LINE__
5316 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5317 "13>::Transform()"
5318 << std::endl
5319 << std::flush;
5320 #endif
5321 #endif
5322 int params_count_copy = params.count;
5323 asm volatile(
5324
5325 // MinMax::Prepare
5326 "vdup.8 q4, %[min]\n"
5327 "vdup.8 q5, %[max]\n"
5328
5329 // Reduce count by leftovers.
5330 "subs %[count], %[count], #13\n"
5331 "beq 2f\n"
5332
5333 "1:"
5334 "subs %[count], %[count], #16\n"
5335
5336 // MinMax::Transform
5337 "vld1.32 {d0, d1}, [%[input]]!\n"
5338 "pld [%[input], #16]\n"
5339 "vmax.u8 q0, q0, q4\n"
5340 "vmin.u8 q0, q0, q5\n"
5341
5342 "vst1.32 {d0, d1}, [%[output]]!\n"
5343 "pld [%[output]]\n"
5344
5345 "bne 1b\n"
5346 "2:"
5347
5348 // Handle leftovers.
5349
5350 // MinMax::Transform
5351 "vld1.32 {d0}, [%[input]]!\n"
5352 "vld1.32 {d1[0]}, [%[input]]!\n"
5353 "vld1.8 {d1[4]}, [%[input]]!\n"
5354 "pld [%[input], #16]\n"
5355 "vmax.u8 q0, q0, q4\n"
5356 "vmin.u8 q0, q0, q5\n"
5357
5358 "vst1.32 {d0}, [%[output]]!\n"
5359 "vst1.32 {d1[0]}, [%[output]]!\n"
5360 "vst1.8 {d1[4]}, [%[output]]!\n"
5361 "pld [%[output]]\n"
5362 : [count] "+r"(params_count_copy), [input] "+r"(input),
5363 [output] "+r"(output)
5364 : [max] "r"(params.max), [min] "r"(params.min)
5365 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5366 }
5367
5368 template <>
5369 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5370 14>::Transform(const uint8_t* input,
5371 const MinMax<uint8_t>& params,
5372 uint8_t* output) {
5373 #ifdef DEBUG
5374 #ifdef DEBUG_METAGEMM_VERBOSE
5375 std::cout << __FILE__ << "(" << __LINE__
5376 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5377 "14>::Transform()"
5378 << std::endl
5379 << std::flush;
5380 #endif
5381 #endif
5382 int params_count_copy = params.count;
5383 asm volatile(
5384
5385 // MinMax::Prepare
5386 "vdup.8 q4, %[min]\n"
5387 "vdup.8 q5, %[max]\n"
5388
5389 // Reduce count by leftovers.
5390 "subs %[count], %[count], #14\n"
5391 "beq 2f\n"
5392
5393 "1:"
5394 "subs %[count], %[count], #16\n"
5395
5396 // MinMax::Transform
5397 "vld1.32 {d0, d1}, [%[input]]!\n"
5398 "pld [%[input], #16]\n"
5399 "vmax.u8 q0, q0, q4\n"
5400 "vmin.u8 q0, q0, q5\n"
5401
5402 "vst1.32 {d0, d1}, [%[output]]!\n"
5403 "pld [%[output]]\n"
5404
5405 "bne 1b\n"
5406 "2:"
5407
5408 // Handle leftovers.
5409
5410 // MinMax::Transform
5411 "vld1.32 {d0}, [%[input]]!\n"
5412 "vld1.32 {d1[0]}, [%[input]]!\n"
5413 "vld1.16 {d1[2]}, [%[input]]!\n"
5414 "pld [%[input], #16]\n"
5415 "vmax.u8 q0, q0, q4\n"
5416 "vmin.u8 q0, q0, q5\n"
5417
5418 "vst1.32 {d0}, [%[output]]!\n"
5419 "vst1.32 {d1[0]}, [%[output]]!\n"
5420 "vst1.16 {d1[2]}, [%[output]]!\n"
5421 "pld [%[output]]\n"
5422 : [count] "+r"(params_count_copy), [input] "+r"(input),
5423 [output] "+r"(output)
5424 : [max] "r"(params.max), [min] "r"(params.min)
5425 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5426 }
5427
5428 template <>
5429 inline void Transform1DKernel<uint8_t, uint8_t, MinMax<uint8_t>, 16,
Transform(const uint8_t * input,const MinMax<uint8_t> & params,uint8_t * output)5430 15>::Transform(const uint8_t* input,
5431 const MinMax<uint8_t>& params,
5432 uint8_t* output) {
5433 #ifdef DEBUG
5434 #ifdef DEBUG_METAGEMM_VERBOSE
5435 std::cout << __FILE__ << "(" << __LINE__
5436 << ") MinMax<uint8_t><uint8_t, uint8_t, MinMax<uint8_t>, 16, "
5437 "15>::Transform()"
5438 << std::endl
5439 << std::flush;
5440 #endif
5441 #endif
5442 int params_count_copy = params.count;
5443 asm volatile(
5444
5445 // MinMax::Prepare
5446 "vdup.8 q4, %[min]\n"
5447 "vdup.8 q5, %[max]\n"
5448
5449 // Reduce count by leftovers.
5450 "subs %[count], %[count], #15\n"
5451 "beq 2f\n"
5452
5453 "1:"
5454 "subs %[count], %[count], #16\n"
5455
5456 // MinMax::Transform
5457 "vld1.32 {d0, d1}, [%[input]]!\n"
5458 "pld [%[input], #16]\n"
5459 "vmax.u8 q0, q0, q4\n"
5460 "vmin.u8 q0, q0, q5\n"
5461
5462 "vst1.32 {d0, d1}, [%[output]]!\n"
5463 "pld [%[output]]\n"
5464
5465 "bne 1b\n"
5466 "2:"
5467
5468 // Handle leftovers.
5469
5470 // MinMax::Transform
5471 "vld1.32 {d0}, [%[input]]!\n"
5472 "vld1.32 {d1[0]}, [%[input]]!\n"
5473 "vld1.16 {d1[2]}, [%[input]]!\n"
5474 "vld1.8 {d1[6]}, [%[input]]!\n"
5475 "pld [%[input], #16]\n"
5476 "vmax.u8 q0, q0, q4\n"
5477 "vmin.u8 q0, q0, q5\n"
5478
5479 "vst1.32 {d0}, [%[output]]!\n"
5480 "vst1.32 {d1[0]}, [%[output]]!\n"
5481 "vst1.16 {d1[2]}, [%[output]]!\n"
5482 "vst1.8 {d1[6]}, [%[output]]!\n"
5483 "pld [%[output]]\n"
5484 : [count] "+r"(params_count_copy), [input] "+r"(input),
5485 [output] "+r"(output)
5486 : [max] "r"(params.max), [min] "r"(params.min)
5487 : "d0", "d1", "d8", "d9", "d10", "d11", "cc", "memory");
5488 }
5489
5490 template <>
5491 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)5492 0>::Transform(const uint8_t* input,
5493 const BiasAdd<uint8_t>& params,
5494 int32_t* output) {
5495 #ifdef DEBUG
5496 #ifdef DEBUG_METAGEMM_VERBOSE
5497 std::cout << __FILE__ << "(" << __LINE__
5498 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
5499 "0>::Transform()"
5500 << std::endl
5501 << std::flush;
5502 #endif
5503 #endif
5504 int params_rows_copy = params.rows;
5505 asm volatile(
5506 "ldr r0, %[input_range_min]\n"
5507 "vdup.32 q8, r0\n"
5508 "ldr r0, %[input_range_scale]\n"
5509 "vdup.32 q9, r0\n"
5510 "ldr r0, %[bias_range_min]\n"
5511 "vdup.32 q10, r0\n"
5512 "ldr r0, %[bias_range_scale]\n"
5513 "vdup.32 q11, r0\n"
5514 "ldr r0, %[output_range_min]\n"
5515 "vdup.32 q12, r0\n"
5516 "ldr r0, %[one_over_output_range_scale]\n"
5517 "vdup.32 q13, r0\n"
5518 "ldr r0, %[output_range_offset]\n"
5519 "vdup.32 q14, r0\n"
5520 "1:"
5521 "mov r0, %[count]\n"
5522 "mov r1, %[bias]\n"
5523 "2:"
5524 "subs r0, r0, #16\n"
5525
5526 // BiasAdd::Transform
5527 "vld1.32 {d0, d1}, [%[input]]!\n"
5528 "vld1.32 {d8, d9}, [r1]!\n"
5529 "pld [%[input], #32]\n"
5530 "vmovl.u8 q1, d1\n"
5531 "vmovl.u8 q0, d0\n"
5532 "vmovl.u8 q5, d9\n"
5533 "vmovl.u8 q4, d8\n"
5534 "vmovl.s16 q3, d3\n"
5535 "vmovl.s16 q2, d2\n"
5536 "vmovl.s16 q7, d11\n"
5537 "vmovl.s16 q6, d10\n"
5538 "vmovl.s16 q1, d1\n"
5539 "vmovl.s16 q0, d0\n"
5540 "vmovl.s16 q5, d9\n"
5541 "vmovl.s16 q4, d8\n"
5542 "vcvt.f32.s32 q0, q0\n"
5543 "vcvt.f32.s32 q1, q1\n"
5544 "vcvt.f32.s32 q2, q2\n"
5545 "vcvt.f32.s32 q3, q3\n"
5546 "vcvt.f32.s32 q4, q4\n"
5547 "vcvt.f32.s32 q5, q5\n"
5548 "vcvt.f32.s32 q6, q6\n"
5549 "vcvt.f32.s32 q7, q7\n"
5550 "vmul.f32 q0, q0, q9\n"
5551 "vmul.f32 q1, q1, q9\n"
5552 "vmul.f32 q2, q2, q9\n"
5553 "vmul.f32 q3, q3, q9\n"
5554 "vmul.f32 q4, q4, q11\n"
5555 "vmul.f32 q5, q5, q11\n"
5556 "vmul.f32 q6, q6, q11\n"
5557 "vmul.f32 q7, q7, q11\n"
5558 "vadd.f32 q0, q0, q8\n"
5559 "vadd.f32 q1, q1, q8\n"
5560 "vadd.f32 q2, q2, q8\n"
5561 "vadd.f32 q3, q3, q8\n"
5562 "vadd.f32 q4, q4, q10\n"
5563 "vadd.f32 q5, q5, q10\n"
5564 "vadd.f32 q6, q6, q10\n"
5565 "vadd.f32 q7, q7, q10\n"
5566 "vadd.f32 q0, q0, q4\n"
5567 "vadd.f32 q1, q1, q5\n"
5568 "vadd.f32 q2, q2, q6\n"
5569 "vadd.f32 q3, q3, q7\n"
5570 "vsub.f32 q0, q0, q12\n"
5571 "vsub.f32 q1, q1, q12\n"
5572 "vsub.f32 q2, q2, q12\n"
5573 "vsub.f32 q3, q3, q12\n"
5574 "vmul.f32 q0, q0, q13\n"
5575 "vmul.f32 q1, q1, q13\n"
5576 "vmul.f32 q2, q2, q13\n"
5577 "vmul.f32 q3, q3, q13\n"
5578 "vadd.f32 q0, q0, q14\n"
5579 "vadd.f32 q1, q1, q14\n"
5580 "vadd.f32 q2, q2, q14\n"
5581 "vadd.f32 q3, q3, q14\n"
5582 "vcvt.s32.f32 q0, q0\n"
5583 "vcvt.s32.f32 q1, q1\n"
5584 "vcvt.s32.f32 q2, q2\n"
5585 "vcvt.s32.f32 q3, q3\n"
5586
5587 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
5588 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
5589 "pld [%[output]]\n"
5590 "bne 2b\n"
5591 "subs %[rows], %[rows], #1\n"
5592 "bne 1b\n"
5593 : [input] "+r"(input), [output] "+r"(output)
5594 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
5595 [output_range_offset] "m"(params.output_range_offset),
5596 [input_range_scale] "m"(params.input_range_scale),
5597 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
5598 [bias_range_min] "m"(params.bias_range_min),
5599 [output_range_min] "m"(params.output_range_min),
5600 [bias_range_scale] "m"(params.bias_range_scale),
5601 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
5602 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
5603 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
5604 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
5605 "cc", "memory");
5606 }
5607
5608 template <>
5609 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)5610 1>::Transform(const uint8_t* input,
5611 const BiasAdd<uint8_t>& params,
5612 int32_t* output) {
5613 #ifdef DEBUG
5614 #ifdef DEBUG_METAGEMM_VERBOSE
5615 std::cout << __FILE__ << "(" << __LINE__
5616 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
5617 "1>::Transform()"
5618 << std::endl
5619 << std::flush;
5620 #endif
5621 #endif
5622 int params_rows_copy = params.rows;
5623 asm volatile(
5624 "ldr r0, %[input_range_min]\n"
5625 "vdup.32 q8, r0\n"
5626 "ldr r0, %[input_range_scale]\n"
5627 "vdup.32 q9, r0\n"
5628 "ldr r0, %[bias_range_min]\n"
5629 "vdup.32 q10, r0\n"
5630 "ldr r0, %[bias_range_scale]\n"
5631 "vdup.32 q11, r0\n"
5632 "ldr r0, %[output_range_min]\n"
5633 "vdup.32 q12, r0\n"
5634 "ldr r0, %[one_over_output_range_scale]\n"
5635 "vdup.32 q13, r0\n"
5636 "ldr r0, %[output_range_offset]\n"
5637 "vdup.32 q14, r0\n"
5638 "1:"
5639 "mov r0, %[count]\n"
5640 "mov r1, %[bias]\n"
5641 "subs r0, r0, #1\n"
5642 "beq 3f\n"
5643 "2:"
5644 "subs r0, r0, #16\n"
5645
5646 // BiasAdd::Transform
5647 "vld1.32 {d0, d1}, [%[input]]!\n"
5648 "vld1.32 {d8, d9}, [r1]!\n"
5649 "pld [%[input], #32]\n"
5650 "vmovl.u8 q1, d1\n"
5651 "vmovl.u8 q0, d0\n"
5652 "vmovl.u8 q5, d9\n"
5653 "vmovl.u8 q4, d8\n"
5654 "vmovl.s16 q3, d3\n"
5655 "vmovl.s16 q2, d2\n"
5656 "vmovl.s16 q7, d11\n"
5657 "vmovl.s16 q6, d10\n"
5658 "vmovl.s16 q1, d1\n"
5659 "vmovl.s16 q0, d0\n"
5660 "vmovl.s16 q5, d9\n"
5661 "vmovl.s16 q4, d8\n"
5662 "vcvt.f32.s32 q0, q0\n"
5663 "vcvt.f32.s32 q1, q1\n"
5664 "vcvt.f32.s32 q2, q2\n"
5665 "vcvt.f32.s32 q3, q3\n"
5666 "vcvt.f32.s32 q4, q4\n"
5667 "vcvt.f32.s32 q5, q5\n"
5668 "vcvt.f32.s32 q6, q6\n"
5669 "vcvt.f32.s32 q7, q7\n"
5670 "vmul.f32 q0, q0, q9\n"
5671 "vmul.f32 q1, q1, q9\n"
5672 "vmul.f32 q2, q2, q9\n"
5673 "vmul.f32 q3, q3, q9\n"
5674 "vmul.f32 q4, q4, q11\n"
5675 "vmul.f32 q5, q5, q11\n"
5676 "vmul.f32 q6, q6, q11\n"
5677 "vmul.f32 q7, q7, q11\n"
5678 "vadd.f32 q0, q0, q8\n"
5679 "vadd.f32 q1, q1, q8\n"
5680 "vadd.f32 q2, q2, q8\n"
5681 "vadd.f32 q3, q3, q8\n"
5682 "vadd.f32 q4, q4, q10\n"
5683 "vadd.f32 q5, q5, q10\n"
5684 "vadd.f32 q6, q6, q10\n"
5685 "vadd.f32 q7, q7, q10\n"
5686 "vadd.f32 q0, q0, q4\n"
5687 "vadd.f32 q1, q1, q5\n"
5688 "vadd.f32 q2, q2, q6\n"
5689 "vadd.f32 q3, q3, q7\n"
5690 "vsub.f32 q0, q0, q12\n"
5691 "vsub.f32 q1, q1, q12\n"
5692 "vsub.f32 q2, q2, q12\n"
5693 "vsub.f32 q3, q3, q12\n"
5694 "vmul.f32 q0, q0, q13\n"
5695 "vmul.f32 q1, q1, q13\n"
5696 "vmul.f32 q2, q2, q13\n"
5697 "vmul.f32 q3, q3, q13\n"
5698 "vadd.f32 q0, q0, q14\n"
5699 "vadd.f32 q1, q1, q14\n"
5700 "vadd.f32 q2, q2, q14\n"
5701 "vadd.f32 q3, q3, q14\n"
5702 "vcvt.s32.f32 q0, q0\n"
5703 "vcvt.s32.f32 q1, q1\n"
5704 "vcvt.s32.f32 q2, q2\n"
5705 "vcvt.s32.f32 q3, q3\n"
5706
5707 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
5708 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
5709 "pld [%[output]]\n"
5710 "bne 2b\n"
5711 "3:"
5712
5713 // BiasAdd::Transform
5714 "vld1.8 {d0[0]}, [%[input]]!\n"
5715 "vld1.8 {d2[0]}, [r1]!\n"
5716 "pld [%[input], #32]\n"
5717 "vmovl.u8 q0, d0\n"
5718 "vmovl.u8 q1, d2\n"
5719 "vmovl.s16 q0, d0\n"
5720 "vmovl.s16 q1, d2\n"
5721 "vcvt.f32.s32 q0, q0\n"
5722 "vcvt.f32.s32 q1, q1\n"
5723 "vmul.f32 q0, q0, q9\n"
5724 "vmul.f32 q1, q1, q11\n"
5725 "vadd.f32 q0, q0, q8\n"
5726 "vadd.f32 q1, q1, q10\n"
5727 "vadd.f32 q0, q0, q1\n"
5728 "vsub.f32 q0, q0, q12\n"
5729 "vmul.f32 q0, q0, q13\n"
5730 "vadd.f32 q0, q0, q14\n"
5731 "vcvt.s32.f32 q0, q0\n"
5732
5733 "vst1.32 {d0[0]}, [%[output]]!\n"
5734 "pld [%[output]]\n"
5735 "subs %[rows], %[rows], #1\n"
5736 "bne 1b\n"
5737 : [input] "+r"(input), [output] "+r"(output)
5738 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
5739 [output_range_offset] "m"(params.output_range_offset),
5740 [input_range_scale] "m"(params.input_range_scale),
5741 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
5742 [bias_range_min] "m"(params.bias_range_min),
5743 [output_range_min] "m"(params.output_range_min),
5744 [bias_range_scale] "m"(params.bias_range_scale),
5745 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
5746 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
5747 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
5748 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
5749 "cc", "memory");
5750 }
5751
5752 template <>
5753 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)5754 2>::Transform(const uint8_t* input,
5755 const BiasAdd<uint8_t>& params,
5756 int32_t* output) {
5757 #ifdef DEBUG
5758 #ifdef DEBUG_METAGEMM_VERBOSE
5759 std::cout << __FILE__ << "(" << __LINE__
5760 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
5761 "2>::Transform()"
5762 << std::endl
5763 << std::flush;
5764 #endif
5765 #endif
5766 int params_rows_copy = params.rows;
5767 asm volatile(
5768 "ldr r0, %[input_range_min]\n"
5769 "vdup.32 q8, r0\n"
5770 "ldr r0, %[input_range_scale]\n"
5771 "vdup.32 q9, r0\n"
5772 "ldr r0, %[bias_range_min]\n"
5773 "vdup.32 q10, r0\n"
5774 "ldr r0, %[bias_range_scale]\n"
5775 "vdup.32 q11, r0\n"
5776 "ldr r0, %[output_range_min]\n"
5777 "vdup.32 q12, r0\n"
5778 "ldr r0, %[one_over_output_range_scale]\n"
5779 "vdup.32 q13, r0\n"
5780 "ldr r0, %[output_range_offset]\n"
5781 "vdup.32 q14, r0\n"
5782 "1:"
5783 "mov r0, %[count]\n"
5784 "mov r1, %[bias]\n"
5785 "subs r0, r0, #2\n"
5786 "beq 3f\n"
5787 "2:"
5788 "subs r0, r0, #16\n"
5789
5790 // BiasAdd::Transform
5791 "vld1.32 {d0, d1}, [%[input]]!\n"
5792 "vld1.32 {d8, d9}, [r1]!\n"
5793 "pld [%[input], #32]\n"
5794 "vmovl.u8 q1, d1\n"
5795 "vmovl.u8 q0, d0\n"
5796 "vmovl.u8 q5, d9\n"
5797 "vmovl.u8 q4, d8\n"
5798 "vmovl.s16 q3, d3\n"
5799 "vmovl.s16 q2, d2\n"
5800 "vmovl.s16 q7, d11\n"
5801 "vmovl.s16 q6, d10\n"
5802 "vmovl.s16 q1, d1\n"
5803 "vmovl.s16 q0, d0\n"
5804 "vmovl.s16 q5, d9\n"
5805 "vmovl.s16 q4, d8\n"
5806 "vcvt.f32.s32 q0, q0\n"
5807 "vcvt.f32.s32 q1, q1\n"
5808 "vcvt.f32.s32 q2, q2\n"
5809 "vcvt.f32.s32 q3, q3\n"
5810 "vcvt.f32.s32 q4, q4\n"
5811 "vcvt.f32.s32 q5, q5\n"
5812 "vcvt.f32.s32 q6, q6\n"
5813 "vcvt.f32.s32 q7, q7\n"
5814 "vmul.f32 q0, q0, q9\n"
5815 "vmul.f32 q1, q1, q9\n"
5816 "vmul.f32 q2, q2, q9\n"
5817 "vmul.f32 q3, q3, q9\n"
5818 "vmul.f32 q4, q4, q11\n"
5819 "vmul.f32 q5, q5, q11\n"
5820 "vmul.f32 q6, q6, q11\n"
5821 "vmul.f32 q7, q7, q11\n"
5822 "vadd.f32 q0, q0, q8\n"
5823 "vadd.f32 q1, q1, q8\n"
5824 "vadd.f32 q2, q2, q8\n"
5825 "vadd.f32 q3, q3, q8\n"
5826 "vadd.f32 q4, q4, q10\n"
5827 "vadd.f32 q5, q5, q10\n"
5828 "vadd.f32 q6, q6, q10\n"
5829 "vadd.f32 q7, q7, q10\n"
5830 "vadd.f32 q0, q0, q4\n"
5831 "vadd.f32 q1, q1, q5\n"
5832 "vadd.f32 q2, q2, q6\n"
5833 "vadd.f32 q3, q3, q7\n"
5834 "vsub.f32 q0, q0, q12\n"
5835 "vsub.f32 q1, q1, q12\n"
5836 "vsub.f32 q2, q2, q12\n"
5837 "vsub.f32 q3, q3, q12\n"
5838 "vmul.f32 q0, q0, q13\n"
5839 "vmul.f32 q1, q1, q13\n"
5840 "vmul.f32 q2, q2, q13\n"
5841 "vmul.f32 q3, q3, q13\n"
5842 "vadd.f32 q0, q0, q14\n"
5843 "vadd.f32 q1, q1, q14\n"
5844 "vadd.f32 q2, q2, q14\n"
5845 "vadd.f32 q3, q3, q14\n"
5846 "vcvt.s32.f32 q0, q0\n"
5847 "vcvt.s32.f32 q1, q1\n"
5848 "vcvt.s32.f32 q2, q2\n"
5849 "vcvt.s32.f32 q3, q3\n"
5850
5851 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
5852 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
5853 "pld [%[output]]\n"
5854 "bne 2b\n"
5855 "3:"
5856
5857 // BiasAdd::Transform
5858 "vld1.16 {d0[0]}, [%[input]]!\n"
5859 "vld1.16 {d2[0]}, [r1]!\n"
5860 "pld [%[input], #32]\n"
5861 "vmovl.u8 q0, d0\n"
5862 "vmovl.u8 q1, d2\n"
5863 "vmovl.s16 q0, d0\n"
5864 "vmovl.s16 q1, d2\n"
5865 "vcvt.f32.s32 q0, q0\n"
5866 "vcvt.f32.s32 q1, q1\n"
5867 "vmul.f32 q0, q0, q9\n"
5868 "vmul.f32 q1, q1, q11\n"
5869 "vadd.f32 q0, q0, q8\n"
5870 "vadd.f32 q1, q1, q10\n"
5871 "vadd.f32 q0, q0, q1\n"
5872 "vsub.f32 q0, q0, q12\n"
5873 "vmul.f32 q0, q0, q13\n"
5874 "vadd.f32 q0, q0, q14\n"
5875 "vcvt.s32.f32 q0, q0\n"
5876
5877 "vst1.32 {d0}, [%[output]]!\n"
5878 "pld [%[output]]\n"
5879 "subs %[rows], %[rows], #1\n"
5880 "bne 1b\n"
5881 : [input] "+r"(input), [output] "+r"(output)
5882 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
5883 [output_range_offset] "m"(params.output_range_offset),
5884 [input_range_scale] "m"(params.input_range_scale),
5885 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
5886 [bias_range_min] "m"(params.bias_range_min),
5887 [output_range_min] "m"(params.output_range_min),
5888 [bias_range_scale] "m"(params.bias_range_scale),
5889 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
5890 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
5891 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
5892 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
5893 "cc", "memory");
5894 }
5895
5896 template <>
5897 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)5898 3>::Transform(const uint8_t* input,
5899 const BiasAdd<uint8_t>& params,
5900 int32_t* output) {
5901 #ifdef DEBUG
5902 #ifdef DEBUG_METAGEMM_VERBOSE
5903 std::cout << __FILE__ << "(" << __LINE__
5904 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
5905 "3>::Transform()"
5906 << std::endl
5907 << std::flush;
5908 #endif
5909 #endif
5910 int params_rows_copy = params.rows;
5911 asm volatile(
5912 "ldr r0, %[input_range_min]\n"
5913 "vdup.32 q8, r0\n"
5914 "ldr r0, %[input_range_scale]\n"
5915 "vdup.32 q9, r0\n"
5916 "ldr r0, %[bias_range_min]\n"
5917 "vdup.32 q10, r0\n"
5918 "ldr r0, %[bias_range_scale]\n"
5919 "vdup.32 q11, r0\n"
5920 "ldr r0, %[output_range_min]\n"
5921 "vdup.32 q12, r0\n"
5922 "ldr r0, %[one_over_output_range_scale]\n"
5923 "vdup.32 q13, r0\n"
5924 "ldr r0, %[output_range_offset]\n"
5925 "vdup.32 q14, r0\n"
5926 "1:"
5927 "mov r0, %[count]\n"
5928 "mov r1, %[bias]\n"
5929 "subs r0, r0, #3\n"
5930 "beq 3f\n"
5931 "2:"
5932 "subs r0, r0, #16\n"
5933
5934 // BiasAdd::Transform
5935 "vld1.32 {d0, d1}, [%[input]]!\n"
5936 "vld1.32 {d8, d9}, [r1]!\n"
5937 "pld [%[input], #32]\n"
5938 "vmovl.u8 q1, d1\n"
5939 "vmovl.u8 q0, d0\n"
5940 "vmovl.u8 q5, d9\n"
5941 "vmovl.u8 q4, d8\n"
5942 "vmovl.s16 q3, d3\n"
5943 "vmovl.s16 q2, d2\n"
5944 "vmovl.s16 q7, d11\n"
5945 "vmovl.s16 q6, d10\n"
5946 "vmovl.s16 q1, d1\n"
5947 "vmovl.s16 q0, d0\n"
5948 "vmovl.s16 q5, d9\n"
5949 "vmovl.s16 q4, d8\n"
5950 "vcvt.f32.s32 q0, q0\n"
5951 "vcvt.f32.s32 q1, q1\n"
5952 "vcvt.f32.s32 q2, q2\n"
5953 "vcvt.f32.s32 q3, q3\n"
5954 "vcvt.f32.s32 q4, q4\n"
5955 "vcvt.f32.s32 q5, q5\n"
5956 "vcvt.f32.s32 q6, q6\n"
5957 "vcvt.f32.s32 q7, q7\n"
5958 "vmul.f32 q0, q0, q9\n"
5959 "vmul.f32 q1, q1, q9\n"
5960 "vmul.f32 q2, q2, q9\n"
5961 "vmul.f32 q3, q3, q9\n"
5962 "vmul.f32 q4, q4, q11\n"
5963 "vmul.f32 q5, q5, q11\n"
5964 "vmul.f32 q6, q6, q11\n"
5965 "vmul.f32 q7, q7, q11\n"
5966 "vadd.f32 q0, q0, q8\n"
5967 "vadd.f32 q1, q1, q8\n"
5968 "vadd.f32 q2, q2, q8\n"
5969 "vadd.f32 q3, q3, q8\n"
5970 "vadd.f32 q4, q4, q10\n"
5971 "vadd.f32 q5, q5, q10\n"
5972 "vadd.f32 q6, q6, q10\n"
5973 "vadd.f32 q7, q7, q10\n"
5974 "vadd.f32 q0, q0, q4\n"
5975 "vadd.f32 q1, q1, q5\n"
5976 "vadd.f32 q2, q2, q6\n"
5977 "vadd.f32 q3, q3, q7\n"
5978 "vsub.f32 q0, q0, q12\n"
5979 "vsub.f32 q1, q1, q12\n"
5980 "vsub.f32 q2, q2, q12\n"
5981 "vsub.f32 q3, q3, q12\n"
5982 "vmul.f32 q0, q0, q13\n"
5983 "vmul.f32 q1, q1, q13\n"
5984 "vmul.f32 q2, q2, q13\n"
5985 "vmul.f32 q3, q3, q13\n"
5986 "vadd.f32 q0, q0, q14\n"
5987 "vadd.f32 q1, q1, q14\n"
5988 "vadd.f32 q2, q2, q14\n"
5989 "vadd.f32 q3, q3, q14\n"
5990 "vcvt.s32.f32 q0, q0\n"
5991 "vcvt.s32.f32 q1, q1\n"
5992 "vcvt.s32.f32 q2, q2\n"
5993 "vcvt.s32.f32 q3, q3\n"
5994
5995 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
5996 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
5997 "pld [%[output]]\n"
5998 "bne 2b\n"
5999 "3:"
6000
6001 // BiasAdd::Transform
6002 "vld1.16 {d0[0]}, [%[input]]!\n"
6003 "vld1.8 {d0[2]}, [%[input]]!\n"
6004 "vld1.16 {d2[0]}, [r1]!\n"
6005 "vld1.8 {d2[2]}, [r1]!\n"
6006 "pld [%[input], #32]\n"
6007 "vmovl.u8 q0, d0\n"
6008 "vmovl.u8 q1, d2\n"
6009 "vmovl.s16 q0, d0\n"
6010 "vmovl.s16 q1, d2\n"
6011 "vcvt.f32.s32 q0, q0\n"
6012 "vcvt.f32.s32 q1, q1\n"
6013 "vmul.f32 q0, q0, q9\n"
6014 "vmul.f32 q1, q1, q11\n"
6015 "vadd.f32 q0, q0, q8\n"
6016 "vadd.f32 q1, q1, q10\n"
6017 "vadd.f32 q0, q0, q1\n"
6018 "vsub.f32 q0, q0, q12\n"
6019 "vmul.f32 q0, q0, q13\n"
6020 "vadd.f32 q0, q0, q14\n"
6021 "vcvt.s32.f32 q0, q0\n"
6022
6023 "vst1.32 {d0}, [%[output]]!\n"
6024 "vst1.32 {d1[0]}, [%[output]]!\n"
6025 "pld [%[output]]\n"
6026 "subs %[rows], %[rows], #1\n"
6027 "bne 1b\n"
6028 : [input] "+r"(input), [output] "+r"(output)
6029 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
6030 [output_range_offset] "m"(params.output_range_offset),
6031 [input_range_scale] "m"(params.input_range_scale),
6032 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
6033 [bias_range_min] "m"(params.bias_range_min),
6034 [output_range_min] "m"(params.output_range_min),
6035 [bias_range_scale] "m"(params.bias_range_scale),
6036 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
6037 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
6038 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
6039 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
6040 "cc", "memory");
6041 }
6042
6043 template <>
6044 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)6045 4>::Transform(const uint8_t* input,
6046 const BiasAdd<uint8_t>& params,
6047 int32_t* output) {
6048 #ifdef DEBUG
6049 #ifdef DEBUG_METAGEMM_VERBOSE
6050 std::cout << __FILE__ << "(" << __LINE__
6051 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
6052 "4>::Transform()"
6053 << std::endl
6054 << std::flush;
6055 #endif
6056 #endif
6057 int params_rows_copy = params.rows;
6058 asm volatile(
6059 "ldr r0, %[input_range_min]\n"
6060 "vdup.32 q8, r0\n"
6061 "ldr r0, %[input_range_scale]\n"
6062 "vdup.32 q9, r0\n"
6063 "ldr r0, %[bias_range_min]\n"
6064 "vdup.32 q10, r0\n"
6065 "ldr r0, %[bias_range_scale]\n"
6066 "vdup.32 q11, r0\n"
6067 "ldr r0, %[output_range_min]\n"
6068 "vdup.32 q12, r0\n"
6069 "ldr r0, %[one_over_output_range_scale]\n"
6070 "vdup.32 q13, r0\n"
6071 "ldr r0, %[output_range_offset]\n"
6072 "vdup.32 q14, r0\n"
6073 "1:"
6074 "mov r0, %[count]\n"
6075 "mov r1, %[bias]\n"
6076 "subs r0, r0, #4\n"
6077 "beq 3f\n"
6078 "2:"
6079 "subs r0, r0, #16\n"
6080
6081 // BiasAdd::Transform
6082 "vld1.32 {d0, d1}, [%[input]]!\n"
6083 "vld1.32 {d8, d9}, [r1]!\n"
6084 "pld [%[input], #32]\n"
6085 "vmovl.u8 q1, d1\n"
6086 "vmovl.u8 q0, d0\n"
6087 "vmovl.u8 q5, d9\n"
6088 "vmovl.u8 q4, d8\n"
6089 "vmovl.s16 q3, d3\n"
6090 "vmovl.s16 q2, d2\n"
6091 "vmovl.s16 q7, d11\n"
6092 "vmovl.s16 q6, d10\n"
6093 "vmovl.s16 q1, d1\n"
6094 "vmovl.s16 q0, d0\n"
6095 "vmovl.s16 q5, d9\n"
6096 "vmovl.s16 q4, d8\n"
6097 "vcvt.f32.s32 q0, q0\n"
6098 "vcvt.f32.s32 q1, q1\n"
6099 "vcvt.f32.s32 q2, q2\n"
6100 "vcvt.f32.s32 q3, q3\n"
6101 "vcvt.f32.s32 q4, q4\n"
6102 "vcvt.f32.s32 q5, q5\n"
6103 "vcvt.f32.s32 q6, q6\n"
6104 "vcvt.f32.s32 q7, q7\n"
6105 "vmul.f32 q0, q0, q9\n"
6106 "vmul.f32 q1, q1, q9\n"
6107 "vmul.f32 q2, q2, q9\n"
6108 "vmul.f32 q3, q3, q9\n"
6109 "vmul.f32 q4, q4, q11\n"
6110 "vmul.f32 q5, q5, q11\n"
6111 "vmul.f32 q6, q6, q11\n"
6112 "vmul.f32 q7, q7, q11\n"
6113 "vadd.f32 q0, q0, q8\n"
6114 "vadd.f32 q1, q1, q8\n"
6115 "vadd.f32 q2, q2, q8\n"
6116 "vadd.f32 q3, q3, q8\n"
6117 "vadd.f32 q4, q4, q10\n"
6118 "vadd.f32 q5, q5, q10\n"
6119 "vadd.f32 q6, q6, q10\n"
6120 "vadd.f32 q7, q7, q10\n"
6121 "vadd.f32 q0, q0, q4\n"
6122 "vadd.f32 q1, q1, q5\n"
6123 "vadd.f32 q2, q2, q6\n"
6124 "vadd.f32 q3, q3, q7\n"
6125 "vsub.f32 q0, q0, q12\n"
6126 "vsub.f32 q1, q1, q12\n"
6127 "vsub.f32 q2, q2, q12\n"
6128 "vsub.f32 q3, q3, q12\n"
6129 "vmul.f32 q0, q0, q13\n"
6130 "vmul.f32 q1, q1, q13\n"
6131 "vmul.f32 q2, q2, q13\n"
6132 "vmul.f32 q3, q3, q13\n"
6133 "vadd.f32 q0, q0, q14\n"
6134 "vadd.f32 q1, q1, q14\n"
6135 "vadd.f32 q2, q2, q14\n"
6136 "vadd.f32 q3, q3, q14\n"
6137 "vcvt.s32.f32 q0, q0\n"
6138 "vcvt.s32.f32 q1, q1\n"
6139 "vcvt.s32.f32 q2, q2\n"
6140 "vcvt.s32.f32 q3, q3\n"
6141
6142 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6143 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
6144 "pld [%[output]]\n"
6145 "bne 2b\n"
6146 "3:"
6147
6148 // BiasAdd::Transform
6149 "vld1.32 {d0[0]}, [%[input]]!\n"
6150 "vld1.32 {d2[0]}, [r1]!\n"
6151 "pld [%[input], #32]\n"
6152 "vmovl.u8 q0, d0\n"
6153 "vmovl.u8 q1, d2\n"
6154 "vmovl.s16 q0, d0\n"
6155 "vmovl.s16 q1, d2\n"
6156 "vcvt.f32.s32 q0, q0\n"
6157 "vcvt.f32.s32 q1, q1\n"
6158 "vmul.f32 q0, q0, q9\n"
6159 "vmul.f32 q1, q1, q11\n"
6160 "vadd.f32 q0, q0, q8\n"
6161 "vadd.f32 q1, q1, q10\n"
6162 "vadd.f32 q0, q0, q1\n"
6163 "vsub.f32 q0, q0, q12\n"
6164 "vmul.f32 q0, q0, q13\n"
6165 "vadd.f32 q0, q0, q14\n"
6166 "vcvt.s32.f32 q0, q0\n"
6167
6168 "vst1.32 {d0, d1}, [%[output]]!\n"
6169 "pld [%[output]]\n"
6170 "subs %[rows], %[rows], #1\n"
6171 "bne 1b\n"
6172 : [input] "+r"(input), [output] "+r"(output)
6173 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
6174 [output_range_offset] "m"(params.output_range_offset),
6175 [input_range_scale] "m"(params.input_range_scale),
6176 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
6177 [bias_range_min] "m"(params.bias_range_min),
6178 [output_range_min] "m"(params.output_range_min),
6179 [bias_range_scale] "m"(params.bias_range_scale),
6180 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
6181 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
6182 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
6183 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
6184 "cc", "memory");
6185 }
6186
6187 template <>
6188 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)6189 5>::Transform(const uint8_t* input,
6190 const BiasAdd<uint8_t>& params,
6191 int32_t* output) {
6192 #ifdef DEBUG
6193 #ifdef DEBUG_METAGEMM_VERBOSE
6194 std::cout << __FILE__ << "(" << __LINE__
6195 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
6196 "5>::Transform()"
6197 << std::endl
6198 << std::flush;
6199 #endif
6200 #endif
6201 int params_rows_copy = params.rows;
6202 asm volatile(
6203 "ldr r0, %[input_range_min]\n"
6204 "vdup.32 q8, r0\n"
6205 "ldr r0, %[input_range_scale]\n"
6206 "vdup.32 q9, r0\n"
6207 "ldr r0, %[bias_range_min]\n"
6208 "vdup.32 q10, r0\n"
6209 "ldr r0, %[bias_range_scale]\n"
6210 "vdup.32 q11, r0\n"
6211 "ldr r0, %[output_range_min]\n"
6212 "vdup.32 q12, r0\n"
6213 "ldr r0, %[one_over_output_range_scale]\n"
6214 "vdup.32 q13, r0\n"
6215 "ldr r0, %[output_range_offset]\n"
6216 "vdup.32 q14, r0\n"
6217 "1:"
6218 "mov r0, %[count]\n"
6219 "mov r1, %[bias]\n"
6220 "subs r0, r0, #5\n"
6221 "beq 3f\n"
6222 "2:"
6223 "subs r0, r0, #16\n"
6224
6225 // BiasAdd::Transform
6226 "vld1.32 {d0, d1}, [%[input]]!\n"
6227 "vld1.32 {d8, d9}, [r1]!\n"
6228 "pld [%[input], #32]\n"
6229 "vmovl.u8 q1, d1\n"
6230 "vmovl.u8 q0, d0\n"
6231 "vmovl.u8 q5, d9\n"
6232 "vmovl.u8 q4, d8\n"
6233 "vmovl.s16 q3, d3\n"
6234 "vmovl.s16 q2, d2\n"
6235 "vmovl.s16 q7, d11\n"
6236 "vmovl.s16 q6, d10\n"
6237 "vmovl.s16 q1, d1\n"
6238 "vmovl.s16 q0, d0\n"
6239 "vmovl.s16 q5, d9\n"
6240 "vmovl.s16 q4, d8\n"
6241 "vcvt.f32.s32 q0, q0\n"
6242 "vcvt.f32.s32 q1, q1\n"
6243 "vcvt.f32.s32 q2, q2\n"
6244 "vcvt.f32.s32 q3, q3\n"
6245 "vcvt.f32.s32 q4, q4\n"
6246 "vcvt.f32.s32 q5, q5\n"
6247 "vcvt.f32.s32 q6, q6\n"
6248 "vcvt.f32.s32 q7, q7\n"
6249 "vmul.f32 q0, q0, q9\n"
6250 "vmul.f32 q1, q1, q9\n"
6251 "vmul.f32 q2, q2, q9\n"
6252 "vmul.f32 q3, q3, q9\n"
6253 "vmul.f32 q4, q4, q11\n"
6254 "vmul.f32 q5, q5, q11\n"
6255 "vmul.f32 q6, q6, q11\n"
6256 "vmul.f32 q7, q7, q11\n"
6257 "vadd.f32 q0, q0, q8\n"
6258 "vadd.f32 q1, q1, q8\n"
6259 "vadd.f32 q2, q2, q8\n"
6260 "vadd.f32 q3, q3, q8\n"
6261 "vadd.f32 q4, q4, q10\n"
6262 "vadd.f32 q5, q5, q10\n"
6263 "vadd.f32 q6, q6, q10\n"
6264 "vadd.f32 q7, q7, q10\n"
6265 "vadd.f32 q0, q0, q4\n"
6266 "vadd.f32 q1, q1, q5\n"
6267 "vadd.f32 q2, q2, q6\n"
6268 "vadd.f32 q3, q3, q7\n"
6269 "vsub.f32 q0, q0, q12\n"
6270 "vsub.f32 q1, q1, q12\n"
6271 "vsub.f32 q2, q2, q12\n"
6272 "vsub.f32 q3, q3, q12\n"
6273 "vmul.f32 q0, q0, q13\n"
6274 "vmul.f32 q1, q1, q13\n"
6275 "vmul.f32 q2, q2, q13\n"
6276 "vmul.f32 q3, q3, q13\n"
6277 "vadd.f32 q0, q0, q14\n"
6278 "vadd.f32 q1, q1, q14\n"
6279 "vadd.f32 q2, q2, q14\n"
6280 "vadd.f32 q3, q3, q14\n"
6281 "vcvt.s32.f32 q0, q0\n"
6282 "vcvt.s32.f32 q1, q1\n"
6283 "vcvt.s32.f32 q2, q2\n"
6284 "vcvt.s32.f32 q3, q3\n"
6285
6286 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6287 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
6288 "pld [%[output]]\n"
6289 "bne 2b\n"
6290 "3:"
6291
6292 // BiasAdd::Transform
6293 "vld1.32 {d0[0]}, [%[input]]!\n"
6294 "vld1.8 {d0[4]}, [%[input]]!\n"
6295 "vld1.32 {d4[0]}, [r1]!\n"
6296 "vld1.8 {d4[4]}, [r1]!\n"
6297 "pld [%[input], #32]\n"
6298 "vmovl.u8 q0, d0\n"
6299 "vmovl.u8 q2, d4\n"
6300 "vmovl.s16 q1, d1\n"
6301 "vmovl.s16 q0, d0\n"
6302 "vmovl.s16 q3, d5\n"
6303 "vmovl.s16 q2, d4\n"
6304 "vcvt.f32.s32 q0, q0\n"
6305 "vcvt.f32.s32 q1, q1\n"
6306 "vcvt.f32.s32 q2, q2\n"
6307 "vcvt.f32.s32 q3, q3\n"
6308 "vmul.f32 q0, q0, q9\n"
6309 "vmul.f32 q1, q1, q9\n"
6310 "vmul.f32 q2, q2, q11\n"
6311 "vmul.f32 q3, q3, q11\n"
6312 "vadd.f32 q0, q0, q8\n"
6313 "vadd.f32 q1, q1, q8\n"
6314 "vadd.f32 q2, q2, q10\n"
6315 "vadd.f32 q3, q3, q10\n"
6316 "vadd.f32 q0, q0, q2\n"
6317 "vadd.f32 q1, q1, q3\n"
6318 "vsub.f32 q0, q0, q12\n"
6319 "vsub.f32 q1, q1, q12\n"
6320 "vmul.f32 q0, q0, q13\n"
6321 "vmul.f32 q1, q1, q13\n"
6322 "vadd.f32 q0, q0, q14\n"
6323 "vadd.f32 q1, q1, q14\n"
6324 "vcvt.s32.f32 q0, q0\n"
6325 "vcvt.s32.f32 q1, q1\n"
6326
6327 "vst1.32 {d0, d1}, [%[output]]!\n"
6328 "vst1.32 {d2[0]}, [%[output]]!\n"
6329 "pld [%[output]]\n"
6330 "subs %[rows], %[rows], #1\n"
6331 "bne 1b\n"
6332 : [input] "+r"(input), [output] "+r"(output)
6333 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
6334 [output_range_offset] "m"(params.output_range_offset),
6335 [input_range_scale] "m"(params.input_range_scale),
6336 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
6337 [bias_range_min] "m"(params.bias_range_min),
6338 [output_range_min] "m"(params.output_range_min),
6339 [bias_range_scale] "m"(params.bias_range_scale),
6340 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
6341 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
6342 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
6343 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
6344 "cc", "memory");
6345 }
6346
6347 template <>
6348 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)6349 6>::Transform(const uint8_t* input,
6350 const BiasAdd<uint8_t>& params,
6351 int32_t* output) {
6352 #ifdef DEBUG
6353 #ifdef DEBUG_METAGEMM_VERBOSE
6354 std::cout << __FILE__ << "(" << __LINE__
6355 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
6356 "6>::Transform()"
6357 << std::endl
6358 << std::flush;
6359 #endif
6360 #endif
6361 int params_rows_copy = params.rows;
6362 asm volatile(
6363 "ldr r0, %[input_range_min]\n"
6364 "vdup.32 q8, r0\n"
6365 "ldr r0, %[input_range_scale]\n"
6366 "vdup.32 q9, r0\n"
6367 "ldr r0, %[bias_range_min]\n"
6368 "vdup.32 q10, r0\n"
6369 "ldr r0, %[bias_range_scale]\n"
6370 "vdup.32 q11, r0\n"
6371 "ldr r0, %[output_range_min]\n"
6372 "vdup.32 q12, r0\n"
6373 "ldr r0, %[one_over_output_range_scale]\n"
6374 "vdup.32 q13, r0\n"
6375 "ldr r0, %[output_range_offset]\n"
6376 "vdup.32 q14, r0\n"
6377 "1:"
6378 "mov r0, %[count]\n"
6379 "mov r1, %[bias]\n"
6380 "subs r0, r0, #6\n"
6381 "beq 3f\n"
6382 "2:"
6383 "subs r0, r0, #16\n"
6384
6385 // BiasAdd::Transform
6386 "vld1.32 {d0, d1}, [%[input]]!\n"
6387 "vld1.32 {d8, d9}, [r1]!\n"
6388 "pld [%[input], #32]\n"
6389 "vmovl.u8 q1, d1\n"
6390 "vmovl.u8 q0, d0\n"
6391 "vmovl.u8 q5, d9\n"
6392 "vmovl.u8 q4, d8\n"
6393 "vmovl.s16 q3, d3\n"
6394 "vmovl.s16 q2, d2\n"
6395 "vmovl.s16 q7, d11\n"
6396 "vmovl.s16 q6, d10\n"
6397 "vmovl.s16 q1, d1\n"
6398 "vmovl.s16 q0, d0\n"
6399 "vmovl.s16 q5, d9\n"
6400 "vmovl.s16 q4, d8\n"
6401 "vcvt.f32.s32 q0, q0\n"
6402 "vcvt.f32.s32 q1, q1\n"
6403 "vcvt.f32.s32 q2, q2\n"
6404 "vcvt.f32.s32 q3, q3\n"
6405 "vcvt.f32.s32 q4, q4\n"
6406 "vcvt.f32.s32 q5, q5\n"
6407 "vcvt.f32.s32 q6, q6\n"
6408 "vcvt.f32.s32 q7, q7\n"
6409 "vmul.f32 q0, q0, q9\n"
6410 "vmul.f32 q1, q1, q9\n"
6411 "vmul.f32 q2, q2, q9\n"
6412 "vmul.f32 q3, q3, q9\n"
6413 "vmul.f32 q4, q4, q11\n"
6414 "vmul.f32 q5, q5, q11\n"
6415 "vmul.f32 q6, q6, q11\n"
6416 "vmul.f32 q7, q7, q11\n"
6417 "vadd.f32 q0, q0, q8\n"
6418 "vadd.f32 q1, q1, q8\n"
6419 "vadd.f32 q2, q2, q8\n"
6420 "vadd.f32 q3, q3, q8\n"
6421 "vadd.f32 q4, q4, q10\n"
6422 "vadd.f32 q5, q5, q10\n"
6423 "vadd.f32 q6, q6, q10\n"
6424 "vadd.f32 q7, q7, q10\n"
6425 "vadd.f32 q0, q0, q4\n"
6426 "vadd.f32 q1, q1, q5\n"
6427 "vadd.f32 q2, q2, q6\n"
6428 "vadd.f32 q3, q3, q7\n"
6429 "vsub.f32 q0, q0, q12\n"
6430 "vsub.f32 q1, q1, q12\n"
6431 "vsub.f32 q2, q2, q12\n"
6432 "vsub.f32 q3, q3, q12\n"
6433 "vmul.f32 q0, q0, q13\n"
6434 "vmul.f32 q1, q1, q13\n"
6435 "vmul.f32 q2, q2, q13\n"
6436 "vmul.f32 q3, q3, q13\n"
6437 "vadd.f32 q0, q0, q14\n"
6438 "vadd.f32 q1, q1, q14\n"
6439 "vadd.f32 q2, q2, q14\n"
6440 "vadd.f32 q3, q3, q14\n"
6441 "vcvt.s32.f32 q0, q0\n"
6442 "vcvt.s32.f32 q1, q1\n"
6443 "vcvt.s32.f32 q2, q2\n"
6444 "vcvt.s32.f32 q3, q3\n"
6445
6446 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6447 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
6448 "pld [%[output]]\n"
6449 "bne 2b\n"
6450 "3:"
6451
6452 // BiasAdd::Transform
6453 "vld1.32 {d0[0]}, [%[input]]!\n"
6454 "vld1.16 {d0[2]}, [%[input]]!\n"
6455 "vld1.32 {d4[0]}, [r1]!\n"
6456 "vld1.16 {d4[2]}, [r1]!\n"
6457 "pld [%[input], #32]\n"
6458 "vmovl.u8 q0, d0\n"
6459 "vmovl.u8 q2, d4\n"
6460 "vmovl.s16 q1, d1\n"
6461 "vmovl.s16 q0, d0\n"
6462 "vmovl.s16 q3, d5\n"
6463 "vmovl.s16 q2, d4\n"
6464 "vcvt.f32.s32 q0, q0\n"
6465 "vcvt.f32.s32 q1, q1\n"
6466 "vcvt.f32.s32 q2, q2\n"
6467 "vcvt.f32.s32 q3, q3\n"
6468 "vmul.f32 q0, q0, q9\n"
6469 "vmul.f32 q1, q1, q9\n"
6470 "vmul.f32 q2, q2, q11\n"
6471 "vmul.f32 q3, q3, q11\n"
6472 "vadd.f32 q0, q0, q8\n"
6473 "vadd.f32 q1, q1, q8\n"
6474 "vadd.f32 q2, q2, q10\n"
6475 "vadd.f32 q3, q3, q10\n"
6476 "vadd.f32 q0, q0, q2\n"
6477 "vadd.f32 q1, q1, q3\n"
6478 "vsub.f32 q0, q0, q12\n"
6479 "vsub.f32 q1, q1, q12\n"
6480 "vmul.f32 q0, q0, q13\n"
6481 "vmul.f32 q1, q1, q13\n"
6482 "vadd.f32 q0, q0, q14\n"
6483 "vadd.f32 q1, q1, q14\n"
6484 "vcvt.s32.f32 q0, q0\n"
6485 "vcvt.s32.f32 q1, q1\n"
6486
6487 "vst1.32 {d0, d1, d2}, [%[output]]!\n"
6488 "pld [%[output]]\n"
6489 "subs %[rows], %[rows], #1\n"
6490 "bne 1b\n"
6491 : [input] "+r"(input), [output] "+r"(output)
6492 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
6493 [output_range_offset] "m"(params.output_range_offset),
6494 [input_range_scale] "m"(params.input_range_scale),
6495 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
6496 [bias_range_min] "m"(params.bias_range_min),
6497 [output_range_min] "m"(params.output_range_min),
6498 [bias_range_scale] "m"(params.bias_range_scale),
6499 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
6500 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
6501 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
6502 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
6503 "cc", "memory");
6504 }
6505
6506 template <>
6507 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)6508 7>::Transform(const uint8_t* input,
6509 const BiasAdd<uint8_t>& params,
6510 int32_t* output) {
6511 #ifdef DEBUG
6512 #ifdef DEBUG_METAGEMM_VERBOSE
6513 std::cout << __FILE__ << "(" << __LINE__
6514 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
6515 "7>::Transform()"
6516 << std::endl
6517 << std::flush;
6518 #endif
6519 #endif
6520 int params_rows_copy = params.rows;
6521 asm volatile(
6522 "ldr r0, %[input_range_min]\n"
6523 "vdup.32 q8, r0\n"
6524 "ldr r0, %[input_range_scale]\n"
6525 "vdup.32 q9, r0\n"
6526 "ldr r0, %[bias_range_min]\n"
6527 "vdup.32 q10, r0\n"
6528 "ldr r0, %[bias_range_scale]\n"
6529 "vdup.32 q11, r0\n"
6530 "ldr r0, %[output_range_min]\n"
6531 "vdup.32 q12, r0\n"
6532 "ldr r0, %[one_over_output_range_scale]\n"
6533 "vdup.32 q13, r0\n"
6534 "ldr r0, %[output_range_offset]\n"
6535 "vdup.32 q14, r0\n"
6536 "1:"
6537 "mov r0, %[count]\n"
6538 "mov r1, %[bias]\n"
6539 "subs r0, r0, #7\n"
6540 "beq 3f\n"
6541 "2:"
6542 "subs r0, r0, #16\n"
6543
6544 // BiasAdd::Transform
6545 "vld1.32 {d0, d1}, [%[input]]!\n"
6546 "vld1.32 {d8, d9}, [r1]!\n"
6547 "pld [%[input], #32]\n"
6548 "vmovl.u8 q1, d1\n"
6549 "vmovl.u8 q0, d0\n"
6550 "vmovl.u8 q5, d9\n"
6551 "vmovl.u8 q4, d8\n"
6552 "vmovl.s16 q3, d3\n"
6553 "vmovl.s16 q2, d2\n"
6554 "vmovl.s16 q7, d11\n"
6555 "vmovl.s16 q6, d10\n"
6556 "vmovl.s16 q1, d1\n"
6557 "vmovl.s16 q0, d0\n"
6558 "vmovl.s16 q5, d9\n"
6559 "vmovl.s16 q4, d8\n"
6560 "vcvt.f32.s32 q0, q0\n"
6561 "vcvt.f32.s32 q1, q1\n"
6562 "vcvt.f32.s32 q2, q2\n"
6563 "vcvt.f32.s32 q3, q3\n"
6564 "vcvt.f32.s32 q4, q4\n"
6565 "vcvt.f32.s32 q5, q5\n"
6566 "vcvt.f32.s32 q6, q6\n"
6567 "vcvt.f32.s32 q7, q7\n"
6568 "vmul.f32 q0, q0, q9\n"
6569 "vmul.f32 q1, q1, q9\n"
6570 "vmul.f32 q2, q2, q9\n"
6571 "vmul.f32 q3, q3, q9\n"
6572 "vmul.f32 q4, q4, q11\n"
6573 "vmul.f32 q5, q5, q11\n"
6574 "vmul.f32 q6, q6, q11\n"
6575 "vmul.f32 q7, q7, q11\n"
6576 "vadd.f32 q0, q0, q8\n"
6577 "vadd.f32 q1, q1, q8\n"
6578 "vadd.f32 q2, q2, q8\n"
6579 "vadd.f32 q3, q3, q8\n"
6580 "vadd.f32 q4, q4, q10\n"
6581 "vadd.f32 q5, q5, q10\n"
6582 "vadd.f32 q6, q6, q10\n"
6583 "vadd.f32 q7, q7, q10\n"
6584 "vadd.f32 q0, q0, q4\n"
6585 "vadd.f32 q1, q1, q5\n"
6586 "vadd.f32 q2, q2, q6\n"
6587 "vadd.f32 q3, q3, q7\n"
6588 "vsub.f32 q0, q0, q12\n"
6589 "vsub.f32 q1, q1, q12\n"
6590 "vsub.f32 q2, q2, q12\n"
6591 "vsub.f32 q3, q3, q12\n"
6592 "vmul.f32 q0, q0, q13\n"
6593 "vmul.f32 q1, q1, q13\n"
6594 "vmul.f32 q2, q2, q13\n"
6595 "vmul.f32 q3, q3, q13\n"
6596 "vadd.f32 q0, q0, q14\n"
6597 "vadd.f32 q1, q1, q14\n"
6598 "vadd.f32 q2, q2, q14\n"
6599 "vadd.f32 q3, q3, q14\n"
6600 "vcvt.s32.f32 q0, q0\n"
6601 "vcvt.s32.f32 q1, q1\n"
6602 "vcvt.s32.f32 q2, q2\n"
6603 "vcvt.s32.f32 q3, q3\n"
6604
6605 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6606 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
6607 "pld [%[output]]\n"
6608 "bne 2b\n"
6609 "3:"
6610
6611 // BiasAdd::Transform
6612 "vld1.32 {d0[0]}, [%[input]]!\n"
6613 "vld1.16 {d0[2]}, [%[input]]!\n"
6614 "vld1.8 {d0[6]}, [%[input]]!\n"
6615 "vld1.32 {d4[0]}, [r1]!\n"
6616 "vld1.16 {d4[2]}, [r1]!\n"
6617 "vld1.8 {d4[6]}, [r1]!\n"
6618 "pld [%[input], #32]\n"
6619 "vmovl.u8 q0, d0\n"
6620 "vmovl.u8 q2, d4\n"
6621 "vmovl.s16 q1, d1\n"
6622 "vmovl.s16 q0, d0\n"
6623 "vmovl.s16 q3, d5\n"
6624 "vmovl.s16 q2, d4\n"
6625 "vcvt.f32.s32 q0, q0\n"
6626 "vcvt.f32.s32 q1, q1\n"
6627 "vcvt.f32.s32 q2, q2\n"
6628 "vcvt.f32.s32 q3, q3\n"
6629 "vmul.f32 q0, q0, q9\n"
6630 "vmul.f32 q1, q1, q9\n"
6631 "vmul.f32 q2, q2, q11\n"
6632 "vmul.f32 q3, q3, q11\n"
6633 "vadd.f32 q0, q0, q8\n"
6634 "vadd.f32 q1, q1, q8\n"
6635 "vadd.f32 q2, q2, q10\n"
6636 "vadd.f32 q3, q3, q10\n"
6637 "vadd.f32 q0, q0, q2\n"
6638 "vadd.f32 q1, q1, q3\n"
6639 "vsub.f32 q0, q0, q12\n"
6640 "vsub.f32 q1, q1, q12\n"
6641 "vmul.f32 q0, q0, q13\n"
6642 "vmul.f32 q1, q1, q13\n"
6643 "vadd.f32 q0, q0, q14\n"
6644 "vadd.f32 q1, q1, q14\n"
6645 "vcvt.s32.f32 q0, q0\n"
6646 "vcvt.s32.f32 q1, q1\n"
6647
6648 "vst1.32 {d0, d1, d2}, [%[output]]!\n"
6649 "vst1.32 {d3[0]}, [%[output]]!\n"
6650 "pld [%[output]]\n"
6651 "subs %[rows], %[rows], #1\n"
6652 "bne 1b\n"
6653 : [input] "+r"(input), [output] "+r"(output)
6654 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
6655 [output_range_offset] "m"(params.output_range_offset),
6656 [input_range_scale] "m"(params.input_range_scale),
6657 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
6658 [bias_range_min] "m"(params.bias_range_min),
6659 [output_range_min] "m"(params.output_range_min),
6660 [bias_range_scale] "m"(params.bias_range_scale),
6661 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
6662 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
6663 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
6664 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
6665 "cc", "memory");
6666 }
6667
6668 template <>
6669 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)6670 8>::Transform(const uint8_t* input,
6671 const BiasAdd<uint8_t>& params,
6672 int32_t* output) {
6673 #ifdef DEBUG
6674 #ifdef DEBUG_METAGEMM_VERBOSE
6675 std::cout << __FILE__ << "(" << __LINE__
6676 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
6677 "8>::Transform()"
6678 << std::endl
6679 << std::flush;
6680 #endif
6681 #endif
6682 int params_rows_copy = params.rows;
6683 asm volatile(
6684 "ldr r0, %[input_range_min]\n"
6685 "vdup.32 q8, r0\n"
6686 "ldr r0, %[input_range_scale]\n"
6687 "vdup.32 q9, r0\n"
6688 "ldr r0, %[bias_range_min]\n"
6689 "vdup.32 q10, r0\n"
6690 "ldr r0, %[bias_range_scale]\n"
6691 "vdup.32 q11, r0\n"
6692 "ldr r0, %[output_range_min]\n"
6693 "vdup.32 q12, r0\n"
6694 "ldr r0, %[one_over_output_range_scale]\n"
6695 "vdup.32 q13, r0\n"
6696 "ldr r0, %[output_range_offset]\n"
6697 "vdup.32 q14, r0\n"
6698 "1:"
6699 "mov r0, %[count]\n"
6700 "mov r1, %[bias]\n"
6701 "subs r0, r0, #8\n"
6702 "beq 3f\n"
6703 "2:"
6704 "subs r0, r0, #16\n"
6705
6706 // BiasAdd::Transform
6707 "vld1.32 {d0, d1}, [%[input]]!\n"
6708 "vld1.32 {d8, d9}, [r1]!\n"
6709 "pld [%[input], #32]\n"
6710 "vmovl.u8 q1, d1\n"
6711 "vmovl.u8 q0, d0\n"
6712 "vmovl.u8 q5, d9\n"
6713 "vmovl.u8 q4, d8\n"
6714 "vmovl.s16 q3, d3\n"
6715 "vmovl.s16 q2, d2\n"
6716 "vmovl.s16 q7, d11\n"
6717 "vmovl.s16 q6, d10\n"
6718 "vmovl.s16 q1, d1\n"
6719 "vmovl.s16 q0, d0\n"
6720 "vmovl.s16 q5, d9\n"
6721 "vmovl.s16 q4, d8\n"
6722 "vcvt.f32.s32 q0, q0\n"
6723 "vcvt.f32.s32 q1, q1\n"
6724 "vcvt.f32.s32 q2, q2\n"
6725 "vcvt.f32.s32 q3, q3\n"
6726 "vcvt.f32.s32 q4, q4\n"
6727 "vcvt.f32.s32 q5, q5\n"
6728 "vcvt.f32.s32 q6, q6\n"
6729 "vcvt.f32.s32 q7, q7\n"
6730 "vmul.f32 q0, q0, q9\n"
6731 "vmul.f32 q1, q1, q9\n"
6732 "vmul.f32 q2, q2, q9\n"
6733 "vmul.f32 q3, q3, q9\n"
6734 "vmul.f32 q4, q4, q11\n"
6735 "vmul.f32 q5, q5, q11\n"
6736 "vmul.f32 q6, q6, q11\n"
6737 "vmul.f32 q7, q7, q11\n"
6738 "vadd.f32 q0, q0, q8\n"
6739 "vadd.f32 q1, q1, q8\n"
6740 "vadd.f32 q2, q2, q8\n"
6741 "vadd.f32 q3, q3, q8\n"
6742 "vadd.f32 q4, q4, q10\n"
6743 "vadd.f32 q5, q5, q10\n"
6744 "vadd.f32 q6, q6, q10\n"
6745 "vadd.f32 q7, q7, q10\n"
6746 "vadd.f32 q0, q0, q4\n"
6747 "vadd.f32 q1, q1, q5\n"
6748 "vadd.f32 q2, q2, q6\n"
6749 "vadd.f32 q3, q3, q7\n"
6750 "vsub.f32 q0, q0, q12\n"
6751 "vsub.f32 q1, q1, q12\n"
6752 "vsub.f32 q2, q2, q12\n"
6753 "vsub.f32 q3, q3, q12\n"
6754 "vmul.f32 q0, q0, q13\n"
6755 "vmul.f32 q1, q1, q13\n"
6756 "vmul.f32 q2, q2, q13\n"
6757 "vmul.f32 q3, q3, q13\n"
6758 "vadd.f32 q0, q0, q14\n"
6759 "vadd.f32 q1, q1, q14\n"
6760 "vadd.f32 q2, q2, q14\n"
6761 "vadd.f32 q3, q3, q14\n"
6762 "vcvt.s32.f32 q0, q0\n"
6763 "vcvt.s32.f32 q1, q1\n"
6764 "vcvt.s32.f32 q2, q2\n"
6765 "vcvt.s32.f32 q3, q3\n"
6766
6767 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6768 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
6769 "pld [%[output]]\n"
6770 "bne 2b\n"
6771 "3:"
6772
6773 // BiasAdd::Transform
6774 "vld1.32 {d0}, [%[input]]!\n"
6775 "vld1.32 {d4}, [r1]!\n"
6776 "pld [%[input], #32]\n"
6777 "vmovl.u8 q0, d0\n"
6778 "vmovl.u8 q2, d4\n"
6779 "vmovl.s16 q1, d1\n"
6780 "vmovl.s16 q0, d0\n"
6781 "vmovl.s16 q3, d5\n"
6782 "vmovl.s16 q2, d4\n"
6783 "vcvt.f32.s32 q0, q0\n"
6784 "vcvt.f32.s32 q1, q1\n"
6785 "vcvt.f32.s32 q2, q2\n"
6786 "vcvt.f32.s32 q3, q3\n"
6787 "vmul.f32 q0, q0, q9\n"
6788 "vmul.f32 q1, q1, q9\n"
6789 "vmul.f32 q2, q2, q11\n"
6790 "vmul.f32 q3, q3, q11\n"
6791 "vadd.f32 q0, q0, q8\n"
6792 "vadd.f32 q1, q1, q8\n"
6793 "vadd.f32 q2, q2, q10\n"
6794 "vadd.f32 q3, q3, q10\n"
6795 "vadd.f32 q0, q0, q2\n"
6796 "vadd.f32 q1, q1, q3\n"
6797 "vsub.f32 q0, q0, q12\n"
6798 "vsub.f32 q1, q1, q12\n"
6799 "vmul.f32 q0, q0, q13\n"
6800 "vmul.f32 q1, q1, q13\n"
6801 "vadd.f32 q0, q0, q14\n"
6802 "vadd.f32 q1, q1, q14\n"
6803 "vcvt.s32.f32 q0, q0\n"
6804 "vcvt.s32.f32 q1, q1\n"
6805
6806 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6807 "pld [%[output]]\n"
6808 "subs %[rows], %[rows], #1\n"
6809 "bne 1b\n"
6810 : [input] "+r"(input), [output] "+r"(output)
6811 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
6812 [output_range_offset] "m"(params.output_range_offset),
6813 [input_range_scale] "m"(params.input_range_scale),
6814 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
6815 [bias_range_min] "m"(params.bias_range_min),
6816 [output_range_min] "m"(params.output_range_min),
6817 [bias_range_scale] "m"(params.bias_range_scale),
6818 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
6819 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
6820 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
6821 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
6822 "cc", "memory");
6823 }
6824
6825 template <>
6826 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)6827 9>::Transform(const uint8_t* input,
6828 const BiasAdd<uint8_t>& params,
6829 int32_t* output) {
6830 #ifdef DEBUG
6831 #ifdef DEBUG_METAGEMM_VERBOSE
6832 std::cout << __FILE__ << "(" << __LINE__
6833 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
6834 "9>::Transform()"
6835 << std::endl
6836 << std::flush;
6837 #endif
6838 #endif
6839 int params_rows_copy = params.rows;
6840 asm volatile(
6841 "ldr r0, %[input_range_min]\n"
6842 "vdup.32 q8, r0\n"
6843 "ldr r0, %[input_range_scale]\n"
6844 "vdup.32 q9, r0\n"
6845 "ldr r0, %[bias_range_min]\n"
6846 "vdup.32 q10, r0\n"
6847 "ldr r0, %[bias_range_scale]\n"
6848 "vdup.32 q11, r0\n"
6849 "ldr r0, %[output_range_min]\n"
6850 "vdup.32 q12, r0\n"
6851 "ldr r0, %[one_over_output_range_scale]\n"
6852 "vdup.32 q13, r0\n"
6853 "ldr r0, %[output_range_offset]\n"
6854 "vdup.32 q14, r0\n"
6855 "1:"
6856 "mov r0, %[count]\n"
6857 "mov r1, %[bias]\n"
6858 "subs r0, r0, #9\n"
6859 "beq 3f\n"
6860 "2:"
6861 "subs r0, r0, #16\n"
6862
6863 // BiasAdd::Transform
6864 "vld1.32 {d0, d1}, [%[input]]!\n"
6865 "vld1.32 {d8, d9}, [r1]!\n"
6866 "pld [%[input], #32]\n"
6867 "vmovl.u8 q1, d1\n"
6868 "vmovl.u8 q0, d0\n"
6869 "vmovl.u8 q5, d9\n"
6870 "vmovl.u8 q4, d8\n"
6871 "vmovl.s16 q3, d3\n"
6872 "vmovl.s16 q2, d2\n"
6873 "vmovl.s16 q7, d11\n"
6874 "vmovl.s16 q6, d10\n"
6875 "vmovl.s16 q1, d1\n"
6876 "vmovl.s16 q0, d0\n"
6877 "vmovl.s16 q5, d9\n"
6878 "vmovl.s16 q4, d8\n"
6879 "vcvt.f32.s32 q0, q0\n"
6880 "vcvt.f32.s32 q1, q1\n"
6881 "vcvt.f32.s32 q2, q2\n"
6882 "vcvt.f32.s32 q3, q3\n"
6883 "vcvt.f32.s32 q4, q4\n"
6884 "vcvt.f32.s32 q5, q5\n"
6885 "vcvt.f32.s32 q6, q6\n"
6886 "vcvt.f32.s32 q7, q7\n"
6887 "vmul.f32 q0, q0, q9\n"
6888 "vmul.f32 q1, q1, q9\n"
6889 "vmul.f32 q2, q2, q9\n"
6890 "vmul.f32 q3, q3, q9\n"
6891 "vmul.f32 q4, q4, q11\n"
6892 "vmul.f32 q5, q5, q11\n"
6893 "vmul.f32 q6, q6, q11\n"
6894 "vmul.f32 q7, q7, q11\n"
6895 "vadd.f32 q0, q0, q8\n"
6896 "vadd.f32 q1, q1, q8\n"
6897 "vadd.f32 q2, q2, q8\n"
6898 "vadd.f32 q3, q3, q8\n"
6899 "vadd.f32 q4, q4, q10\n"
6900 "vadd.f32 q5, q5, q10\n"
6901 "vadd.f32 q6, q6, q10\n"
6902 "vadd.f32 q7, q7, q10\n"
6903 "vadd.f32 q0, q0, q4\n"
6904 "vadd.f32 q1, q1, q5\n"
6905 "vadd.f32 q2, q2, q6\n"
6906 "vadd.f32 q3, q3, q7\n"
6907 "vsub.f32 q0, q0, q12\n"
6908 "vsub.f32 q1, q1, q12\n"
6909 "vsub.f32 q2, q2, q12\n"
6910 "vsub.f32 q3, q3, q12\n"
6911 "vmul.f32 q0, q0, q13\n"
6912 "vmul.f32 q1, q1, q13\n"
6913 "vmul.f32 q2, q2, q13\n"
6914 "vmul.f32 q3, q3, q13\n"
6915 "vadd.f32 q0, q0, q14\n"
6916 "vadd.f32 q1, q1, q14\n"
6917 "vadd.f32 q2, q2, q14\n"
6918 "vadd.f32 q3, q3, q14\n"
6919 "vcvt.s32.f32 q0, q0\n"
6920 "vcvt.s32.f32 q1, q1\n"
6921 "vcvt.s32.f32 q2, q2\n"
6922 "vcvt.s32.f32 q3, q3\n"
6923
6924 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6925 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
6926 "pld [%[output]]\n"
6927 "bne 2b\n"
6928 "3:"
6929
6930 // BiasAdd::Transform
6931 "vld1.32 {d0}, [%[input]]!\n"
6932 "vld1.8 {d1[0]}, [%[input]]!\n"
6933 "vld1.32 {d6}, [r1]!\n"
6934 "vld1.8 {d7[0]}, [r1]!\n"
6935 "pld [%[input], #32]\n"
6936 "vmovl.u8 q1, d1\n"
6937 "vmovl.u8 q0, d0\n"
6938 "vmovl.u8 q4, d7\n"
6939 "vmovl.u8 q3, d6\n"
6940 "vmovl.s16 q2, d2\n"
6941 "vmovl.s16 q5, d8\n"
6942 "vmovl.s16 q1, d1\n"
6943 "vmovl.s16 q0, d0\n"
6944 "vmovl.s16 q4, d7\n"
6945 "vmovl.s16 q3, d6\n"
6946 "vcvt.f32.s32 q0, q0\n"
6947 "vcvt.f32.s32 q1, q1\n"
6948 "vcvt.f32.s32 q2, q2\n"
6949 "vcvt.f32.s32 q3, q3\n"
6950 "vcvt.f32.s32 q4, q4\n"
6951 "vcvt.f32.s32 q5, q5\n"
6952 "vmul.f32 q0, q0, q9\n"
6953 "vmul.f32 q1, q1, q9\n"
6954 "vmul.f32 q2, q2, q9\n"
6955 "vmul.f32 q3, q3, q11\n"
6956 "vmul.f32 q4, q4, q11\n"
6957 "vmul.f32 q5, q5, q11\n"
6958 "vadd.f32 q0, q0, q8\n"
6959 "vadd.f32 q1, q1, q8\n"
6960 "vadd.f32 q2, q2, q8\n"
6961 "vadd.f32 q3, q3, q10\n"
6962 "vadd.f32 q4, q4, q10\n"
6963 "vadd.f32 q5, q5, q10\n"
6964 "vadd.f32 q0, q0, q3\n"
6965 "vadd.f32 q1, q1, q4\n"
6966 "vadd.f32 q2, q2, q5\n"
6967 "vsub.f32 q0, q0, q12\n"
6968 "vsub.f32 q1, q1, q12\n"
6969 "vsub.f32 q2, q2, q12\n"
6970 "vmul.f32 q0, q0, q13\n"
6971 "vmul.f32 q1, q1, q13\n"
6972 "vmul.f32 q2, q2, q13\n"
6973 "vadd.f32 q0, q0, q14\n"
6974 "vadd.f32 q1, q1, q14\n"
6975 "vadd.f32 q2, q2, q14\n"
6976 "vcvt.s32.f32 q0, q0\n"
6977 "vcvt.s32.f32 q1, q1\n"
6978 "vcvt.s32.f32 q2, q2\n"
6979
6980 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
6981 "vst1.32 {d4[0]}, [%[output]]!\n"
6982 "pld [%[output]]\n"
6983 "subs %[rows], %[rows], #1\n"
6984 "bne 1b\n"
6985 : [input] "+r"(input), [output] "+r"(output)
6986 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
6987 [output_range_offset] "m"(params.output_range_offset),
6988 [input_range_scale] "m"(params.input_range_scale),
6989 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
6990 [bias_range_min] "m"(params.bias_range_min),
6991 [output_range_min] "m"(params.output_range_min),
6992 [bias_range_scale] "m"(params.bias_range_scale),
6993 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
6994 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
6995 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
6996 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
6997 "cc", "memory");
6998 }
6999
7000 template <>
7001 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)7002 10>::Transform(const uint8_t* input,
7003 const BiasAdd<uint8_t>& params,
7004 int32_t* output) {
7005 #ifdef DEBUG
7006 #ifdef DEBUG_METAGEMM_VERBOSE
7007 std::cout << __FILE__ << "(" << __LINE__
7008 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
7009 "10>::Transform()"
7010 << std::endl
7011 << std::flush;
7012 #endif
7013 #endif
7014 int params_rows_copy = params.rows;
7015 asm volatile(
7016 "ldr r0, %[input_range_min]\n"
7017 "vdup.32 q8, r0\n"
7018 "ldr r0, %[input_range_scale]\n"
7019 "vdup.32 q9, r0\n"
7020 "ldr r0, %[bias_range_min]\n"
7021 "vdup.32 q10, r0\n"
7022 "ldr r0, %[bias_range_scale]\n"
7023 "vdup.32 q11, r0\n"
7024 "ldr r0, %[output_range_min]\n"
7025 "vdup.32 q12, r0\n"
7026 "ldr r0, %[one_over_output_range_scale]\n"
7027 "vdup.32 q13, r0\n"
7028 "ldr r0, %[output_range_offset]\n"
7029 "vdup.32 q14, r0\n"
7030 "1:"
7031 "mov r0, %[count]\n"
7032 "mov r1, %[bias]\n"
7033 "subs r0, r0, #10\n"
7034 "beq 3f\n"
7035 "2:"
7036 "subs r0, r0, #16\n"
7037
7038 // BiasAdd::Transform
7039 "vld1.32 {d0, d1}, [%[input]]!\n"
7040 "vld1.32 {d8, d9}, [r1]!\n"
7041 "pld [%[input], #32]\n"
7042 "vmovl.u8 q1, d1\n"
7043 "vmovl.u8 q0, d0\n"
7044 "vmovl.u8 q5, d9\n"
7045 "vmovl.u8 q4, d8\n"
7046 "vmovl.s16 q3, d3\n"
7047 "vmovl.s16 q2, d2\n"
7048 "vmovl.s16 q7, d11\n"
7049 "vmovl.s16 q6, d10\n"
7050 "vmovl.s16 q1, d1\n"
7051 "vmovl.s16 q0, d0\n"
7052 "vmovl.s16 q5, d9\n"
7053 "vmovl.s16 q4, d8\n"
7054 "vcvt.f32.s32 q0, q0\n"
7055 "vcvt.f32.s32 q1, q1\n"
7056 "vcvt.f32.s32 q2, q2\n"
7057 "vcvt.f32.s32 q3, q3\n"
7058 "vcvt.f32.s32 q4, q4\n"
7059 "vcvt.f32.s32 q5, q5\n"
7060 "vcvt.f32.s32 q6, q6\n"
7061 "vcvt.f32.s32 q7, q7\n"
7062 "vmul.f32 q0, q0, q9\n"
7063 "vmul.f32 q1, q1, q9\n"
7064 "vmul.f32 q2, q2, q9\n"
7065 "vmul.f32 q3, q3, q9\n"
7066 "vmul.f32 q4, q4, q11\n"
7067 "vmul.f32 q5, q5, q11\n"
7068 "vmul.f32 q6, q6, q11\n"
7069 "vmul.f32 q7, q7, q11\n"
7070 "vadd.f32 q0, q0, q8\n"
7071 "vadd.f32 q1, q1, q8\n"
7072 "vadd.f32 q2, q2, q8\n"
7073 "vadd.f32 q3, q3, q8\n"
7074 "vadd.f32 q4, q4, q10\n"
7075 "vadd.f32 q5, q5, q10\n"
7076 "vadd.f32 q6, q6, q10\n"
7077 "vadd.f32 q7, q7, q10\n"
7078 "vadd.f32 q0, q0, q4\n"
7079 "vadd.f32 q1, q1, q5\n"
7080 "vadd.f32 q2, q2, q6\n"
7081 "vadd.f32 q3, q3, q7\n"
7082 "vsub.f32 q0, q0, q12\n"
7083 "vsub.f32 q1, q1, q12\n"
7084 "vsub.f32 q2, q2, q12\n"
7085 "vsub.f32 q3, q3, q12\n"
7086 "vmul.f32 q0, q0, q13\n"
7087 "vmul.f32 q1, q1, q13\n"
7088 "vmul.f32 q2, q2, q13\n"
7089 "vmul.f32 q3, q3, q13\n"
7090 "vadd.f32 q0, q0, q14\n"
7091 "vadd.f32 q1, q1, q14\n"
7092 "vadd.f32 q2, q2, q14\n"
7093 "vadd.f32 q3, q3, q14\n"
7094 "vcvt.s32.f32 q0, q0\n"
7095 "vcvt.s32.f32 q1, q1\n"
7096 "vcvt.s32.f32 q2, q2\n"
7097 "vcvt.s32.f32 q3, q3\n"
7098
7099 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7100 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
7101 "pld [%[output]]\n"
7102 "bne 2b\n"
7103 "3:"
7104
7105 // BiasAdd::Transform
7106 "vld1.32 {d0}, [%[input]]!\n"
7107 "vld1.16 {d1[0]}, [%[input]]!\n"
7108 "vld1.32 {d6}, [r1]!\n"
7109 "vld1.16 {d7[0]}, [r1]!\n"
7110 "pld [%[input], #32]\n"
7111 "vmovl.u8 q1, d1\n"
7112 "vmovl.u8 q0, d0\n"
7113 "vmovl.u8 q4, d7\n"
7114 "vmovl.u8 q3, d6\n"
7115 "vmovl.s16 q2, d2\n"
7116 "vmovl.s16 q5, d8\n"
7117 "vmovl.s16 q1, d1\n"
7118 "vmovl.s16 q0, d0\n"
7119 "vmovl.s16 q4, d7\n"
7120 "vmovl.s16 q3, d6\n"
7121 "vcvt.f32.s32 q0, q0\n"
7122 "vcvt.f32.s32 q1, q1\n"
7123 "vcvt.f32.s32 q2, q2\n"
7124 "vcvt.f32.s32 q3, q3\n"
7125 "vcvt.f32.s32 q4, q4\n"
7126 "vcvt.f32.s32 q5, q5\n"
7127 "vmul.f32 q0, q0, q9\n"
7128 "vmul.f32 q1, q1, q9\n"
7129 "vmul.f32 q2, q2, q9\n"
7130 "vmul.f32 q3, q3, q11\n"
7131 "vmul.f32 q4, q4, q11\n"
7132 "vmul.f32 q5, q5, q11\n"
7133 "vadd.f32 q0, q0, q8\n"
7134 "vadd.f32 q1, q1, q8\n"
7135 "vadd.f32 q2, q2, q8\n"
7136 "vadd.f32 q3, q3, q10\n"
7137 "vadd.f32 q4, q4, q10\n"
7138 "vadd.f32 q5, q5, q10\n"
7139 "vadd.f32 q0, q0, q3\n"
7140 "vadd.f32 q1, q1, q4\n"
7141 "vadd.f32 q2, q2, q5\n"
7142 "vsub.f32 q0, q0, q12\n"
7143 "vsub.f32 q1, q1, q12\n"
7144 "vsub.f32 q2, q2, q12\n"
7145 "vmul.f32 q0, q0, q13\n"
7146 "vmul.f32 q1, q1, q13\n"
7147 "vmul.f32 q2, q2, q13\n"
7148 "vadd.f32 q0, q0, q14\n"
7149 "vadd.f32 q1, q1, q14\n"
7150 "vadd.f32 q2, q2, q14\n"
7151 "vcvt.s32.f32 q0, q0\n"
7152 "vcvt.s32.f32 q1, q1\n"
7153 "vcvt.s32.f32 q2, q2\n"
7154
7155 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7156 "vst1.32 {d4}, [%[output]]!\n"
7157 "pld [%[output]]\n"
7158 "subs %[rows], %[rows], #1\n"
7159 "bne 1b\n"
7160 : [input] "+r"(input), [output] "+r"(output)
7161 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
7162 [output_range_offset] "m"(params.output_range_offset),
7163 [input_range_scale] "m"(params.input_range_scale),
7164 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
7165 [bias_range_min] "m"(params.bias_range_min),
7166 [output_range_min] "m"(params.output_range_min),
7167 [bias_range_scale] "m"(params.bias_range_scale),
7168 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
7169 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
7170 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
7171 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
7172 "cc", "memory");
7173 }
7174
7175 template <>
7176 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)7177 11>::Transform(const uint8_t* input,
7178 const BiasAdd<uint8_t>& params,
7179 int32_t* output) {
7180 #ifdef DEBUG
7181 #ifdef DEBUG_METAGEMM_VERBOSE
7182 std::cout << __FILE__ << "(" << __LINE__
7183 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
7184 "11>::Transform()"
7185 << std::endl
7186 << std::flush;
7187 #endif
7188 #endif
7189 int params_rows_copy = params.rows;
7190 asm volatile(
7191 "ldr r0, %[input_range_min]\n"
7192 "vdup.32 q8, r0\n"
7193 "ldr r0, %[input_range_scale]\n"
7194 "vdup.32 q9, r0\n"
7195 "ldr r0, %[bias_range_min]\n"
7196 "vdup.32 q10, r0\n"
7197 "ldr r0, %[bias_range_scale]\n"
7198 "vdup.32 q11, r0\n"
7199 "ldr r0, %[output_range_min]\n"
7200 "vdup.32 q12, r0\n"
7201 "ldr r0, %[one_over_output_range_scale]\n"
7202 "vdup.32 q13, r0\n"
7203 "ldr r0, %[output_range_offset]\n"
7204 "vdup.32 q14, r0\n"
7205 "1:"
7206 "mov r0, %[count]\n"
7207 "mov r1, %[bias]\n"
7208 "subs r0, r0, #11\n"
7209 "beq 3f\n"
7210 "2:"
7211 "subs r0, r0, #16\n"
7212
7213 // BiasAdd::Transform
7214 "vld1.32 {d0, d1}, [%[input]]!\n"
7215 "vld1.32 {d8, d9}, [r1]!\n"
7216 "pld [%[input], #32]\n"
7217 "vmovl.u8 q1, d1\n"
7218 "vmovl.u8 q0, d0\n"
7219 "vmovl.u8 q5, d9\n"
7220 "vmovl.u8 q4, d8\n"
7221 "vmovl.s16 q3, d3\n"
7222 "vmovl.s16 q2, d2\n"
7223 "vmovl.s16 q7, d11\n"
7224 "vmovl.s16 q6, d10\n"
7225 "vmovl.s16 q1, d1\n"
7226 "vmovl.s16 q0, d0\n"
7227 "vmovl.s16 q5, d9\n"
7228 "vmovl.s16 q4, d8\n"
7229 "vcvt.f32.s32 q0, q0\n"
7230 "vcvt.f32.s32 q1, q1\n"
7231 "vcvt.f32.s32 q2, q2\n"
7232 "vcvt.f32.s32 q3, q3\n"
7233 "vcvt.f32.s32 q4, q4\n"
7234 "vcvt.f32.s32 q5, q5\n"
7235 "vcvt.f32.s32 q6, q6\n"
7236 "vcvt.f32.s32 q7, q7\n"
7237 "vmul.f32 q0, q0, q9\n"
7238 "vmul.f32 q1, q1, q9\n"
7239 "vmul.f32 q2, q2, q9\n"
7240 "vmul.f32 q3, q3, q9\n"
7241 "vmul.f32 q4, q4, q11\n"
7242 "vmul.f32 q5, q5, q11\n"
7243 "vmul.f32 q6, q6, q11\n"
7244 "vmul.f32 q7, q7, q11\n"
7245 "vadd.f32 q0, q0, q8\n"
7246 "vadd.f32 q1, q1, q8\n"
7247 "vadd.f32 q2, q2, q8\n"
7248 "vadd.f32 q3, q3, q8\n"
7249 "vadd.f32 q4, q4, q10\n"
7250 "vadd.f32 q5, q5, q10\n"
7251 "vadd.f32 q6, q6, q10\n"
7252 "vadd.f32 q7, q7, q10\n"
7253 "vadd.f32 q0, q0, q4\n"
7254 "vadd.f32 q1, q1, q5\n"
7255 "vadd.f32 q2, q2, q6\n"
7256 "vadd.f32 q3, q3, q7\n"
7257 "vsub.f32 q0, q0, q12\n"
7258 "vsub.f32 q1, q1, q12\n"
7259 "vsub.f32 q2, q2, q12\n"
7260 "vsub.f32 q3, q3, q12\n"
7261 "vmul.f32 q0, q0, q13\n"
7262 "vmul.f32 q1, q1, q13\n"
7263 "vmul.f32 q2, q2, q13\n"
7264 "vmul.f32 q3, q3, q13\n"
7265 "vadd.f32 q0, q0, q14\n"
7266 "vadd.f32 q1, q1, q14\n"
7267 "vadd.f32 q2, q2, q14\n"
7268 "vadd.f32 q3, q3, q14\n"
7269 "vcvt.s32.f32 q0, q0\n"
7270 "vcvt.s32.f32 q1, q1\n"
7271 "vcvt.s32.f32 q2, q2\n"
7272 "vcvt.s32.f32 q3, q3\n"
7273
7274 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7275 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
7276 "pld [%[output]]\n"
7277 "bne 2b\n"
7278 "3:"
7279
7280 // BiasAdd::Transform
7281 "vld1.32 {d0}, [%[input]]!\n"
7282 "vld1.16 {d1[0]}, [%[input]]!\n"
7283 "vld1.8 {d1[2]}, [%[input]]!\n"
7284 "vld1.32 {d6}, [r1]!\n"
7285 "vld1.16 {d7[0]}, [r1]!\n"
7286 "vld1.8 {d7[2]}, [r1]!\n"
7287 "pld [%[input], #32]\n"
7288 "vmovl.u8 q1, d1\n"
7289 "vmovl.u8 q0, d0\n"
7290 "vmovl.u8 q4, d7\n"
7291 "vmovl.u8 q3, d6\n"
7292 "vmovl.s16 q2, d2\n"
7293 "vmovl.s16 q5, d8\n"
7294 "vmovl.s16 q1, d1\n"
7295 "vmovl.s16 q0, d0\n"
7296 "vmovl.s16 q4, d7\n"
7297 "vmovl.s16 q3, d6\n"
7298 "vcvt.f32.s32 q0, q0\n"
7299 "vcvt.f32.s32 q1, q1\n"
7300 "vcvt.f32.s32 q2, q2\n"
7301 "vcvt.f32.s32 q3, q3\n"
7302 "vcvt.f32.s32 q4, q4\n"
7303 "vcvt.f32.s32 q5, q5\n"
7304 "vmul.f32 q0, q0, q9\n"
7305 "vmul.f32 q1, q1, q9\n"
7306 "vmul.f32 q2, q2, q9\n"
7307 "vmul.f32 q3, q3, q11\n"
7308 "vmul.f32 q4, q4, q11\n"
7309 "vmul.f32 q5, q5, q11\n"
7310 "vadd.f32 q0, q0, q8\n"
7311 "vadd.f32 q1, q1, q8\n"
7312 "vadd.f32 q2, q2, q8\n"
7313 "vadd.f32 q3, q3, q10\n"
7314 "vadd.f32 q4, q4, q10\n"
7315 "vadd.f32 q5, q5, q10\n"
7316 "vadd.f32 q0, q0, q3\n"
7317 "vadd.f32 q1, q1, q4\n"
7318 "vadd.f32 q2, q2, q5\n"
7319 "vsub.f32 q0, q0, q12\n"
7320 "vsub.f32 q1, q1, q12\n"
7321 "vsub.f32 q2, q2, q12\n"
7322 "vmul.f32 q0, q0, q13\n"
7323 "vmul.f32 q1, q1, q13\n"
7324 "vmul.f32 q2, q2, q13\n"
7325 "vadd.f32 q0, q0, q14\n"
7326 "vadd.f32 q1, q1, q14\n"
7327 "vadd.f32 q2, q2, q14\n"
7328 "vcvt.s32.f32 q0, q0\n"
7329 "vcvt.s32.f32 q1, q1\n"
7330 "vcvt.s32.f32 q2, q2\n"
7331
7332 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7333 "vst1.32 {d4}, [%[output]]!\n"
7334 "vst1.32 {d5[0]}, [%[output]]!\n"
7335 "pld [%[output]]\n"
7336 "subs %[rows], %[rows], #1\n"
7337 "bne 1b\n"
7338 : [input] "+r"(input), [output] "+r"(output)
7339 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
7340 [output_range_offset] "m"(params.output_range_offset),
7341 [input_range_scale] "m"(params.input_range_scale),
7342 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
7343 [bias_range_min] "m"(params.bias_range_min),
7344 [output_range_min] "m"(params.output_range_min),
7345 [bias_range_scale] "m"(params.bias_range_scale),
7346 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
7347 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
7348 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
7349 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
7350 "cc", "memory");
7351 }
7352
7353 template <>
7354 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)7355 12>::Transform(const uint8_t* input,
7356 const BiasAdd<uint8_t>& params,
7357 int32_t* output) {
7358 #ifdef DEBUG
7359 #ifdef DEBUG_METAGEMM_VERBOSE
7360 std::cout << __FILE__ << "(" << __LINE__
7361 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
7362 "12>::Transform()"
7363 << std::endl
7364 << std::flush;
7365 #endif
7366 #endif
7367 int params_rows_copy = params.rows;
7368 asm volatile(
7369 "ldr r0, %[input_range_min]\n"
7370 "vdup.32 q8, r0\n"
7371 "ldr r0, %[input_range_scale]\n"
7372 "vdup.32 q9, r0\n"
7373 "ldr r0, %[bias_range_min]\n"
7374 "vdup.32 q10, r0\n"
7375 "ldr r0, %[bias_range_scale]\n"
7376 "vdup.32 q11, r0\n"
7377 "ldr r0, %[output_range_min]\n"
7378 "vdup.32 q12, r0\n"
7379 "ldr r0, %[one_over_output_range_scale]\n"
7380 "vdup.32 q13, r0\n"
7381 "ldr r0, %[output_range_offset]\n"
7382 "vdup.32 q14, r0\n"
7383 "1:"
7384 "mov r0, %[count]\n"
7385 "mov r1, %[bias]\n"
7386 "subs r0, r0, #12\n"
7387 "beq 3f\n"
7388 "2:"
7389 "subs r0, r0, #16\n"
7390
7391 // BiasAdd::Transform
7392 "vld1.32 {d0, d1}, [%[input]]!\n"
7393 "vld1.32 {d8, d9}, [r1]!\n"
7394 "pld [%[input], #32]\n"
7395 "vmovl.u8 q1, d1\n"
7396 "vmovl.u8 q0, d0\n"
7397 "vmovl.u8 q5, d9\n"
7398 "vmovl.u8 q4, d8\n"
7399 "vmovl.s16 q3, d3\n"
7400 "vmovl.s16 q2, d2\n"
7401 "vmovl.s16 q7, d11\n"
7402 "vmovl.s16 q6, d10\n"
7403 "vmovl.s16 q1, d1\n"
7404 "vmovl.s16 q0, d0\n"
7405 "vmovl.s16 q5, d9\n"
7406 "vmovl.s16 q4, d8\n"
7407 "vcvt.f32.s32 q0, q0\n"
7408 "vcvt.f32.s32 q1, q1\n"
7409 "vcvt.f32.s32 q2, q2\n"
7410 "vcvt.f32.s32 q3, q3\n"
7411 "vcvt.f32.s32 q4, q4\n"
7412 "vcvt.f32.s32 q5, q5\n"
7413 "vcvt.f32.s32 q6, q6\n"
7414 "vcvt.f32.s32 q7, q7\n"
7415 "vmul.f32 q0, q0, q9\n"
7416 "vmul.f32 q1, q1, q9\n"
7417 "vmul.f32 q2, q2, q9\n"
7418 "vmul.f32 q3, q3, q9\n"
7419 "vmul.f32 q4, q4, q11\n"
7420 "vmul.f32 q5, q5, q11\n"
7421 "vmul.f32 q6, q6, q11\n"
7422 "vmul.f32 q7, q7, q11\n"
7423 "vadd.f32 q0, q0, q8\n"
7424 "vadd.f32 q1, q1, q8\n"
7425 "vadd.f32 q2, q2, q8\n"
7426 "vadd.f32 q3, q3, q8\n"
7427 "vadd.f32 q4, q4, q10\n"
7428 "vadd.f32 q5, q5, q10\n"
7429 "vadd.f32 q6, q6, q10\n"
7430 "vadd.f32 q7, q7, q10\n"
7431 "vadd.f32 q0, q0, q4\n"
7432 "vadd.f32 q1, q1, q5\n"
7433 "vadd.f32 q2, q2, q6\n"
7434 "vadd.f32 q3, q3, q7\n"
7435 "vsub.f32 q0, q0, q12\n"
7436 "vsub.f32 q1, q1, q12\n"
7437 "vsub.f32 q2, q2, q12\n"
7438 "vsub.f32 q3, q3, q12\n"
7439 "vmul.f32 q0, q0, q13\n"
7440 "vmul.f32 q1, q1, q13\n"
7441 "vmul.f32 q2, q2, q13\n"
7442 "vmul.f32 q3, q3, q13\n"
7443 "vadd.f32 q0, q0, q14\n"
7444 "vadd.f32 q1, q1, q14\n"
7445 "vadd.f32 q2, q2, q14\n"
7446 "vadd.f32 q3, q3, q14\n"
7447 "vcvt.s32.f32 q0, q0\n"
7448 "vcvt.s32.f32 q1, q1\n"
7449 "vcvt.s32.f32 q2, q2\n"
7450 "vcvt.s32.f32 q3, q3\n"
7451
7452 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7453 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
7454 "pld [%[output]]\n"
7455 "bne 2b\n"
7456 "3:"
7457
7458 // BiasAdd::Transform
7459 "vld1.32 {d0}, [%[input]]!\n"
7460 "vld1.32 {d1[0]}, [%[input]]!\n"
7461 "vld1.32 {d6}, [r1]!\n"
7462 "vld1.32 {d7[0]}, [r1]!\n"
7463 "pld [%[input], #32]\n"
7464 "vmovl.u8 q1, d1\n"
7465 "vmovl.u8 q0, d0\n"
7466 "vmovl.u8 q4, d7\n"
7467 "vmovl.u8 q3, d6\n"
7468 "vmovl.s16 q2, d2\n"
7469 "vmovl.s16 q5, d8\n"
7470 "vmovl.s16 q1, d1\n"
7471 "vmovl.s16 q0, d0\n"
7472 "vmovl.s16 q4, d7\n"
7473 "vmovl.s16 q3, d6\n"
7474 "vcvt.f32.s32 q0, q0\n"
7475 "vcvt.f32.s32 q1, q1\n"
7476 "vcvt.f32.s32 q2, q2\n"
7477 "vcvt.f32.s32 q3, q3\n"
7478 "vcvt.f32.s32 q4, q4\n"
7479 "vcvt.f32.s32 q5, q5\n"
7480 "vmul.f32 q0, q0, q9\n"
7481 "vmul.f32 q1, q1, q9\n"
7482 "vmul.f32 q2, q2, q9\n"
7483 "vmul.f32 q3, q3, q11\n"
7484 "vmul.f32 q4, q4, q11\n"
7485 "vmul.f32 q5, q5, q11\n"
7486 "vadd.f32 q0, q0, q8\n"
7487 "vadd.f32 q1, q1, q8\n"
7488 "vadd.f32 q2, q2, q8\n"
7489 "vadd.f32 q3, q3, q10\n"
7490 "vadd.f32 q4, q4, q10\n"
7491 "vadd.f32 q5, q5, q10\n"
7492 "vadd.f32 q0, q0, q3\n"
7493 "vadd.f32 q1, q1, q4\n"
7494 "vadd.f32 q2, q2, q5\n"
7495 "vsub.f32 q0, q0, q12\n"
7496 "vsub.f32 q1, q1, q12\n"
7497 "vsub.f32 q2, q2, q12\n"
7498 "vmul.f32 q0, q0, q13\n"
7499 "vmul.f32 q1, q1, q13\n"
7500 "vmul.f32 q2, q2, q13\n"
7501 "vadd.f32 q0, q0, q14\n"
7502 "vadd.f32 q1, q1, q14\n"
7503 "vadd.f32 q2, q2, q14\n"
7504 "vcvt.s32.f32 q0, q0\n"
7505 "vcvt.s32.f32 q1, q1\n"
7506 "vcvt.s32.f32 q2, q2\n"
7507
7508 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7509 "vst1.32 {d4, d5}, [%[output]]!\n"
7510 "pld [%[output]]\n"
7511 "subs %[rows], %[rows], #1\n"
7512 "bne 1b\n"
7513 : [input] "+r"(input), [output] "+r"(output)
7514 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
7515 [output_range_offset] "m"(params.output_range_offset),
7516 [input_range_scale] "m"(params.input_range_scale),
7517 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
7518 [bias_range_min] "m"(params.bias_range_min),
7519 [output_range_min] "m"(params.output_range_min),
7520 [bias_range_scale] "m"(params.bias_range_scale),
7521 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
7522 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
7523 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
7524 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
7525 "cc", "memory");
7526 }
7527
7528 template <>
7529 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)7530 13>::Transform(const uint8_t* input,
7531 const BiasAdd<uint8_t>& params,
7532 int32_t* output) {
7533 #ifdef DEBUG
7534 #ifdef DEBUG_METAGEMM_VERBOSE
7535 std::cout << __FILE__ << "(" << __LINE__
7536 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
7537 "13>::Transform()"
7538 << std::endl
7539 << std::flush;
7540 #endif
7541 #endif
7542 int params_rows_copy = params.rows;
7543 asm volatile(
7544 "ldr r0, %[input_range_min]\n"
7545 "vdup.32 q8, r0\n"
7546 "ldr r0, %[input_range_scale]\n"
7547 "vdup.32 q9, r0\n"
7548 "ldr r0, %[bias_range_min]\n"
7549 "vdup.32 q10, r0\n"
7550 "ldr r0, %[bias_range_scale]\n"
7551 "vdup.32 q11, r0\n"
7552 "ldr r0, %[output_range_min]\n"
7553 "vdup.32 q12, r0\n"
7554 "ldr r0, %[one_over_output_range_scale]\n"
7555 "vdup.32 q13, r0\n"
7556 "ldr r0, %[output_range_offset]\n"
7557 "vdup.32 q14, r0\n"
7558 "1:"
7559 "mov r0, %[count]\n"
7560 "mov r1, %[bias]\n"
7561 "subs r0, r0, #13\n"
7562 "beq 3f\n"
7563 "2:"
7564 "subs r0, r0, #16\n"
7565
7566 // BiasAdd::Transform
7567 "vld1.32 {d0, d1}, [%[input]]!\n"
7568 "vld1.32 {d8, d9}, [r1]!\n"
7569 "pld [%[input], #32]\n"
7570 "vmovl.u8 q1, d1\n"
7571 "vmovl.u8 q0, d0\n"
7572 "vmovl.u8 q5, d9\n"
7573 "vmovl.u8 q4, d8\n"
7574 "vmovl.s16 q3, d3\n"
7575 "vmovl.s16 q2, d2\n"
7576 "vmovl.s16 q7, d11\n"
7577 "vmovl.s16 q6, d10\n"
7578 "vmovl.s16 q1, d1\n"
7579 "vmovl.s16 q0, d0\n"
7580 "vmovl.s16 q5, d9\n"
7581 "vmovl.s16 q4, d8\n"
7582 "vcvt.f32.s32 q0, q0\n"
7583 "vcvt.f32.s32 q1, q1\n"
7584 "vcvt.f32.s32 q2, q2\n"
7585 "vcvt.f32.s32 q3, q3\n"
7586 "vcvt.f32.s32 q4, q4\n"
7587 "vcvt.f32.s32 q5, q5\n"
7588 "vcvt.f32.s32 q6, q6\n"
7589 "vcvt.f32.s32 q7, q7\n"
7590 "vmul.f32 q0, q0, q9\n"
7591 "vmul.f32 q1, q1, q9\n"
7592 "vmul.f32 q2, q2, q9\n"
7593 "vmul.f32 q3, q3, q9\n"
7594 "vmul.f32 q4, q4, q11\n"
7595 "vmul.f32 q5, q5, q11\n"
7596 "vmul.f32 q6, q6, q11\n"
7597 "vmul.f32 q7, q7, q11\n"
7598 "vadd.f32 q0, q0, q8\n"
7599 "vadd.f32 q1, q1, q8\n"
7600 "vadd.f32 q2, q2, q8\n"
7601 "vadd.f32 q3, q3, q8\n"
7602 "vadd.f32 q4, q4, q10\n"
7603 "vadd.f32 q5, q5, q10\n"
7604 "vadd.f32 q6, q6, q10\n"
7605 "vadd.f32 q7, q7, q10\n"
7606 "vadd.f32 q0, q0, q4\n"
7607 "vadd.f32 q1, q1, q5\n"
7608 "vadd.f32 q2, q2, q6\n"
7609 "vadd.f32 q3, q3, q7\n"
7610 "vsub.f32 q0, q0, q12\n"
7611 "vsub.f32 q1, q1, q12\n"
7612 "vsub.f32 q2, q2, q12\n"
7613 "vsub.f32 q3, q3, q12\n"
7614 "vmul.f32 q0, q0, q13\n"
7615 "vmul.f32 q1, q1, q13\n"
7616 "vmul.f32 q2, q2, q13\n"
7617 "vmul.f32 q3, q3, q13\n"
7618 "vadd.f32 q0, q0, q14\n"
7619 "vadd.f32 q1, q1, q14\n"
7620 "vadd.f32 q2, q2, q14\n"
7621 "vadd.f32 q3, q3, q14\n"
7622 "vcvt.s32.f32 q0, q0\n"
7623 "vcvt.s32.f32 q1, q1\n"
7624 "vcvt.s32.f32 q2, q2\n"
7625 "vcvt.s32.f32 q3, q3\n"
7626
7627 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7628 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
7629 "pld [%[output]]\n"
7630 "bne 2b\n"
7631 "3:"
7632
7633 // BiasAdd::Transform
7634 "vld1.32 {d0}, [%[input]]!\n"
7635 "vld1.32 {d1[0]}, [%[input]]!\n"
7636 "vld1.8 {d1[4]}, [%[input]]!\n"
7637 "vld1.32 {d8}, [r1]!\n"
7638 "vld1.32 {d9[0]}, [r1]!\n"
7639 "vld1.8 {d9[4]}, [r1]!\n"
7640 "pld [%[input], #32]\n"
7641 "vmovl.u8 q1, d1\n"
7642 "vmovl.u8 q0, d0\n"
7643 "vmovl.u8 q5, d9\n"
7644 "vmovl.u8 q4, d8\n"
7645 "vmovl.s16 q3, d3\n"
7646 "vmovl.s16 q2, d2\n"
7647 "vmovl.s16 q7, d11\n"
7648 "vmovl.s16 q6, d10\n"
7649 "vmovl.s16 q1, d1\n"
7650 "vmovl.s16 q0, d0\n"
7651 "vmovl.s16 q5, d9\n"
7652 "vmovl.s16 q4, d8\n"
7653 "vcvt.f32.s32 q0, q0\n"
7654 "vcvt.f32.s32 q1, q1\n"
7655 "vcvt.f32.s32 q2, q2\n"
7656 "vcvt.f32.s32 q3, q3\n"
7657 "vcvt.f32.s32 q4, q4\n"
7658 "vcvt.f32.s32 q5, q5\n"
7659 "vcvt.f32.s32 q6, q6\n"
7660 "vcvt.f32.s32 q7, q7\n"
7661 "vmul.f32 q0, q0, q9\n"
7662 "vmul.f32 q1, q1, q9\n"
7663 "vmul.f32 q2, q2, q9\n"
7664 "vmul.f32 q3, q3, q9\n"
7665 "vmul.f32 q4, q4, q11\n"
7666 "vmul.f32 q5, q5, q11\n"
7667 "vmul.f32 q6, q6, q11\n"
7668 "vmul.f32 q7, q7, q11\n"
7669 "vadd.f32 q0, q0, q8\n"
7670 "vadd.f32 q1, q1, q8\n"
7671 "vadd.f32 q2, q2, q8\n"
7672 "vadd.f32 q3, q3, q8\n"
7673 "vadd.f32 q4, q4, q10\n"
7674 "vadd.f32 q5, q5, q10\n"
7675 "vadd.f32 q6, q6, q10\n"
7676 "vadd.f32 q7, q7, q10\n"
7677 "vadd.f32 q0, q0, q4\n"
7678 "vadd.f32 q1, q1, q5\n"
7679 "vadd.f32 q2, q2, q6\n"
7680 "vadd.f32 q3, q3, q7\n"
7681 "vsub.f32 q0, q0, q12\n"
7682 "vsub.f32 q1, q1, q12\n"
7683 "vsub.f32 q2, q2, q12\n"
7684 "vsub.f32 q3, q3, q12\n"
7685 "vmul.f32 q0, q0, q13\n"
7686 "vmul.f32 q1, q1, q13\n"
7687 "vmul.f32 q2, q2, q13\n"
7688 "vmul.f32 q3, q3, q13\n"
7689 "vadd.f32 q0, q0, q14\n"
7690 "vadd.f32 q1, q1, q14\n"
7691 "vadd.f32 q2, q2, q14\n"
7692 "vadd.f32 q3, q3, q14\n"
7693 "vcvt.s32.f32 q0, q0\n"
7694 "vcvt.s32.f32 q1, q1\n"
7695 "vcvt.s32.f32 q2, q2\n"
7696 "vcvt.s32.f32 q3, q3\n"
7697
7698 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7699 "vst1.32 {d4, d5}, [%[output]]!\n"
7700 "vst1.32 {d6[0]}, [%[output]]!\n"
7701 "pld [%[output]]\n"
7702 "subs %[rows], %[rows], #1\n"
7703 "bne 1b\n"
7704 : [input] "+r"(input), [output] "+r"(output)
7705 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
7706 [output_range_offset] "m"(params.output_range_offset),
7707 [input_range_scale] "m"(params.input_range_scale),
7708 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
7709 [bias_range_min] "m"(params.bias_range_min),
7710 [output_range_min] "m"(params.output_range_min),
7711 [bias_range_scale] "m"(params.bias_range_scale),
7712 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
7713 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
7714 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
7715 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
7716 "cc", "memory");
7717 }
7718
7719 template <>
7720 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)7721 14>::Transform(const uint8_t* input,
7722 const BiasAdd<uint8_t>& params,
7723 int32_t* output) {
7724 #ifdef DEBUG
7725 #ifdef DEBUG_METAGEMM_VERBOSE
7726 std::cout << __FILE__ << "(" << __LINE__
7727 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
7728 "14>::Transform()"
7729 << std::endl
7730 << std::flush;
7731 #endif
7732 #endif
7733 int params_rows_copy = params.rows;
7734 asm volatile(
7735 "ldr r0, %[input_range_min]\n"
7736 "vdup.32 q8, r0\n"
7737 "ldr r0, %[input_range_scale]\n"
7738 "vdup.32 q9, r0\n"
7739 "ldr r0, %[bias_range_min]\n"
7740 "vdup.32 q10, r0\n"
7741 "ldr r0, %[bias_range_scale]\n"
7742 "vdup.32 q11, r0\n"
7743 "ldr r0, %[output_range_min]\n"
7744 "vdup.32 q12, r0\n"
7745 "ldr r0, %[one_over_output_range_scale]\n"
7746 "vdup.32 q13, r0\n"
7747 "ldr r0, %[output_range_offset]\n"
7748 "vdup.32 q14, r0\n"
7749 "1:"
7750 "mov r0, %[count]\n"
7751 "mov r1, %[bias]\n"
7752 "subs r0, r0, #14\n"
7753 "beq 3f\n"
7754 "2:"
7755 "subs r0, r0, #16\n"
7756
7757 // BiasAdd::Transform
7758 "vld1.32 {d0, d1}, [%[input]]!\n"
7759 "vld1.32 {d8, d9}, [r1]!\n"
7760 "pld [%[input], #32]\n"
7761 "vmovl.u8 q1, d1\n"
7762 "vmovl.u8 q0, d0\n"
7763 "vmovl.u8 q5, d9\n"
7764 "vmovl.u8 q4, d8\n"
7765 "vmovl.s16 q3, d3\n"
7766 "vmovl.s16 q2, d2\n"
7767 "vmovl.s16 q7, d11\n"
7768 "vmovl.s16 q6, d10\n"
7769 "vmovl.s16 q1, d1\n"
7770 "vmovl.s16 q0, d0\n"
7771 "vmovl.s16 q5, d9\n"
7772 "vmovl.s16 q4, d8\n"
7773 "vcvt.f32.s32 q0, q0\n"
7774 "vcvt.f32.s32 q1, q1\n"
7775 "vcvt.f32.s32 q2, q2\n"
7776 "vcvt.f32.s32 q3, q3\n"
7777 "vcvt.f32.s32 q4, q4\n"
7778 "vcvt.f32.s32 q5, q5\n"
7779 "vcvt.f32.s32 q6, q6\n"
7780 "vcvt.f32.s32 q7, q7\n"
7781 "vmul.f32 q0, q0, q9\n"
7782 "vmul.f32 q1, q1, q9\n"
7783 "vmul.f32 q2, q2, q9\n"
7784 "vmul.f32 q3, q3, q9\n"
7785 "vmul.f32 q4, q4, q11\n"
7786 "vmul.f32 q5, q5, q11\n"
7787 "vmul.f32 q6, q6, q11\n"
7788 "vmul.f32 q7, q7, q11\n"
7789 "vadd.f32 q0, q0, q8\n"
7790 "vadd.f32 q1, q1, q8\n"
7791 "vadd.f32 q2, q2, q8\n"
7792 "vadd.f32 q3, q3, q8\n"
7793 "vadd.f32 q4, q4, q10\n"
7794 "vadd.f32 q5, q5, q10\n"
7795 "vadd.f32 q6, q6, q10\n"
7796 "vadd.f32 q7, q7, q10\n"
7797 "vadd.f32 q0, q0, q4\n"
7798 "vadd.f32 q1, q1, q5\n"
7799 "vadd.f32 q2, q2, q6\n"
7800 "vadd.f32 q3, q3, q7\n"
7801 "vsub.f32 q0, q0, q12\n"
7802 "vsub.f32 q1, q1, q12\n"
7803 "vsub.f32 q2, q2, q12\n"
7804 "vsub.f32 q3, q3, q12\n"
7805 "vmul.f32 q0, q0, q13\n"
7806 "vmul.f32 q1, q1, q13\n"
7807 "vmul.f32 q2, q2, q13\n"
7808 "vmul.f32 q3, q3, q13\n"
7809 "vadd.f32 q0, q0, q14\n"
7810 "vadd.f32 q1, q1, q14\n"
7811 "vadd.f32 q2, q2, q14\n"
7812 "vadd.f32 q3, q3, q14\n"
7813 "vcvt.s32.f32 q0, q0\n"
7814 "vcvt.s32.f32 q1, q1\n"
7815 "vcvt.s32.f32 q2, q2\n"
7816 "vcvt.s32.f32 q3, q3\n"
7817
7818 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7819 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
7820 "pld [%[output]]\n"
7821 "bne 2b\n"
7822 "3:"
7823
7824 // BiasAdd::Transform
7825 "vld1.32 {d0}, [%[input]]!\n"
7826 "vld1.32 {d1[0]}, [%[input]]!\n"
7827 "vld1.16 {d1[2]}, [%[input]]!\n"
7828 "vld1.32 {d8}, [r1]!\n"
7829 "vld1.32 {d9[0]}, [r1]!\n"
7830 "vld1.16 {d9[2]}, [r1]!\n"
7831 "pld [%[input], #32]\n"
7832 "vmovl.u8 q1, d1\n"
7833 "vmovl.u8 q0, d0\n"
7834 "vmovl.u8 q5, d9\n"
7835 "vmovl.u8 q4, d8\n"
7836 "vmovl.s16 q3, d3\n"
7837 "vmovl.s16 q2, d2\n"
7838 "vmovl.s16 q7, d11\n"
7839 "vmovl.s16 q6, d10\n"
7840 "vmovl.s16 q1, d1\n"
7841 "vmovl.s16 q0, d0\n"
7842 "vmovl.s16 q5, d9\n"
7843 "vmovl.s16 q4, d8\n"
7844 "vcvt.f32.s32 q0, q0\n"
7845 "vcvt.f32.s32 q1, q1\n"
7846 "vcvt.f32.s32 q2, q2\n"
7847 "vcvt.f32.s32 q3, q3\n"
7848 "vcvt.f32.s32 q4, q4\n"
7849 "vcvt.f32.s32 q5, q5\n"
7850 "vcvt.f32.s32 q6, q6\n"
7851 "vcvt.f32.s32 q7, q7\n"
7852 "vmul.f32 q0, q0, q9\n"
7853 "vmul.f32 q1, q1, q9\n"
7854 "vmul.f32 q2, q2, q9\n"
7855 "vmul.f32 q3, q3, q9\n"
7856 "vmul.f32 q4, q4, q11\n"
7857 "vmul.f32 q5, q5, q11\n"
7858 "vmul.f32 q6, q6, q11\n"
7859 "vmul.f32 q7, q7, q11\n"
7860 "vadd.f32 q0, q0, q8\n"
7861 "vadd.f32 q1, q1, q8\n"
7862 "vadd.f32 q2, q2, q8\n"
7863 "vadd.f32 q3, q3, q8\n"
7864 "vadd.f32 q4, q4, q10\n"
7865 "vadd.f32 q5, q5, q10\n"
7866 "vadd.f32 q6, q6, q10\n"
7867 "vadd.f32 q7, q7, q10\n"
7868 "vadd.f32 q0, q0, q4\n"
7869 "vadd.f32 q1, q1, q5\n"
7870 "vadd.f32 q2, q2, q6\n"
7871 "vadd.f32 q3, q3, q7\n"
7872 "vsub.f32 q0, q0, q12\n"
7873 "vsub.f32 q1, q1, q12\n"
7874 "vsub.f32 q2, q2, q12\n"
7875 "vsub.f32 q3, q3, q12\n"
7876 "vmul.f32 q0, q0, q13\n"
7877 "vmul.f32 q1, q1, q13\n"
7878 "vmul.f32 q2, q2, q13\n"
7879 "vmul.f32 q3, q3, q13\n"
7880 "vadd.f32 q0, q0, q14\n"
7881 "vadd.f32 q1, q1, q14\n"
7882 "vadd.f32 q2, q2, q14\n"
7883 "vadd.f32 q3, q3, q14\n"
7884 "vcvt.s32.f32 q0, q0\n"
7885 "vcvt.s32.f32 q1, q1\n"
7886 "vcvt.s32.f32 q2, q2\n"
7887 "vcvt.s32.f32 q3, q3\n"
7888
7889 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
7890 "vst1.32 {d4, d5, d6}, [%[output]]!\n"
7891 "pld [%[output]]\n"
7892 "subs %[rows], %[rows], #1\n"
7893 "bne 1b\n"
7894 : [input] "+r"(input), [output] "+r"(output)
7895 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
7896 [output_range_offset] "m"(params.output_range_offset),
7897 [input_range_scale] "m"(params.input_range_scale),
7898 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
7899 [bias_range_min] "m"(params.bias_range_min),
7900 [output_range_min] "m"(params.output_range_min),
7901 [bias_range_scale] "m"(params.bias_range_scale),
7902 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
7903 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
7904 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
7905 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
7906 "cc", "memory");
7907 }
7908
7909 template <>
7910 inline void Transform1DKernel<uint8_t, int32_t, BiasAdd<uint8_t>, 16,
Transform(const uint8_t * input,const BiasAdd<uint8_t> & params,int32_t * output)7911 15>::Transform(const uint8_t* input,
7912 const BiasAdd<uint8_t>& params,
7913 int32_t* output) {
7914 #ifdef DEBUG
7915 #ifdef DEBUG_METAGEMM_VERBOSE
7916 std::cout << __FILE__ << "(" << __LINE__
7917 << ") BiasAdd<uint8_t><uint8_t, int32_t, BiasAdd<uint8_t>, 16, "
7918 "15>::Transform()"
7919 << std::endl
7920 << std::flush;
7921 #endif
7922 #endif
7923 int params_rows_copy = params.rows;
7924 asm volatile(
7925 "ldr r0, %[input_range_min]\n"
7926 "vdup.32 q8, r0\n"
7927 "ldr r0, %[input_range_scale]\n"
7928 "vdup.32 q9, r0\n"
7929 "ldr r0, %[bias_range_min]\n"
7930 "vdup.32 q10, r0\n"
7931 "ldr r0, %[bias_range_scale]\n"
7932 "vdup.32 q11, r0\n"
7933 "ldr r0, %[output_range_min]\n"
7934 "vdup.32 q12, r0\n"
7935 "ldr r0, %[one_over_output_range_scale]\n"
7936 "vdup.32 q13, r0\n"
7937 "ldr r0, %[output_range_offset]\n"
7938 "vdup.32 q14, r0\n"
7939 "1:"
7940 "mov r0, %[count]\n"
7941 "mov r1, %[bias]\n"
7942 "subs r0, r0, #15\n"
7943 "beq 3f\n"
7944 "2:"
7945 "subs r0, r0, #16\n"
7946
7947 // BiasAdd::Transform
7948 "vld1.32 {d0, d1}, [%[input]]!\n"
7949 "vld1.32 {d8, d9}, [r1]!\n"
7950 "pld [%[input], #32]\n"
7951 "vmovl.u8 q1, d1\n"
7952 "vmovl.u8 q0, d0\n"
7953 "vmovl.u8 q5, d9\n"
7954 "vmovl.u8 q4, d8\n"
7955 "vmovl.s16 q3, d3\n"
7956 "vmovl.s16 q2, d2\n"
7957 "vmovl.s16 q7, d11\n"
7958 "vmovl.s16 q6, d10\n"
7959 "vmovl.s16 q1, d1\n"
7960 "vmovl.s16 q0, d0\n"
7961 "vmovl.s16 q5, d9\n"
7962 "vmovl.s16 q4, d8\n"
7963 "vcvt.f32.s32 q0, q0\n"
7964 "vcvt.f32.s32 q1, q1\n"
7965 "vcvt.f32.s32 q2, q2\n"
7966 "vcvt.f32.s32 q3, q3\n"
7967 "vcvt.f32.s32 q4, q4\n"
7968 "vcvt.f32.s32 q5, q5\n"
7969 "vcvt.f32.s32 q6, q6\n"
7970 "vcvt.f32.s32 q7, q7\n"
7971 "vmul.f32 q0, q0, q9\n"
7972 "vmul.f32 q1, q1, q9\n"
7973 "vmul.f32 q2, q2, q9\n"
7974 "vmul.f32 q3, q3, q9\n"
7975 "vmul.f32 q4, q4, q11\n"
7976 "vmul.f32 q5, q5, q11\n"
7977 "vmul.f32 q6, q6, q11\n"
7978 "vmul.f32 q7, q7, q11\n"
7979 "vadd.f32 q0, q0, q8\n"
7980 "vadd.f32 q1, q1, q8\n"
7981 "vadd.f32 q2, q2, q8\n"
7982 "vadd.f32 q3, q3, q8\n"
7983 "vadd.f32 q4, q4, q10\n"
7984 "vadd.f32 q5, q5, q10\n"
7985 "vadd.f32 q6, q6, q10\n"
7986 "vadd.f32 q7, q7, q10\n"
7987 "vadd.f32 q0, q0, q4\n"
7988 "vadd.f32 q1, q1, q5\n"
7989 "vadd.f32 q2, q2, q6\n"
7990 "vadd.f32 q3, q3, q7\n"
7991 "vsub.f32 q0, q0, q12\n"
7992 "vsub.f32 q1, q1, q12\n"
7993 "vsub.f32 q2, q2, q12\n"
7994 "vsub.f32 q3, q3, q12\n"
7995 "vmul.f32 q0, q0, q13\n"
7996 "vmul.f32 q1, q1, q13\n"
7997 "vmul.f32 q2, q2, q13\n"
7998 "vmul.f32 q3, q3, q13\n"
7999 "vadd.f32 q0, q0, q14\n"
8000 "vadd.f32 q1, q1, q14\n"
8001 "vadd.f32 q2, q2, q14\n"
8002 "vadd.f32 q3, q3, q14\n"
8003 "vcvt.s32.f32 q0, q0\n"
8004 "vcvt.s32.f32 q1, q1\n"
8005 "vcvt.s32.f32 q2, q2\n"
8006 "vcvt.s32.f32 q3, q3\n"
8007
8008 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
8009 "vst1.32 {d4, d5, d6, d7}, [%[output]]!\n"
8010 "pld [%[output]]\n"
8011 "bne 2b\n"
8012 "3:"
8013
8014 // BiasAdd::Transform
8015 "vld1.32 {d0}, [%[input]]!\n"
8016 "vld1.32 {d1[0]}, [%[input]]!\n"
8017 "vld1.16 {d1[2]}, [%[input]]!\n"
8018 "vld1.8 {d1[6]}, [%[input]]!\n"
8019 "vld1.32 {d8}, [r1]!\n"
8020 "vld1.32 {d9[0]}, [r1]!\n"
8021 "vld1.16 {d9[2]}, [r1]!\n"
8022 "vld1.8 {d9[6]}, [r1]!\n"
8023 "pld [%[input], #32]\n"
8024 "vmovl.u8 q1, d1\n"
8025 "vmovl.u8 q0, d0\n"
8026 "vmovl.u8 q5, d9\n"
8027 "vmovl.u8 q4, d8\n"
8028 "vmovl.s16 q3, d3\n"
8029 "vmovl.s16 q2, d2\n"
8030 "vmovl.s16 q7, d11\n"
8031 "vmovl.s16 q6, d10\n"
8032 "vmovl.s16 q1, d1\n"
8033 "vmovl.s16 q0, d0\n"
8034 "vmovl.s16 q5, d9\n"
8035 "vmovl.s16 q4, d8\n"
8036 "vcvt.f32.s32 q0, q0\n"
8037 "vcvt.f32.s32 q1, q1\n"
8038 "vcvt.f32.s32 q2, q2\n"
8039 "vcvt.f32.s32 q3, q3\n"
8040 "vcvt.f32.s32 q4, q4\n"
8041 "vcvt.f32.s32 q5, q5\n"
8042 "vcvt.f32.s32 q6, q6\n"
8043 "vcvt.f32.s32 q7, q7\n"
8044 "vmul.f32 q0, q0, q9\n"
8045 "vmul.f32 q1, q1, q9\n"
8046 "vmul.f32 q2, q2, q9\n"
8047 "vmul.f32 q3, q3, q9\n"
8048 "vmul.f32 q4, q4, q11\n"
8049 "vmul.f32 q5, q5, q11\n"
8050 "vmul.f32 q6, q6, q11\n"
8051 "vmul.f32 q7, q7, q11\n"
8052 "vadd.f32 q0, q0, q8\n"
8053 "vadd.f32 q1, q1, q8\n"
8054 "vadd.f32 q2, q2, q8\n"
8055 "vadd.f32 q3, q3, q8\n"
8056 "vadd.f32 q4, q4, q10\n"
8057 "vadd.f32 q5, q5, q10\n"
8058 "vadd.f32 q6, q6, q10\n"
8059 "vadd.f32 q7, q7, q10\n"
8060 "vadd.f32 q0, q0, q4\n"
8061 "vadd.f32 q1, q1, q5\n"
8062 "vadd.f32 q2, q2, q6\n"
8063 "vadd.f32 q3, q3, q7\n"
8064 "vsub.f32 q0, q0, q12\n"
8065 "vsub.f32 q1, q1, q12\n"
8066 "vsub.f32 q2, q2, q12\n"
8067 "vsub.f32 q3, q3, q12\n"
8068 "vmul.f32 q0, q0, q13\n"
8069 "vmul.f32 q1, q1, q13\n"
8070 "vmul.f32 q2, q2, q13\n"
8071 "vmul.f32 q3, q3, q13\n"
8072 "vadd.f32 q0, q0, q14\n"
8073 "vadd.f32 q1, q1, q14\n"
8074 "vadd.f32 q2, q2, q14\n"
8075 "vadd.f32 q3, q3, q14\n"
8076 "vcvt.s32.f32 q0, q0\n"
8077 "vcvt.s32.f32 q1, q1\n"
8078 "vcvt.s32.f32 q2, q2\n"
8079 "vcvt.s32.f32 q3, q3\n"
8080
8081 "vst1.32 {d0, d1, d2, d3}, [%[output]]!\n"
8082 "vst1.32 {d4, d5, d6}, [%[output]]!\n"
8083 "vst1.32 {d7[0]}, [%[output]]!\n"
8084 "pld [%[output]]\n"
8085 "subs %[rows], %[rows], #1\n"
8086 "bne 1b\n"
8087 : [input] "+r"(input), [output] "+r"(output)
8088 : [count] "r"(params.count), [rows] "r"(params_rows_copy),
8089 [output_range_offset] "m"(params.output_range_offset),
8090 [input_range_scale] "m"(params.input_range_scale),
8091 [one_over_output_range_scale] "m"(params.one_over_output_range_scale),
8092 [bias_range_min] "m"(params.bias_range_min),
8093 [output_range_min] "m"(params.output_range_min),
8094 [bias_range_scale] "m"(params.bias_range_scale),
8095 [bias] "r"(params.bias), [input_range_min] "m"(params.input_range_min)
8096 : "r0", "r1", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9",
8097 "d10", "d11", "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19",
8098 "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29",
8099 "cc", "memory");
8100 }
8101
8102 } // namespace meta
8103 } // namespace gemmlowp
8104
8105 #else
8106 #warning "Meta gemm for arm32 requires: GEMMLOWP_NEON_32!"
8107 #endif
8108
8109 #endif // GEMMLOWP_META_TRANSFORM_KERNELS_ARM_32_H_
8110