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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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