• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
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 
16 #ifndef COMPILER_OPTIMIZER_IR_DATATYPE_H
17 #define COMPILER_OPTIMIZER_IR_DATATYPE_H
18 
19 #include "macros.h"
20 #include "utils/arch.h"
21 #include "mem/mem.h"
22 
23 // NOLINTNEXTLINE(modernize-concat-nested-namespaces)
24 namespace ark::compiler {
25 /*
26  * Type of the param/instruction
27  */
28 // NOLINTNEXTLINE(readability-identifier-naming)
29 namespace DataType {
30 enum Type : uint8_t {
31     NO_TYPE = 0,
32     REFERENCE,
33     BOOL,
34     UINT8,
35     INT8,
36     UINT16,
37     INT16,
38     UINT32,
39     INT32,
40     UINT64,
41     INT64,
42     FLOAT32,
43     FLOAT64,
44     ANY,
45     VOID,
46     POINTER,
47     LAST = POINTER
48 };
49 
50 class Any {
51 public:
Any(uint64_t value)52     explicit Any(uint64_t value) : value_(value) {}
53 
Raw()54     uint64_t Raw() const
55     {
56         return value_;
57     }
58 
59 private:
60     uint64_t value_ {0};
61 };
62 
63 namespace internal {
64 inline constexpr std::array<const char *, Type::LAST + 1> TYPE_NAMES = {
65     "",      // NO_TYPE
66     "ref",   // REFERENCE
67     "b",     // BOOL
68     "u8",    // UINT8
69     "i8",    // INT8
70     "u16",   // UINT16
71     "i16",   // INT16
72     "u32",   // UINT32
73     "i32",   // INT32
74     "u64",   // UINT64
75     "i64",   // INT64
76     "f32",   // FLOAT32
77     "f64",   // FLOAT64
78     "any",   // ANY
79     "void",  // VOID
80     "ptr"    // POINTER
81 };
82 }  // namespace internal
83 
ToString(Type type)84 inline const char *ToString(Type type)
85 {
86     ASSERT(type <= Type::LAST);
87     return internal::TYPE_NAMES[type];
88 }
89 
90 inline std::ostream &operator<<(std::ostream &os, const DataType::Type &type)
91 {
92     os << ToString(type);
93     return os;
94 }
95 
GetCommonType(Type type)96 constexpr inline Type GetCommonType(Type type)
97 {
98     switch (type) {
99         case Type::BOOL:
100         case Type::UINT8:
101         case Type::INT8:
102         case Type::UINT16:
103         case Type::INT16:
104         case Type::UINT32:
105         case Type::INT32:
106         case Type::UINT64:
107         case Type::INT64:
108             return Type::INT64;
109         case Type::REFERENCE:
110         case Type::POINTER:
111             return Type::POINTER;
112         default:
113             return type;
114     };
115 }
116 
IsInt32Bit(Type type)117 inline bool IsInt32Bit(Type type)
118 {
119     switch (type) {
120         case Type::BOOL:
121         case Type::UINT8:
122         case Type::INT8:
123         case Type::UINT16:
124         case Type::INT16:
125         case Type::UINT32:
126         case Type::INT32:
127             return true;
128         default:
129             return false;
130     };
131 }
132 
IsTypeNumeric(Type type)133 inline bool IsTypeNumeric(Type type)
134 {
135     switch (type) {
136         case BOOL:
137         case UINT8:
138         case INT8:
139         case UINT16:
140         case INT16:
141         case UINT32:
142         case INT32:
143         case UINT64:
144         case INT64:
145         case FLOAT32:
146         case FLOAT64:
147         case POINTER:
148             return true;
149         default:
150             return false;
151     }
152 }
153 
IsLessInt32(Type type)154 inline bool IsLessInt32(Type type)
155 {
156     switch (type) {
157         case BOOL:
158         case UINT8:
159         case INT8:
160         case UINT16:
161         case INT16:
162             return true;
163         default:
164             return false;
165     }
166 }
167 
GetIntTypeForReference(Arch arch)168 inline Type GetIntTypeForReference([[maybe_unused]] Arch arch)
169 {
170     // This is necessary for arm32 cross compilation
171     if (arch == Arch::AARCH32) {
172         return UINT32;
173     }
174 
175     if constexpr (ark::OBJECT_POINTER_SIZE == sizeof(uint64_t)) {
176         return UINT64;
177     } else if constexpr (ark::OBJECT_POINTER_SIZE == sizeof(uint32_t)) {
178         return UINT32;
179     } else if constexpr (ark::OBJECT_POINTER_SIZE == sizeof(uint16_t)) {
180         UNREACHABLE_CONSTEXPR();
181         return UINT16;
182     } else {
183         UNREACHABLE_CONSTEXPR();
184         return UINT8;
185     }
186 }
187 
188 constexpr inline Type GetIntTypeBySize(size_t sizeInBytes, bool isSigned = false)
189 {
190     if (sizeInBytes <= sizeof(uint8_t)) {
191         return isSigned ? INT8 : UINT8;
192     }
193     if (sizeInBytes <= sizeof(uint16_t)) {
194         return isSigned ? INT16 : UINT16;
195     }
196     if (sizeInBytes <= sizeof(uint32_t)) {
197         return isSigned ? INT32 : UINT32;
198     }
199     if (sizeInBytes <= sizeof(uint64_t)) {
200         return isSigned ? INT64 : UINT64;
201     }
202     UNREACHABLE_CONSTEXPR();
203     return NO_TYPE;
204 }
205 
Is32Bits(Type type,Arch arch)206 inline bool Is32Bits(Type type, Arch arch)
207 {
208     switch (type) {
209         case BOOL:
210         case UINT8:
211         case INT8:
212         case UINT16:
213         case INT16:
214         case UINT32:
215         case INT32:
216         case FLOAT32:
217             return true;
218         case POINTER:
219             return !Is64BitsArch(arch);
220         case REFERENCE:
221             return Is32Bits(GetIntTypeForReference(arch), arch);
222         default:
223             return false;
224     }
225 }
226 
Is64Bits(Type type,Arch arch)227 inline bool Is64Bits(Type type, Arch arch)
228 {
229     return !Is32Bits(type, arch);
230 }
231 
IsFloatType(Type type)232 inline bool IsFloatType(Type type)
233 {
234     switch (type) {
235         case FLOAT32:
236         case FLOAT64:
237             return true;
238         default:
239             return false;
240     }
241 }
242 
IsTypeSigned(Type type)243 inline bool IsTypeSigned(Type type)
244 {
245     switch (type) {
246         case INT8:
247         case INT16:
248         case INT32:
249         case INT64:
250         case FLOAT32:
251         case FLOAT64:
252             return true;
253         default:
254             return false;
255     }
256 }
257 
IsReference(Type type)258 inline bool IsReference(Type type)
259 {
260     return type == REFERENCE;
261 }
262 
ShiftByType(Type type,Arch arch)263 inline uint8_t ShiftByType(Type type, Arch arch)
264 {
265     switch (type) {
266         case VOID:
267         case BOOL:
268         case UINT8:
269         case INT8:
270             return 0;
271         case UINT16:
272         case INT16:
273             return 1;
274         case UINT32:
275         case INT32:
276         case FLOAT32:
277             return 2U;
278         case UINT64:
279         case INT64:
280         case FLOAT64:
281         case ANY:
282             return 3U;
283         case REFERENCE:
284             return ShiftByType(GetIntTypeForReference(arch), arch);
285         case POINTER:
286             return Is64BitsArch(arch) ? 3U : 2U;
287         default:
288             UNREACHABLE();
289             return 0;
290     }
291 }
292 
GetTypeSize(Type type,Arch arch)293 inline uint8_t GetTypeSize(Type type, Arch arch)
294 {
295     // NOLINTNEXTLINE(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers)
296     return 8U << ShiftByType(type, arch);
297 }
298 
GetTypeByteSize(Type type,Arch arch)299 inline uint8_t GetTypeByteSize(Type type, Arch arch)
300 {
301     // NOLINTNEXTLINE(readability-magic-numbers, cppcoreguidelines-avoid-magic-numbers)
302     return 1U << ShiftByType(type, arch);
303 }
304 
NeedCastIntTypes(Arch arch,DataType::Type typeBefore,DataType::Type typeAfter)305 inline bool NeedCastIntTypes(Arch arch, DataType::Type typeBefore, DataType::Type typeAfter)
306 {
307     auto sizeBefore = DataType::GetTypeSize(typeBefore, arch);
308     auto sizeAfter = DataType::GetTypeSize(typeAfter, arch);
309 
310     // In our ISA minimal type is 32-bit, so type less then 32-bit we should extend to 32-bit.
311     // Thereby we may to avoid some casts.
312     constexpr auto NUM_BITS_INT32 = 32U;
313     bool extendNotNeed = sizeBefore < sizeAfter && sizeAfter <= NUM_BITS_INT32;
314     return !extendNotNeed || DataType::IsTypeSigned(typeBefore) != DataType::IsTypeSigned(typeAfter);
315 }
316 
NeedCastForTypes(Arch arch,DataType::Type typeBefore,DataType::Type typeAfter)317 inline bool NeedCastForTypes(Arch arch, DataType::Type typeBefore, DataType::Type typeAfter)
318 {
319     // If types is equal, we avoid cast
320     if (typeBefore == typeAfter) {
321         return false;
322     }
323 
324     // There are types left here: int and float
325     ASSERT(DataType::IsTypeNumeric(typeBefore) && DataType::IsTypeNumeric(typeAfter));
326     if (DataType::IsFloatType(typeBefore) || DataType::IsFloatType(typeAfter)) {
327         return true;
328     }
329 
330     // There are types left here: int
331     return NeedCastIntTypes(arch, typeBefore, typeAfter);
332 }
333 
334 }  // namespace DataType
335 }  // namespace ark::compiler
336 
337 #endif  // COMPILER_OPTIMIZER_IR_DATATYPE_H
338