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