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 "common.h"
17 #include "const_array_resolver.h"
18
19 namespace panda::bytecodeopt::test {
20
TEST_F(CommonTest,ConstArrayResolverInt64)21 TEST_F(CommonTest, ConstArrayResolverInt64)
22 {
23 auto graph = CreateEmptyGraph();
24 GRAPH(graph)
25 {
26 CONSTANT(1, 2).s64();
27 CONSTANT(2, 0).s64();
28
29 BASIC_BLOCK(2, -1)
30 {
31 INST(20, Opcode::SaveState).NoVregs();
32 INST(4, Opcode::LoadAndInitClass).ref().Inputs(20).TypeId(68);
33 INST(3, Opcode::NewArray).ref().Inputs(4, 1, 20);
34 INST(11, Opcode::StoreArray).u64().Inputs(3, 2, 2);
35 INST(13, Opcode::StoreArray).u64().Inputs(3, 2, 2);
36 INST(10, Opcode::Return).ref().Inputs(3);
37 }
38 }
39
40 pandasm::Program program;
41 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
42 maps.classes.emplace(0, "i64[]");
43 IrInterfaceTest interface(&program, &maps);
44 options.SetConstArrayResolver(true);
45 EXPECT_TRUE(graph->RunPass<ConstArrayResolver>(&interface));
46 auto expected = CreateEmptyGraph();
47 GRAPH(expected)
48 {
49 CONSTANT(1, 2).s64();
50 CONSTANT(2, 0).s64();
51
52 BASIC_BLOCK(2, -1)
53 {
54 INST(20, Opcode::SaveState).NoVregs();
55 INST(4, Opcode::LoadAndInitClass).ref().Inputs(20).TypeId(68);
56 INST(22, Opcode::SaveState).NoVregs();
57 INST(21, Opcode::LoadConstArray).ref().Inputs(22);
58 INST(10, Opcode::Return).ref().Inputs(21);
59 }
60 }
61 EXPECT_TRUE(GraphComparator().Compare(graph, expected));
62 }
63
TEST_F(CommonTest,ConstArrayResolverInt32)64 TEST_F(CommonTest, ConstArrayResolverInt32)
65 {
66 auto graph = CreateEmptyGraph();
67 GRAPH(graph)
68 {
69 CONSTANT(1, 2).s32();
70 CONSTANT(2, 0).s32();
71
72 BASIC_BLOCK(2, -1)
73 {
74 INST(20, Opcode::SaveState).NoVregs();
75 INST(4, Opcode::LoadAndInitClass).ref().Inputs(20).TypeId(68);
76 INST(3, Opcode::NewArray).ref().Inputs(4, 1, 20);
77 INST(11, Opcode::StoreArray).u32().Inputs(3, 2, 2);
78 INST(13, Opcode::StoreArray).u32().Inputs(3, 2, 2);
79 INST(10, Opcode::Return).ref().Inputs(3);
80 }
81 }
82
83 pandasm::Program program;
84 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
85 maps.classes.emplace(0, "i32[]");
86 IrInterfaceTest interface(&program, &maps);
87 options.SetConstArrayResolver(true);
88 EXPECT_TRUE(graph->RunPass<ConstArrayResolver>(&interface));
89 }
90
TEST_F(CommonTest,ConstArrayResolverFloat32)91 TEST_F(CommonTest, ConstArrayResolverFloat32)
92 {
93 auto graph = CreateEmptyGraph();
94 GRAPH(graph)
95 {
96 CONSTANT(0, 3).s32();
97 CONSTANT(4, 0).s32();
98 CONSTANT(6, 100).f64();
99 CONSTANT(10, 1).s32();
100 CONSTANT(13, 200).f64();
101 CONSTANT(16, 2).s32();
102 CONSTANT(20, 300).f64();
103
104 BASIC_BLOCK(2, -1)
105 {
106 using namespace compiler::DataType;
107
108 INST(3, Opcode::SaveState).NoVregs();
109 INST(44, Opcode::LoadAndInitClass).ref().Inputs(3).TypeId(68);
110 INST(5, Opcode::NewArray).ref().Inputs(44, 0, 3);
111 INST(12, Opcode::Cast).f32().SrcType(FLOAT64).Inputs(6);
112 INST(11, Opcode::StoreArray).f32().Inputs(5, 4, 12);
113 INST(19, Opcode::Cast).f32().SrcType(FLOAT64).Inputs(13);
114 INST(18, Opcode::StoreArray).f32().Inputs(5, 10, 19);
115 INST(26, Opcode::Cast).f32().SrcType(FLOAT64).Inputs(20);
116 INST(25, Opcode::StoreArray).f32().Inputs(5, 16, 26);
117 INST(27, Opcode::Return).ref().Inputs(5);
118 }
119 }
120
121 pandasm::Program program;
122 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
123 maps.classes.emplace(0, "f32[]");
124 IrInterfaceTest interface(&program, &maps);
125 options.SetConstArrayResolver(true);
126 EXPECT_TRUE(graph->RunPass<ConstArrayResolver>(&interface));
127 }
128
TEST_F(CommonTest,ConstArrayResolverFloat64)129 TEST_F(CommonTest, ConstArrayResolverFloat64)
130 {
131 auto graph = CreateEmptyGraph();
132 GRAPH(graph)
133 {
134 CONSTANT(0, 0).s32();
135 CONSTANT(1, 1).s32();
136 CONSTANT(2, 2).s32();
137 CONSTANT(3, 100.0).f64();
138 CONSTANT(4, 200.0).f64();
139
140 BASIC_BLOCK(2, -1)
141 {
142 INST(20, Opcode::SaveState).NoVregs();
143 INST(44, Opcode::LoadAndInitClass).ref().Inputs(20).TypeId(68);
144 INST(5, Opcode::NewArray).ref().Inputs(44, 2, 20);
145 INST(11, Opcode::StoreArray).f64().Inputs(5, 0, 3);
146 INST(13, Opcode::StoreArray).f64().Inputs(5, 1, 4);
147 INST(10, Opcode::Return).ref().Inputs(5);
148 }
149 }
150
151 pandasm::Program program;
152 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
153 maps.classes.emplace(0, "f64[]");
154 IrInterfaceTest interface(&program, &maps);
155 options.SetConstArrayResolver(true);
156 EXPECT_TRUE(graph->RunPass<ConstArrayResolver>(&interface));
157 }
158
TEST_F(CommonTest,ConstArrayResolverByteAccess)159 TEST_F(CommonTest, ConstArrayResolverByteAccess)
160 {
161 auto graph = CreateEmptyGraph();
162 GRAPH(graph)
163 {
164 CONSTANT(0, 0).s32();
165 CONSTANT(1, 1).s32();
166 CONSTANT(2, 2).s32();
167 CONSTANT(3, 3).s32();
168
169 BASIC_BLOCK(2, -1)
170 {
171 INST(4, Opcode::SaveState).NoVregs();
172 INST(44, Opcode::LoadAndInitClass).ref().Inputs(4).TypeId(68);
173 INST(5, Opcode::NewArray).ref().Inputs(44, 3, 4);
174 INST(6, Opcode::StoreArray).s8().Inputs(5, 0, 0);
175 INST(7, Opcode::StoreArray).s8().Inputs(5, 1, 1);
176 INST(8, Opcode::StoreArray).s8().Inputs(5, 2, 2);
177 INST(9, Opcode::Return).ref().Inputs(5);
178 ;
179 }
180 }
181
182 pandasm::Program program;
183 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
184 maps.classes.emplace(0, "i8[]");
185 IrInterfaceTest interface(&program, &maps);
186 options.SetConstArrayResolver(true);
187 EXPECT_TRUE(graph->RunPass<ConstArrayResolver>(&interface));
188
189 auto expected = CreateEmptyGraph();
190 GRAPH(expected)
191 {
192 CONSTANT(0, 0).s32();
193 CONSTANT(1, 1).s32();
194 CONSTANT(2, 2).s32();
195 CONSTANT(3, 3).s32();
196
197 BASIC_BLOCK(2, -1)
198 {
199 INST(4, Opcode::SaveState).NoVregs();
200 INST(44, Opcode::LoadAndInitClass).ref().Inputs(4).TypeId(68);
201 INST(11, Opcode::SaveState).NoVregs();
202 INST(10, Opcode::LoadConstArray).ref().Inputs(11);
203 INST(9, Opcode::Return).ref().Inputs(10);
204 }
205 }
206
207 EXPECT_TRUE(GraphComparator().Compare(graph, expected));
208 }
209
TEST_F(CommonTest,ConstArrayResolverStringAccess)210 TEST_F(CommonTest, ConstArrayResolverStringAccess)
211 {
212 auto graph = CreateEmptyGraph();
213 GRAPH(graph)
214 {
215 CONSTANT(0, 0).s32();
216 CONSTANT(1, 1).s32();
217 CONSTANT(2, 2).s32();
218 CONSTANT(3, 3).s32();
219
220 BASIC_BLOCK(2, -1)
221 {
222 INST(4, Opcode::SaveState).NoVregs();
223 INST(44, Opcode::LoadAndInitClass).ref().Inputs(4).TypeId(68);
224 INST(5, Opcode::NewArray).ref().Inputs(44, 3, 4);
225
226 INST(6, Opcode::SaveState).NoVregs();
227 INST(7, Opcode::LoadString).ref().Inputs(6);
228 INST(8, Opcode::StoreArray).ref().Inputs(5, 0, 7);
229
230 INST(9, Opcode::SaveState).NoVregs();
231 INST(10, Opcode::LoadString).ref().Inputs(9);
232 INST(11, Opcode::StoreArray).ref().Inputs(5, 1, 10);
233
234 INST(12, Opcode::SaveState).NoVregs();
235 INST(13, Opcode::LoadString).ref().Inputs(12);
236 INST(24, Opcode::StoreArray).ref().Inputs(5, 2, 13);
237
238 INST(15, Opcode::Return).ref().Inputs(5);
239 }
240 }
241
242 pandasm::Program program;
243 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
244 maps.classes.emplace(0, "panda/String[]");
245 IrInterfaceTest interface(&program, &maps);
246 options.SetConstArrayResolver(true);
247 EXPECT_TRUE(graph->RunPass<ConstArrayResolver>(&interface));
248
249 auto expected = CreateEmptyGraph();
250 GRAPH(expected)
251 {
252 CONSTANT(0, 0).s32();
253 CONSTANT(1, 1).s32();
254 CONSTANT(2, 2).s32();
255 CONSTANT(3, 3).s32();
256
257 BASIC_BLOCK(2, -1)
258 {
259 INST(4, Opcode::SaveState).NoVregs();
260 INST(44, Opcode::LoadAndInitClass).ref().Inputs(4).TypeId(68);
261 INST(5, Opcode::SaveState).NoVregs();
262 INST(6, Opcode::LoadConstArray).ref().Inputs(5);
263
264 INST(7, Opcode::SaveState).NoVregs();
265 INST(8, Opcode::LoadString).ref().Inputs(7);
266 INST(9, Opcode::SaveState).NoVregs();
267 INST(10, Opcode::LoadString).ref().Inputs(9);
268 INST(11, Opcode::SaveState).NoVregs();
269 INST(12, Opcode::LoadString).ref().Inputs(11);
270
271 INST(13, Opcode::Return).ref().Inputs(6);
272 }
273 }
274
275 EXPECT_TRUE(GraphComparator().Compare(graph, expected));
276 }
277
TEST_F(CommonTest,ConstArrayResolverParameterAsArray)278 TEST_F(CommonTest, ConstArrayResolverParameterAsArray)
279 {
280 auto graph = CreateEmptyGraph();
281 GRAPH(graph)
282 {
283 PARAMETER(0, 0).ref();
284 CONSTANT(1, 0).s64();
285 CONSTANT(2, 0).s64();
286
287 BASIC_BLOCK(2, -1)
288 {
289 INST(3, Opcode::LoadArray).u64().Inputs(0, 1);
290 INST(4, Opcode::Return).u64().Inputs(3);
291 }
292 }
293
294 pandasm::Program program;
295 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
296 maps.classes.emplace(0, "i64[]");
297 IrInterfaceTest interface(&program, &maps);
298 options.SetConstArrayResolver(true);
299 EXPECT_FALSE(graph->RunPass<ConstArrayResolver>(&interface));
300 }
301
TEST_F(CommonTest,ConstArrayResolverDifferentBlocks)302 TEST_F(CommonTest, ConstArrayResolverDifferentBlocks)
303 {
304 auto graph = CreateEmptyGraph();
305 GRAPH(graph)
306 {
307 PARAMETER(0, 0).s32();
308 CONSTANT(1, 0).s64();
309 CONSTANT(2, 0).s64();
310
311 BASIC_BLOCK(2, 3, 4)
312 {
313 INST(3, Opcode::SaveState);
314 INST(44, Opcode::LoadAndInitClass).ref().Inputs(3).TypeId(68);
315 INST(4, Opcode::NewArray).ref().Inputs(44, 1, 3);
316 INST(5, Opcode::IfImm).SrcType(compiler::DataType::INT32).CC(compiler::CC_EQ).Imm(0).Inputs(0);
317 }
318 BASIC_BLOCK(3, -1)
319 {
320 INST(6, Opcode::StoreArray).u64().Inputs(4, 1, 2);
321 INST(7, Opcode::Return).ref().Inputs(4);
322 }
323 BASIC_BLOCK(4, -1)
324 {
325 INST(8, Opcode::ReturnVoid).v0id();
326 }
327 }
328
329 pandasm::Program program;
330 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
331 maps.classes.emplace(0, "i64[]");
332 IrInterfaceTest interface(&program, &maps);
333 options.SetConstArrayResolver(true);
334 EXPECT_FALSE(graph->RunPass<ConstArrayResolver>(&interface));
335 }
336
TEST_F(CommonTest,ConstArrayResolverArraySizeNotConstant)337 TEST_F(CommonTest, ConstArrayResolverArraySizeNotConstant)
338 {
339 auto graph = CreateEmptyGraph();
340 GRAPH(graph)
341 {
342 PARAMETER(0, 0).s64();
343 CONSTANT(4, 0).s64();
344 CONSTANT(5, 0).s64();
345
346 BASIC_BLOCK(2, -1)
347 {
348 INST(1, Opcode::SaveState);
349 INST(44, Opcode::LoadAndInitClass).ref().Inputs(1).TypeId(68);
350 INST(2, Opcode::NewArray).ref().Inputs(44, 0, 1);
351 INST(3, Opcode::StoreArray).u64().Inputs(2, 4, 5);
352 INST(6, Opcode::ReturnVoid).v0id();
353 }
354 }
355
356 pandasm::Program program;
357 pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps;
358 maps.classes.emplace(0, "i64[]");
359 IrInterfaceTest interface(&program, &maps);
360 options.SetConstArrayResolver(true);
361 EXPECT_FALSE(graph->RunPass<ConstArrayResolver>(&interface));
362 }
363
364 } // namespace panda::bytecodeopt::test
365