1 /**
2 * Copyright (c) 2021-2022 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 static inline auto random_gen = std::mt19937_64(SEED);
26
27 // Encoder header
28 #include "optimizer/code_generator/operands.h"
29
30 namespace panda::compiler {
TEST(Operands,TypeInfo)31 TEST(Operands, TypeInfo)
32 {
33 uint8_t u8;
34 int8_t i8;
35 uint16_t u16;
36 int16_t i16;
37 uint32_t u32;
38 int32_t i32;
39 uint64_t u64;
40 int64_t i64;
41
42 float f32;
43 double f64;
44
45 TypeInfo arr[] = {
46 TypeInfo(u8), // 0
47 TypeInfo(u16),
48 TypeInfo(u32),
49 TypeInfo(u64),
50 TypeInfo(i8), // 4
51 TypeInfo(i16),
52 TypeInfo(i32),
53 TypeInfo(i64),
54 TypeInfo(INT8_TYPE), // 8
55 TypeInfo(INT16_TYPE),
56 TypeInfo(INT32_TYPE),
57 TypeInfo(INT64_TYPE),
58 TypeInfo(f32), // 12
59 TypeInfo(f64),
60 TypeInfo(FLOAT32_TYPE), // 14
61 TypeInfo(FLOAT64_TYPE),
62 TypeInfo(), // 16
63 INVALID_TYPE,
64 };
65
66 for (uint8_t i = 0; i < sizeof(arr) / sizeof(TypeInfo); ++i) {
67 if (i >= 16) {
68 ASSERT_FALSE(arr[i].IsValid());
69 } else {
70 ASSERT_TRUE(arr[i].IsValid());
71 }
72 }
73
74 for (int i = 0; i < 4; ++i) {
75 ASSERT_EQ(arr[i], arr[4 + i]);
76 ASSERT_EQ(arr[i], arr[8 + i]);
77 ASSERT_EQ(arr[4 + i], arr[8 + i]);
78
79 ASSERT_EQ(arr[i].GetSize(), arr[4 + i].GetSize());
80 ASSERT_EQ(arr[i].GetSize(), arr[8 + i].GetSize());
81 ASSERT_EQ(arr[4 + i].GetSize(), arr[8 + i].GetSize());
82
83 ASSERT_TRUE(arr[i].IsScalar());
84 ASSERT_TRUE(arr[4 + i].IsScalar());
85 ASSERT_TRUE(arr[8 + i].IsScalar());
86
87 ASSERT_FALSE(arr[i].IsFloat());
88 ASSERT_FALSE(arr[4 + i].IsFloat());
89 ASSERT_FALSE(arr[8 + i].IsFloat());
90
91 ASSERT_NE(arr[i], arr[12]);
92 ASSERT_NE(arr[i], arr[13]);
93 ASSERT_NE(arr[4 + i], arr[12]);
94 ASSERT_NE(arr[4 + i], arr[13]);
95 ASSERT_NE(arr[8 + i], arr[12]);
96 ASSERT_NE(arr[8 + i], arr[13]);
97
98 ASSERT_NE(arr[i], arr[14]);
99 ASSERT_NE(arr[i], arr[15]);
100 ASSERT_NE(arr[4 + i], arr[14]);
101 ASSERT_NE(arr[4 + i], arr[15]);
102 ASSERT_NE(arr[8 + i], arr[14]);
103 ASSERT_NE(arr[8 + i], arr[15]);
104 ASSERT_NE(arr[i], arr[16]);
105 ASSERT_NE(arr[i], arr[17]);
106 ASSERT_NE(arr[4 + i], arr[16]);
107 ASSERT_NE(arr[4 + i], arr[17]);
108 ASSERT_NE(arr[8 + i], arr[16]);
109 ASSERT_NE(arr[8 + i], arr[17]);
110 }
111 // Float
112 ASSERT_EQ(arr[2].GetSize(), arr[12].GetSize());
113 ASSERT_EQ(arr[2].GetSize(), arr[14].GetSize());
114
115 ASSERT_TRUE(arr[12].IsValid());
116 ASSERT_TRUE(arr[14].IsValid());
117 ASSERT_TRUE(arr[12].IsFloat());
118 ASSERT_TRUE(arr[14].IsFloat());
119 // Double
120 ASSERT_EQ(arr[3].GetSize(), arr[13].GetSize());
121 ASSERT_EQ(arr[3].GetSize(), arr[15].GetSize());
122
123 // Check sizes:
124 ASSERT_EQ(BYTE_SIZE, HALF_SIZE / 2);
125 ASSERT_EQ(HALF_SIZE, WORD_SIZE / 2);
126 ASSERT_EQ(WORD_SIZE, DOUBLE_WORD_SIZE / 2);
127
128 ASSERT_EQ(arr[0].GetSize(), BYTE_SIZE);
129 ASSERT_EQ(arr[1].GetSize(), HALF_SIZE);
130 ASSERT_EQ(arr[2].GetSize(), WORD_SIZE);
131 ASSERT_EQ(arr[3].GetSize(), DOUBLE_WORD_SIZE);
132
133 ASSERT_EQ(sizeof(TypeInfo), sizeof(uint8_t));
134
135 ASSERT_EQ(TypeInfo(u8), INT8_TYPE);
136 ASSERT_EQ(TypeInfo(u16), INT16_TYPE);
137 ASSERT_EQ(TypeInfo(u32), INT32_TYPE);
138 ASSERT_EQ(TypeInfo(u64), INT64_TYPE);
139
140 ASSERT_EQ(TypeInfo(f32), FLOAT32_TYPE);
141 ASSERT_EQ(TypeInfo(f64), FLOAT64_TYPE);
142 }
143
TEST(Operands,Reg)144 TEST(Operands, Reg)
145 {
146 // Size of structure
147 ASSERT_LE(sizeof(Reg), sizeof(size_t));
148
149 ASSERT_EQ(INVALID_REGISTER.GetId(), INVALID_REG_ID);
150
151 // Check, what it is possible to create all 32 registers
152 // for each type
153
154 // Check what special registers are possible to compare with others
155
156 // Check equality between registers
157
158 // Check invalid registers
159 }
160
TEST(Operands,Imm)161 TEST(Operands, Imm)
162 {
163 // Check all possible types:
164 // Imm holds same data (static cast for un-signed)
165 // GetType
166 // Getsize
167 // Is scalar
168 // Is Valid
169 // Bounary checks
170 // Check IsZero
171 // Inc/dec checks
172 // INVALID_IMM check
173
174 for (uint64_t i = 0; i < ITERATION; ++i) {
175 uint8_t u8 = random_gen(), u8_z = 0, u8_min = std::numeric_limits<uint8_t>::min(),
176 u8_max = std::numeric_limits<uint8_t>::max();
177 uint16_t u16 = random_gen(), u16_z = 0, u16_min = std::numeric_limits<uint16_t>::min(),
178 u16_max = std::numeric_limits<uint16_t>::max();
179 uint32_t u32 = random_gen(), u32_z = 0, u32_min = std::numeric_limits<uint32_t>::min(),
180 u32_max = std::numeric_limits<uint32_t>::max();
181 uint64_t u64 = random_gen(), u64_z = 0, u64_min = std::numeric_limits<uint64_t>::min(),
182 u64_max = std::numeric_limits<uint64_t>::max();
183
184 int8_t i8 = random_gen(), i8_z = 0, i8_min = std::numeric_limits<int8_t>::min(),
185 i8_max = std::numeric_limits<int8_t>::max();
186 int16_t i16 = random_gen(), i16_z = 0, i16_min = std::numeric_limits<int16_t>::min(),
187 i16_max = std::numeric_limits<int16_t>::max();
188 int32_t i32 = random_gen(), i32_z = 0, i32_min = std::numeric_limits<int32_t>::min(),
189 i32_max = std::numeric_limits<int32_t>::max();
190 int64_t i64 = random_gen(), i64_z = 0, i64_min = std::numeric_limits<int64_t>::min(),
191 i64_max = std::numeric_limits<int64_t>::max();
192
193 float f32 = random_gen(), f32_z = 0, f32_min = std::numeric_limits<float>::min(),
194 f32_max = std::numeric_limits<float>::max();
195 double f64 = random_gen(), f64_z = 0, f64_min = std::numeric_limits<double>::min(),
196 f64_max = std::numeric_limits<double>::max();
197
198 // Unsigned part - check across static_cast
199
200 Imm imm_u8(u8), imm_u8_z(u8_z), imm_u8_min(u8_min), imm_u8_max(u8_max);
201 ASSERT_EQ(imm_u8.GetValue<int8_t>(), static_cast<int8_t>(u8));
202 ASSERT_EQ(imm_u8_min.GetValue<int8_t>(), static_cast<int8_t>(u8_min));
203 ASSERT_EQ(imm_u8_max.GetValue<int8_t>(), static_cast<int8_t>(u8_max));
204 ASSERT_EQ(imm_u8_z.GetValue<int8_t>(), static_cast<int8_t>(u8_z));
205
206 ASSERT_TRUE(imm_u8_min.IsZero());
207 ASSERT_TRUE(imm_u8_z.IsZero());
208 ASSERT_FALSE(imm_u8_max.IsZero());
209
210 ASSERT_TRUE(imm_u8.IsValid());
211 ASSERT_TRUE(imm_u8_z.IsValid());
212 ASSERT_TRUE(imm_u8_min.IsValid());
213 ASSERT_TRUE(imm_u8_max.IsValid());
214
215 Imm imm_u16(u16), imm_u16_z(u16_z), imm_u16_min(u16_min), imm_u16_max(u16_max);
216 ASSERT_EQ(imm_u16.GetValue<int16_t>(), static_cast<int16_t>(u16));
217 ASSERT_EQ(imm_u16_min.GetValue<int16_t>(), static_cast<int16_t>(u16_min));
218 ASSERT_EQ(imm_u16_max.GetValue<int16_t>(), static_cast<int16_t>(u16_max));
219 ASSERT_EQ(imm_u16_z.GetValue<int16_t>(), static_cast<int16_t>(u16_z));
220
221 ASSERT_TRUE(imm_u16_min.IsZero());
222 ASSERT_TRUE(imm_u16_z.IsZero());
223 ASSERT_FALSE(imm_u16_max.IsZero());
224
225 ASSERT_TRUE(imm_u16.IsValid());
226 ASSERT_TRUE(imm_u16_z.IsValid());
227 ASSERT_TRUE(imm_u16_min.IsValid());
228 ASSERT_TRUE(imm_u16_max.IsValid());
229
230 Imm imm_u32(u32), imm_u32_z(u32_z), imm_u32_min(u32_min), imm_u32_max(u32_max);
231 ASSERT_EQ(imm_u32.GetValue<int32_t>(), static_cast<int32_t>(u32));
232 ASSERT_EQ(imm_u32_min.GetValue<int32_t>(), static_cast<int32_t>(u32_min));
233 ASSERT_EQ(imm_u32_max.GetValue<int32_t>(), static_cast<int32_t>(u32_max));
234 ASSERT_EQ(imm_u32_z.GetValue<int32_t>(), static_cast<int32_t>(u32_z));
235
236 ASSERT_TRUE(imm_u32_min.IsZero());
237 ASSERT_TRUE(imm_u32_z.IsZero());
238 ASSERT_FALSE(imm_u32_max.IsZero());
239
240 ASSERT_TRUE(imm_u32.IsValid());
241 ASSERT_TRUE(imm_u32_z.IsValid());
242 ASSERT_TRUE(imm_u32_min.IsValid());
243 ASSERT_TRUE(imm_u32_max.IsValid());
244
245 Imm imm_u64(u64), imm_u64_z(u64_z), imm_u64_min(u64_min), imm_u64_max(u64_max);
246 ASSERT_EQ(imm_u64.GetValue<int64_t>(), static_cast<int64_t>(u64));
247 ASSERT_EQ(imm_u64_min.GetValue<int64_t>(), static_cast<int64_t>(u64_min));
248 ASSERT_EQ(imm_u64_max.GetValue<int64_t>(), static_cast<int64_t>(u64_max));
249 ASSERT_EQ(imm_u64_z.GetValue<int64_t>(), static_cast<int64_t>(u64_z));
250
251 ASSERT_TRUE(imm_u64_min.IsZero());
252 ASSERT_TRUE(imm_u64_z.IsZero());
253 ASSERT_FALSE(imm_u64_max.IsZero());
254
255 ASSERT_TRUE(imm_u64.IsValid());
256 ASSERT_TRUE(imm_u64_z.IsValid());
257 ASSERT_TRUE(imm_u64_min.IsValid());
258 ASSERT_TRUE(imm_u64_max.IsValid());
259
260 // Signed part
261
262 Imm imm_i8(i8), imm_i8_z(i8_z), imm_i8_min(i8_min), imm_i8_max(i8_max);
263 ASSERT_EQ(imm_i8.GetValue<int8_t>(), i8);
264 ASSERT_EQ(imm_i8_min.GetValue<int8_t>(), i8_min);
265 ASSERT_EQ(imm_i8_max.GetValue<int8_t>(), i8_max);
266 ASSERT_EQ(imm_i8_z.GetValue<int8_t>(), i8_z);
267
268 ASSERT_FALSE(imm_i8_min.IsZero());
269 ASSERT_TRUE(imm_i8_z.IsZero());
270 ASSERT_FALSE(imm_i8_max.IsZero());
271
272 ASSERT_TRUE(imm_i8.IsValid());
273 ASSERT_TRUE(imm_i8_z.IsValid());
274 ASSERT_TRUE(imm_i8_min.IsValid());
275 ASSERT_TRUE(imm_i8_max.IsValid());
276
277 Imm imm_i16(i16), imm_i16_z(i16_z), imm_i16_min(i16_min), imm_i16_max(i16_max);
278 ASSERT_EQ(imm_i16.GetValue<int16_t>(), i16);
279 ASSERT_EQ(imm_i16_min.GetValue<int16_t>(), i16_min);
280 ASSERT_EQ(imm_i16_max.GetValue<int16_t>(), i16_max);
281 ASSERT_EQ(imm_i16_z.GetValue<int16_t>(), i16_z);
282
283 ASSERT_FALSE(imm_i16_min.IsZero());
284 ASSERT_TRUE(imm_i16_z.IsZero());
285 ASSERT_FALSE(imm_i16_max.IsZero());
286
287 ASSERT_TRUE(imm_i16.IsValid());
288 ASSERT_TRUE(imm_i16_z.IsValid());
289 ASSERT_TRUE(imm_i16_min.IsValid());
290 ASSERT_TRUE(imm_i16_max.IsValid());
291
292 Imm imm_i32(i32), imm_i32_z(i32_z), imm_i32_min(i32_min), imm_i32_max(i32_max);
293 ASSERT_EQ(imm_i32.GetValue<int32_t>(), i32);
294 ASSERT_EQ(imm_i32_min.GetValue<int32_t>(), i32_min);
295 ASSERT_EQ(imm_i32_max.GetValue<int32_t>(), i32_max);
296 ASSERT_EQ(imm_i32_z.GetValue<int32_t>(), i32_z);
297
298 ASSERT_FALSE(imm_i32_min.IsZero());
299 ASSERT_TRUE(imm_i32_z.IsZero());
300 ASSERT_FALSE(imm_i32_max.IsZero());
301
302 ASSERT_TRUE(imm_i32.IsValid());
303 ASSERT_TRUE(imm_i32_z.IsValid());
304 ASSERT_TRUE(imm_i32_min.IsValid());
305 ASSERT_TRUE(imm_i32_max.IsValid());
306
307 Imm imm_i64(i64), imm_i64_z(i64_z), imm_i64_min(i64_min), imm_i64_max(i64_max);
308 ASSERT_EQ(imm_i64.GetValue<int64_t>(), i64);
309 ASSERT_EQ(imm_i64_min.GetValue<int64_t>(), i64_min);
310 ASSERT_EQ(imm_i64_max.GetValue<int64_t>(), i64_max);
311 ASSERT_EQ(imm_i64_z.GetValue<int64_t>(), i64_z);
312
313 ASSERT_FALSE(imm_i64_min.IsZero());
314 ASSERT_TRUE(imm_i64_z.IsZero());
315 ASSERT_FALSE(imm_i64_max.IsZero());
316
317 ASSERT_TRUE(imm_i64.IsValid());
318 ASSERT_TRUE(imm_i64_z.IsValid());
319 ASSERT_TRUE(imm_i64_min.IsValid());
320 ASSERT_TRUE(imm_i64_max.IsValid());
321 }
322 // Sizeof imm:
323 // Imm holds 2 uint64_t values (std::variant)
324 ASSERT_LE(sizeof(Imm), sizeof(uint64_t) * 2);
325 }
326
TEST(Operands,MemRef)327 TEST(Operands, MemRef)
328 {
329 Reg r1(1, INT64_TYPE), r2(2, INT64_TYPE), r_i(INVALID_REG_ID, INVALID_TYPE);
330 ssize_t i1(0x0), i2(0x2);
331
332 MemRef arr[] {MemRef(r1), MemRef(r1, i1), MemRef(r1)};
333 // 1. Check constructors
334 // for getters
335 // for validness
336 // for operator ==
337 // 2. Create mem with invalid_reg / invalid imm
338 }
339 } // namespace panda::compiler
340