blob: e648ce2fb54ba84ebaeea6c915a39a6687678d01 [file] [log] [blame]
Michele Di Giorgio5b6904b2018-01-29 12:24:14 +00001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2017 Arm Limited.
Michele Di Giorgio5b6904b2018-01-29 12:24:14 +00003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
Pablo Telloeb82fd22018-02-23 13:43:50 +000024
Michele Di Giorgio5b6904b2018-01-29 12:24:14 +000025#pragma once
26
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000027#include "arm_gemm.hpp"
28
Georgios Pinitas7cd26d42019-01-09 18:35:17 +000029#include <cstddef>
Georgios Pinitas421405b2018-10-26 19:05:32 +010030
Pablo Telloeb82fd22018-02-23 13:43:50 +000031// Macro for unreachable code (e.g. impossible default cases on switch)
Anthony Barbier5f707732018-07-03 16:22:02 +010032#define UNREACHABLE(why) __builtin_unreachable()
Michele Di Giorgio5b6904b2018-01-29 12:24:14 +000033
Pablo Telloeb82fd22018-02-23 13:43:50 +000034// Paranoid option for the above with assert
35// #define UNREACHABLE(why) assert(0 && why)
Michele Di Giorgio5b6904b2018-01-29 12:24:14 +000036
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000037namespace arm_gemm {
38
Georgios Pinitas1d480652019-01-23 11:24:50 +000039template<typename T>
40inline T iceildiv(const T a, const T b) {
Georgios Pinitas421405b2018-10-26 19:05:32 +010041 return (a + b - 1) / b;
Pablo Telloeb82fd22018-02-23 13:43:50 +000042}
Michele Di Giorgio5b6904b2018-01-29 12:24:14 +000043
Pablo Telloeb82fd22018-02-23 13:43:50 +000044template <typename T>
Anthony Barbier5f707732018-07-03 16:22:02 +010045inline T roundup(const T a, const T b) {
Georgios Pinitas421405b2018-10-26 19:05:32 +010046 T rem = a % b;
Michele Di Giorgio5b6904b2018-01-29 12:24:14 +000047
Georgios Pinitas421405b2018-10-26 19:05:32 +010048 if (rem) {
49 return a + b - rem;
50 } else {
51 return a;
52 }
Pablo Telloeb82fd22018-02-23 13:43:50 +000053}
David Manselld93991e2018-07-06 14:52:52 +010054
Georgios Pinitasc0b6f762020-11-02 01:37:17 +000055enum class VLType {
56 None,
57 SVE,
58};
59
60template<typename T>
61struct IndirectOutputArg {
62 struct {
63 T *base;
64 size_t stride;
65 } direct = {};
66 struct {
67 T * const *ptr;
68 size_t offset;
69 } indirect = {};
70 bool is_indirect;
71
72 // Direct
73 IndirectOutputArg(T *base, size_t stride) : is_indirect(false) {
74 direct.base = base;
75 direct.stride = stride;
76 }
77
78 // Indirect
79 IndirectOutputArg(T * const * ptr, size_t offset) : is_indirect(true) {
80 indirect.ptr = ptr;
81 indirect.offset = offset;
82 }
83
84 IndirectOutputArg() : is_indirect(false) {
85 direct.base = nullptr;
86 direct.stride = 0;
87 }
88};
89
90// Check that the provided Requantize32 doesn't have a left shift.
91inline bool quant_no_left_shift(const Requantize32 &qp) {
92 if (qp.per_channel_requant) {
93 return (qp.per_channel_left_shifts == nullptr);
94 } else {
95 return (qp.per_layer_left_shift == 0);
96 }
97}
98
99// Check that the provided Requantize32 is compatible with the "symmetric" hybrid kernels. These don't include row
100// sums, so the 'b_offset' has to be zero.
101inline bool quant_hybrid_symmetric(const Requantize32 &qp) {
102 return quant_no_left_shift(qp) && qp.b_offset == 0;
103}
104
105// Check that the provided Requantize32 is compatible with the "asymmetric" hybrid kernels. These don't support per
106// channel quantization. Technically b_offset==0 cases would work, but it is a waste to sum and then multiply by 0...
107inline bool quant_hybrid_asymmetric(const Requantize32 &qp) {
108 return quant_no_left_shift(qp) /* && qp.b_offset != 0 */ && qp.per_channel_requant==false;
109}
110
111template<typename T>
112struct IndirectInputArg {
113 struct {
114 const T *base;
115 size_t stride;
116 } direct = {};
117 struct {
118 const T * const * const * ptr;
119 unsigned int start_row;
120 unsigned int start_col;
121 } indirect = {};
122 bool is_indirect;
123
124 // Direct
125 IndirectInputArg(const T *base, size_t stride) : is_indirect(false) {
126 direct.base = base;
127 direct.stride = stride;
128 }
129
130 // Indirect
131 IndirectInputArg(const T * const * const *ptr, unsigned int start_row, unsigned int start_col) : is_indirect(true) {
132 indirect.ptr = ptr;
133 indirect.start_row = start_row;
134 indirect.start_col = start_col;
135 }
136
137 IndirectInputArg() : is_indirect(false) {
138 direct.base = nullptr;
139 direct.stride = 0;
140 }
141};
142
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000143namespace utils {
David Manselld93991e2018-07-06 14:52:52 +0100144template <typename T>
145inline unsigned long get_vector_length() {
Michalis Spyrou20fca522021-06-07 14:23:57 +0100146#if defined(ARM_COMPUTE_ENABLE_SVE)
147 uint64_t vl;
148
149 __asm __volatile (
150 ".inst 0x0420e3e0\n" // CNTB X0, ALL, MUL #1
151 "mov %0, X0\n"
152 : "=r" (vl)
153 :
154 : "x0"
155 );
156
157 return vl / sizeof(T);
158#else // !defined(ARM_COMPUTE_ENABLE_SVE)
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000159 return 16 / sizeof(T);
Michalis Spyrou20fca522021-06-07 14:23:57 +0100160#endif // defined(ARM_COMPUTE_ENABLE_SVE)
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000161}
David Manselld93991e2018-07-06 14:52:52 +0100162
Michele Di Giorgiod02d5ed2021-01-22 09:47:04 +0000163template <typename T>
164inline unsigned long get_vector_length(VLType vl_type) {
165 switch (vl_type) {
Michalis Spyrou20fca522021-06-07 14:23:57 +0100166#if defined(ARM_COMPUTE_ENABLE_SVE)
Michele Di Giorgiod02d5ed2021-01-22 09:47:04 +0000167 case VLType::SVE:
Michalis Spyrou20fca522021-06-07 14:23:57 +0100168 return get_vector_length<T>();
169#endif // defined(ARM_COMPUTE_ENABLE_SVE)
Michele Di Giorgiod02d5ed2021-01-22 09:47:04 +0000170 default:
171 return 16 / sizeof(T);
172 }
173}
Georgios Pinitas7cd26d42019-01-09 18:35:17 +0000174} // utils namespace
175} // arm_gemm namespace
176
Georgios Pinitascfa2bba2019-06-27 17:00:52 +0100177using namespace arm_gemm::utils;