• 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 #include <random>
17 #include <gtest/gtest.h>
18 
19 const uint64_t SEED = 0x1234;
20 #ifndef PANDA_NIGHTLY_TEST_ON
21 const uint64_t ITERATION = 20;
22 #else
23 const uint64_t ITERATION = 4000;
24 #endif
25 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects,cert-msc51-cpp)
26 static auto g_randomGen = std::mt19937_64(SEED);
27 
28 // Encoder header
29 #include "optimizer/code_generator/operands.h"
30 
31 // NOLINTBEGIN(readability-isolate-declaration)
32 namespace ark::compiler {
33 
34 class TypeInfoTest : public ::testing::Test {
35 public:
CheckValid()36     void CheckValid()
37     {
38         for (uint64_t i = 0; i < sizeof(arr_) / sizeof(TypeInfo); ++i) {
39             if (i >= 16U) {  // NOLINT(readability-magic-numbers)
40                 ASSERT_FALSE(arr_[i].IsValid());
41             } else {
42                 ASSERT_TRUE(arr_[i].IsValid());
43             }
44         }
45     }
46 
CheckSizes()47     void CheckSizes()
48     {
49         ASSERT_EQ(BYTE_SIZE, HALF_SIZE / 2U);
50         ASSERT_EQ(HALF_SIZE, WORD_SIZE / 2U);
51         ASSERT_EQ(WORD_SIZE, DOUBLE_WORD_SIZE / 2U);
52 
53         ASSERT_EQ(arr_[0U].GetSize(), BYTE_SIZE);
54         ASSERT_EQ(arr_[1U].GetSize(), HALF_SIZE);
55         ASSERT_EQ(arr_[2U].GetSize(), WORD_SIZE);
56         ASSERT_EQ(arr_[3U].GetSize(), DOUBLE_WORD_SIZE);
57 
58         ASSERT_EQ(sizeof(TypeInfo), sizeof(uint8_t));
59 
60         ASSERT_EQ(TypeInfo(u8_), INT8_TYPE);
61         ASSERT_EQ(TypeInfo(u16_), INT16_TYPE);
62         ASSERT_EQ(TypeInfo(u32_), INT32_TYPE);
63         ASSERT_EQ(TypeInfo(u64_), INT64_TYPE);
64 
65         ASSERT_EQ(TypeInfo(f32_), FLOAT32_TYPE);
66         ASSERT_EQ(TypeInfo(f64_), FLOAT64_TYPE);
67         // Float
68         ASSERT_EQ(arr_[2U].GetSize(), arr_[12U].GetSize());
69         ASSERT_EQ(arr_[2U].GetSize(), arr_[14U].GetSize());
70         // Double
71         ASSERT_EQ(arr_[3U].GetSize(), arr_[13U].GetSize());
72         ASSERT_EQ(arr_[3U].GetSize(), arr_[15U].GetSize());
73     }
74 
CompareSizes()75     void CompareSizes()
76     {
77         for (size_t i = 0; i < 4U; ++i) {
78             ASSERT_EQ(arr_[i], arr_[4U + i]);
79             ASSERT_EQ(arr_[i], arr_[8U + i]);
80             ASSERT_EQ(arr_[4U + i], arr_[8U + i]);
81 
82             ASSERT_EQ(arr_[i].GetSize(), arr_[4U + i].GetSize());
83             ASSERT_EQ(arr_[i].GetSize(), arr_[8U + i].GetSize());
84             ASSERT_EQ(arr_[4U + i].GetSize(), arr_[8U + i].GetSize());
85 
86             ASSERT_TRUE(arr_[i].IsScalar());
87             ASSERT_TRUE(arr_[4U + i].IsScalar());
88             ASSERT_TRUE(arr_[8U + i].IsScalar());
89 
90             ASSERT_FALSE(arr_[i].IsFloat());
91             ASSERT_FALSE(arr_[4U + i].IsFloat());
92             ASSERT_FALSE(arr_[8U + i].IsFloat());
93 
94             ASSERT_NE(arr_[i], arr_[12U]);
95             ASSERT_NE(arr_[i], arr_[13U]);
96             ASSERT_NE(arr_[4U + i], arr_[12U]);
97             ASSERT_NE(arr_[4U + i], arr_[13U]);
98             ASSERT_NE(arr_[8U + i], arr_[12U]);
99             ASSERT_NE(arr_[8U + i], arr_[13U]);
100 
101             ASSERT_NE(arr_[i], arr_[14U]);
102             ASSERT_NE(arr_[i], arr_[15U]);
103             ASSERT_NE(arr_[4U + i], arr_[14U]);
104             ASSERT_NE(arr_[4U + i], arr_[15U]);
105             ASSERT_NE(arr_[8U + i], arr_[14U]);
106             ASSERT_NE(arr_[8U + i], arr_[15U]);
107             ASSERT_NE(arr_[i], arr_[16U]);
108             ASSERT_NE(arr_[i], arr_[17U]);
109             ASSERT_NE(arr_[4U + i], arr_[16U]);
110             ASSERT_NE(arr_[4U + i], arr_[17U]);
111             ASSERT_NE(arr_[8U + i], arr_[16U]);
112             ASSERT_NE(arr_[8U + i], arr_[17U]);
113         }
114     }
115 
CheckFloats()116     void CheckFloats()
117     {
118         // Float
119         ASSERT_TRUE(arr_[12U].IsValid());
120         ASSERT_TRUE(arr_[14U].IsValid());
121         ASSERT_TRUE(arr_[12U].IsFloat());
122         ASSERT_TRUE(arr_[14U].IsFloat());
123     }
124 
125 private:
126     uint8_t u8_ = 0;
127     int8_t i8_ = 0;
128     uint16_t u16_ = 0;
129     int16_t i16_ = 0;
130     uint32_t u32_ = 0;
131     int32_t i32_ = 0;
132     uint64_t u64_ = 0;
133     int64_t i64_ = 0;
134 
135     float f32_ = 0.0;
136     double f64_ = 0.0;
137 
138     // NOLINTNEXTLINE(readability-magic-numbers)
139     std::array<TypeInfo, 18U> arr_ {
140         TypeInfo(u8_),  // 0
141         TypeInfo(u16_),
142         TypeInfo(u32_),
143         TypeInfo(u64_),
144         TypeInfo(i8_),  // 4
145         TypeInfo(i16_),
146         TypeInfo(i32_),
147         TypeInfo(i64_),
148         TypeInfo(INT8_TYPE),  // 8
149         TypeInfo(INT16_TYPE),
150         TypeInfo(INT32_TYPE),
151         TypeInfo(INT64_TYPE),
152         TypeInfo(f32_),  // 12
153         TypeInfo(f64_),
154         TypeInfo(FLOAT32_TYPE),  // 14
155         TypeInfo(FLOAT64_TYPE),
156         TypeInfo(),  // 16
157         INVALID_TYPE,
158     };
159 };
160 
TEST_F(TypeInfoTest,Valid)161 TEST_F(TypeInfoTest, Valid)
162 {
163     CheckValid();
164     CheckFloats();
165 }
166 
TEST_F(TypeInfoTest,Sizes)167 TEST_F(TypeInfoTest, Sizes)
168 {
169     CheckSizes();
170     CompareSizes();
171 }
172 
TEST(Operands,Reg)173 TEST(Operands, Reg)
174 {
175     //  Size of structure
176     ASSERT_LE(sizeof(Reg), sizeof(size_t));
177 
178     ASSERT_EQ(INVALID_REGISTER.GetId(), INVALID_REG_ID);
179 
180     // Check, what it is possible to create all 32 registers
181     // for each type
182 
183     // Check what special registers are possible to compare with others
184 
185     // Check equality between registers
186 
187     // Check invalid registers
188 }
189 
TEST(Operands,ImmUnsignedSmall)190 TEST(Operands, ImmUnsignedSmall)
191 {
192     // Check all possible types:
193     //  Imm holds same data (static cast for un-signed)
194 
195     for (uint64_t i = 0; i < ITERATION; ++i) {
196         uint8_t u8 = g_randomGen(), u8Z = 0U, u8Min = std::numeric_limits<uint8_t>::min(),
197                 u8Max = std::numeric_limits<uint8_t>::max();
198         uint16_t u16 = g_randomGen(), u16Z = 0U, u16Min = std::numeric_limits<uint16_t>::min(),
199                  u16Max = std::numeric_limits<uint16_t>::max();
200         // Unsigned part - check across static_cast
201 
202         Imm immU8(u8), immU8Z(u8Z), immU8Min(u8Min), immU8Max(u8Max);
203         ASSERT_EQ(immU8.GetAsInt(), u8);
204         ASSERT_EQ(immU8Min.GetAsInt(), u8Min);
205         ASSERT_EQ(immU8Max.GetAsInt(), u8Max);
206         ASSERT_EQ(immU8Z.GetAsInt(), u8Z);
207 
208         TypedImm typedImmU8(u8), typedImmU8Z(u8Z);
209         ASSERT_EQ(typedImmU8Z.GetType(), INT8_TYPE);
210         ASSERT_EQ(typedImmU8.GetType(), INT8_TYPE);
211         ASSERT_EQ(typedImmU8Z.GetImm().GetAsInt(), u8Z);
212         ASSERT_EQ(typedImmU8.GetImm().GetAsInt(), u8);
213 
214         Imm immU16(u16), immU16Z(u16Z), immU16Min(u16Min), immU16Max(u16Max);
215         ASSERT_EQ(immU16.GetAsInt(), u16);
216         ASSERT_EQ(immU16Min.GetAsInt(), u16Min);
217         ASSERT_EQ(immU16Max.GetAsInt(), u16Max);
218         ASSERT_EQ(immU16Z.GetAsInt(), u16Z);
219 
220         TypedImm typedImmU16(u16), typedImmU16Z(u16Z);
221         ASSERT_EQ(typedImmU16Z.GetType(), INT16_TYPE);
222         ASSERT_EQ(typedImmU16.GetType(), INT16_TYPE);
223         ASSERT_EQ(typedImmU16Z.GetImm().GetAsInt(), u16Z);
224         ASSERT_EQ(typedImmU16.GetImm().GetAsInt(), u16);
225     }
226 
227 #ifndef NDEBUG
228     // Imm holds std::variant:
229     ASSERT_EQ(sizeof(Imm), sizeof(uint64_t) * 2U);
230 #else
231     // Imm holds 64-bit storage only:
232     ASSERT_EQ(sizeof(Imm), sizeof(uint64_t));
233 #endif  // NDEBUG
234 }
235 
TEST(Operands,ImmUnsignedLarge)236 TEST(Operands, ImmUnsignedLarge)
237 {
238     for (uint64_t i = 0; i < ITERATION; ++i) {
239         uint32_t u32 = g_randomGen(), u32Z = 0U, u32Min = std::numeric_limits<uint32_t>::min(),
240                  u32Max = std::numeric_limits<uint32_t>::max();
241         uint64_t u64 = g_randomGen(), u64Z = 0U, u64Min = std::numeric_limits<uint64_t>::min(),
242                  u64Max = std::numeric_limits<uint64_t>::max();
243 
244         Imm immU32(u32), immU32Z(u32Z), immU32Min(u32Min), immU32Max(u32Max);
245         ASSERT_EQ(immU32.GetAsInt(), u32);
246         ASSERT_EQ(immU32Min.GetAsInt(), u32Min);
247         ASSERT_EQ(immU32Max.GetAsInt(), u32Max);
248         ASSERT_EQ(immU32Z.GetAsInt(), u32Z);
249 
250         TypedImm typedImmU32(u32), typedImmU32Z(u32Z);
251         ASSERT_EQ(typedImmU32Z.GetType(), INT32_TYPE);
252         ASSERT_EQ(typedImmU32.GetType(), INT32_TYPE);
253         ASSERT_EQ(typedImmU32Z.GetImm().GetAsInt(), u32Z);
254         ASSERT_EQ(typedImmU32.GetImm().GetAsInt(), u32);
255 
256         Imm immU64(u64), immU64Z(u64Z), immU64Min(u64Min), immU64Max(u64Max);
257         ASSERT_EQ(immU64.GetAsInt(), u64);
258         ASSERT_EQ(immU64Min.GetAsInt(), u64Min);
259         ASSERT_EQ(immU64Max.GetAsInt(), u64Max);
260         ASSERT_EQ(immU64Z.GetAsInt(), u64Z);
261 
262         TypedImm typedImmU64(u64), typedImmU64Z(u64Z);
263         ASSERT_EQ(typedImmU64Z.GetType(), INT64_TYPE);
264         ASSERT_EQ(typedImmU64.GetType(), INT64_TYPE);
265         ASSERT_EQ(typedImmU64Z.GetImm().GetAsInt(), u64Z);
266         ASSERT_EQ(typedImmU64.GetImm().GetAsInt(), u64);
267     }
268 }
269 
TEST(Operands,ImmSignedSmall)270 TEST(Operands, ImmSignedSmall)
271 {
272     for (uint64_t i = 0; i < ITERATION; ++i) {
273         // Signed part
274 
275         int8_t i8 = g_randomGen(), i8Z = 0U, i8Min = std::numeric_limits<int8_t>::min(),
276                i8Max = std::numeric_limits<int8_t>::max();
277         int16_t i16 = g_randomGen(), i16Z = 0U, i16Min = std::numeric_limits<int16_t>::min(),
278                 i16Max = std::numeric_limits<int16_t>::max();
279 
280         Imm immI8(i8), immI8Z(i8Z), immI8Min(i8Min), immI8Max(i8Max);
281         ASSERT_EQ(immI8.GetAsInt(), i8);
282         ASSERT_EQ(immI8Min.GetAsInt(), i8Min);
283         ASSERT_EQ(immI8Max.GetAsInt(), i8Max);
284         ASSERT_EQ(immI8Z.GetAsInt(), i8Z);
285 
286         TypedImm typedImmI8(i8), typedImmI8Z(i8Z);
287         ASSERT_EQ(typedImmI8Z.GetType(), INT8_TYPE);
288         ASSERT_EQ(typedImmI8.GetType(), INT8_TYPE);
289         ASSERT_EQ(typedImmI8Z.GetImm().GetAsInt(), i8Z);
290         ASSERT_EQ(typedImmI8.GetImm().GetAsInt(), i8);
291 
292         Imm immI16(i16), immI16Z(i16Z), immI16Min(i16Min), immI16Max(i16Max);
293         ASSERT_EQ(immI16.GetAsInt(), i16);
294         ASSERT_EQ(immI16Min.GetAsInt(), i16Min);
295         ASSERT_EQ(immI16Max.GetAsInt(), i16Max);
296         ASSERT_EQ(immI16Z.GetAsInt(), i16Z);
297 
298         TypedImm typedImmI16(i16), typedImmI16Z(i16Z);
299         ASSERT_EQ(typedImmI16Z.GetType(), INT16_TYPE);
300         ASSERT_EQ(typedImmI16.GetType(), INT16_TYPE);
301         ASSERT_EQ(typedImmI16Z.GetImm().GetAsInt(), i16Z);
302         ASSERT_EQ(typedImmI16.GetImm().GetAsInt(), i16);
303     }
304 }
305 
TEST(Operands,ImmSignedLarge)306 TEST(Operands, ImmSignedLarge)
307 {
308     for (uint64_t i = 0; i < ITERATION; ++i) {
309         int32_t i32 = g_randomGen(), i32Z = 0U, i32Min = std::numeric_limits<int32_t>::min(),
310                 i32Max = std::numeric_limits<int32_t>::max();
311         int64_t i64 = g_randomGen(), i64Z = 0U, i64Min = std::numeric_limits<int64_t>::min(),
312                 i64Max = std::numeric_limits<int64_t>::max();
313 
314         Imm immI32(i32), immI32Z(i32Z), immI32Min(i32Min), immI32Max(i32Max);
315         ASSERT_EQ(immI32.GetAsInt(), i32);
316         ASSERT_EQ(immI32Min.GetAsInt(), i32Min);
317         ASSERT_EQ(immI32Max.GetAsInt(), i32Max);
318         ASSERT_EQ(immI32Z.GetAsInt(), i32Z);
319 
320         TypedImm typedImmI32(i32), typedImmI32Z(i32Z);
321         ASSERT_EQ(typedImmI32Z.GetType(), INT32_TYPE);
322         ASSERT_EQ(typedImmI32.GetType(), INT32_TYPE);
323         ASSERT_EQ(typedImmI32Z.GetImm().GetAsInt(), i32Z);
324         ASSERT_EQ(typedImmI32.GetImm().GetAsInt(), i32);
325 
326         Imm immI64(i64), immI64Z(i64Z), immI64Min(i64Min), immI64Max(i64Max);
327         ASSERT_EQ(immI64.GetAsInt(), i64);
328         ASSERT_EQ(immI64Min.GetAsInt(), i64Min);
329         ASSERT_EQ(immI64Max.GetAsInt(), i64Max);
330         ASSERT_EQ(immI64Z.GetAsInt(), i64Z);
331 
332         TypedImm typedImmI64(i64), typedImmI64Z(i64Z);
333         ASSERT_EQ(typedImmI64Z.GetType(), INT64_TYPE);
334         ASSERT_EQ(typedImmI64.GetType(), INT64_TYPE);
335         ASSERT_EQ(typedImmI64Z.GetImm().GetAsInt(), i64Z);
336         ASSERT_EQ(typedImmI64.GetImm().GetAsInt(), i64);
337     }
338 }
339 
TEST(Operands,ImmFloat)340 TEST(Operands, ImmFloat)
341 {
342     for (uint64_t i = 0; i < ITERATION; ++i) {
343         float f32 = g_randomGen(), f32Z = 0.0, f32Min = std::numeric_limits<float>::min(),
344               f32Max = std::numeric_limits<float>::max();
345         double f64 = g_randomGen(), f64Z = 0.0, f64Min = std::numeric_limits<double>::min(),
346                f64Max = std::numeric_limits<double>::max();
347 
348         // Float test:
349         Imm immF32(f32), immF32Z(f32Z), immF32Min(f32Min), immF32Max(f32Max);
350         ASSERT_EQ(immF32.GetAsFloat(), f32);
351         ASSERT_EQ(immF32Min.GetAsFloat(), f32Min);
352         ASSERT_EQ(immF32Max.GetAsFloat(), f32Max);
353         ASSERT_EQ(immF32Z.GetAsFloat(), f32Z);
354         ASSERT_EQ(bit_cast<float>(static_cast<int32_t>(immF32.GetRawValue())), f32);
355         ASSERT_EQ(bit_cast<float>(static_cast<int32_t>(immF32Min.GetRawValue())), f32Min);
356         ASSERT_EQ(bit_cast<float>(static_cast<int32_t>(immF32Max.GetRawValue())), f32Max);
357         ASSERT_EQ(bit_cast<float>(static_cast<int32_t>(immF32Z.GetRawValue())), f32Z);
358 
359         TypedImm typedImmF32(f32), typedImmF32Z(f32Z);
360         ASSERT_EQ(typedImmF32Z.GetType(), FLOAT32_TYPE);
361         ASSERT_EQ(typedImmF32.GetType(), FLOAT32_TYPE);
362         ASSERT_EQ(typedImmF32Z.GetImm().GetAsFloat(), f32Z);
363         ASSERT_EQ(typedImmF32.GetImm().GetAsFloat(), f32);
364 
365         Imm immF64(f64), immF64Z(f64Z), immF64Min(f64Min), immF64Max(f64Max);
366         ASSERT_EQ(immF64.GetAsDouble(), f64);
367         ASSERT_EQ(immF64Min.GetAsDouble(), f64Min);
368         ASSERT_EQ(immF64Max.GetAsDouble(), f64Max);
369         ASSERT_EQ(immF64Z.GetAsDouble(), f64Z);
370         ASSERT_EQ(bit_cast<double>(immF64.GetRawValue()), f64);
371         ASSERT_EQ(bit_cast<double>(immF64Min.GetRawValue()), f64Min);
372         ASSERT_EQ(bit_cast<double>(immF64Max.GetRawValue()), f64Max);
373         ASSERT_EQ(bit_cast<double>(immF64Z.GetRawValue()), f64Z);
374 
375         TypedImm typedImmF64(f64), typedImmF64Z(f64Z);
376         ASSERT_EQ(typedImmF64Z.GetType(), FLOAT64_TYPE);
377         ASSERT_EQ(typedImmF64.GetType(), FLOAT64_TYPE);
378         ASSERT_EQ(typedImmF64Z.GetImm().GetAsDouble(), f64Z);
379         ASSERT_EQ(typedImmF64.GetImm().GetAsDouble(), f64);
380     }
381 }
382 
TEST(Operands,MemRef)383 TEST(Operands, MemRef)
384 {
385     Reg r1(1U, INT64_TYPE), r2(2U, INT64_TYPE), rI(INVALID_REG_ID, INVALID_TYPE);
386     ssize_t i1(0x0U), i2(0x2U);
387 
388     // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
389     std::array<MemRef, 3U> arr {MemRef(r1), MemRef(r1, i1), MemRef(r1)};
390     // 1. Check constructors
391     //  for getters
392     //  for validness
393     //  for operator ==
394     // 2. Create mem with invalid_reg / invalid imm
395 }
396 // NOLINTEND(readability-isolate-declaration)
397 
398 }  // namespace ark::compiler
399