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 "unit_test.h"
17
18 #include "optimizer/optimizations/cleanup.h"
19
20 namespace panda::compiler {
21 class CleanupTest : public GraphTest {
22 };
23
TEST_F(CleanupTest,Simple)24 TEST_F(CleanupTest, Simple)
25 {
26 GRAPH(GetGraph())
27 {
28 BASIC_BLOCK(2, 3) {}
29 BASIC_BLOCK(3, -1)
30 {
31 INST(0, Opcode::ReturnVoid);
32 }
33 }
34
35 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
36
37 auto graph = CreateEmptyGraph();
38 GRAPH(graph)
39 {
40 BASIC_BLOCK(3, -1)
41 {
42 INST(0, Opcode::ReturnVoid);
43 }
44 }
45 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
46 }
47
TEST_F(CleanupTest,BothHasPhi)48 TEST_F(CleanupTest, BothHasPhi)
49 {
50 GRAPH(GetGraph())
51 {
52 PARAMETER(0, 0).s64();
53 PARAMETER(1, 1).s64();
54 BASIC_BLOCK(2, 3, 6)
55 {
56 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LE).Inputs(0, 1);
57 }
58 BASIC_BLOCK(3, 4, 5)
59 {
60 INST(3, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_EQ).Inputs(0, 1);
61 }
62 BASIC_BLOCK(4, 5)
63 {
64 INST(4, Opcode::Add).s64().Inputs(0, 1);
65 }
66 BASIC_BLOCK(5, 6)
67 {
68 INST(5, Opcode::Phi).s64().Inputs({{3, 1}, {4, 4}});
69 }
70 BASIC_BLOCK(6, -1)
71 {
72 INST(6, Opcode::Phi).s64().Inputs({{2, 0}, {5, 5}});
73 INST(7, Opcode::Return).s64().Inputs(6);
74 }
75 }
76
77 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
78
79 auto graph = CreateEmptyGraph();
80 GRAPH(graph)
81 {
82 PARAMETER(0, 0).s64();
83 PARAMETER(1, 1).s64();
84 BASIC_BLOCK(2, 3, 6)
85 {
86 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LE).Inputs(0, 1);
87 }
88 BASIC_BLOCK(3, 4, 6)
89 {
90 INST(3, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_EQ).Inputs(0, 1);
91 }
92 BASIC_BLOCK(4, 6)
93 {
94 INST(4, Opcode::Add).s64().Inputs(0, 1);
95 }
96 BASIC_BLOCK(6, -1)
97 {
98 INST(5, Opcode::Phi).s64().Inputs({{2, 0}, {3, 1}, {4, 4}});
99 INST(6, Opcode::Return).s64().Inputs(5);
100 }
101 }
102 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
103 }
104
TEST_F(CleanupTest,HasPhi)105 TEST_F(CleanupTest, HasPhi)
106 {
107 GRAPH(GetGraph())
108 {
109 PARAMETER(0, 0).s64();
110 PARAMETER(1, 1).s64();
111 BASIC_BLOCK(2, 3, 4)
112 {
113 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0, 1);
114 }
115 BASIC_BLOCK(3, 4)
116 {
117 INST(3, Opcode::Add).s64().Inputs(0, 1);
118 }
119 BASIC_BLOCK(4, 5)
120 {
121 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 3}});
122 }
123 BASIC_BLOCK(5, -1)
124 {
125 INST(6, Opcode::Return).s64().Inputs(4);
126 }
127 }
128
129 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
130
131 auto graph = CreateEmptyGraph();
132 GRAPH(graph)
133 {
134 PARAMETER(0, 0).s64();
135 PARAMETER(1, 1).s64();
136 BASIC_BLOCK(2, 3, 5)
137 {
138 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0, 1);
139 }
140 BASIC_BLOCK(3, 5)
141 {
142 INST(3, Opcode::Add).s64().Inputs(0, 1);
143 }
144 BASIC_BLOCK(5, -1)
145 {
146 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 3}});
147 INST(6, Opcode::Return).s64().Inputs(4);
148 }
149 }
150 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
151 }
152
TEST_F(CleanupTest,DeadPhi)153 TEST_F(CleanupTest, DeadPhi)
154 {
155 GRAPH(GetGraph())
156 {
157 PARAMETER(0, 0).s64();
158 PARAMETER(1, 1).s64();
159 BASIC_BLOCK(2, 3, 6)
160 {
161 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_NE).Inputs(0, 1);
162 }
163 BASIC_BLOCK(3, 4, 5)
164 {
165 INST(3, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0, 1);
166 }
167 BASIC_BLOCK(4, 5) {}
168 BASIC_BLOCK(5, 6)
169 {
170 INST(4, Opcode::Phi).s64().Inputs({{3, 0}, {4, 1}});
171 }
172 BASIC_BLOCK(6, -1)
173 {
174 INST(5, Opcode::ReturnVoid);
175 }
176 }
177
178 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
179
180 auto graph = CreateEmptyGraph();
181 GRAPH(graph)
182 {
183 BASIC_BLOCK(2, -1)
184 {
185 INST(2, Opcode::ReturnVoid);
186 }
187 }
188 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
189 }
190
TEST_F(CleanupTest,LoopPreHeader)191 TEST_F(CleanupTest, LoopPreHeader)
192 {
193 GRAPH(GetGraph())
194 {
195 PARAMETER(0, 0).s64();
196 PARAMETER(1, 1).s64();
197 BASIC_BLOCK(2, 3) {}
198 BASIC_BLOCK(3, 3, -1)
199 {
200 INST(3, Opcode::Neg).s64().Inputs(0);
201 INST(5, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 3);
202 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
203 }
204 }
205
206 ASSERT_EQ(&BB(2), BB(3).GetLoop()->GetPreHeader());
207 ASSERT_EQ(1U, BB(3).GetLoop()->GetBlocks().size());
208 ASSERT_EQ(3U, BB(3).GetLoop()->GetOuterLoop()->GetBlocks().size());
209
210 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
211
212 auto graph = CreateEmptyGraph();
213 GRAPH(graph)
214 {
215 PARAMETER(0, 0).s64();
216 PARAMETER(1, 1).s64();
217 BASIC_BLOCK(2, 3) {}
218 BASIC_BLOCK(3, 3, -1)
219 {
220 INST(3, Opcode::Neg).s64().Inputs(0);
221 INST(5, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 3);
222 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
223 }
224 }
225 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
226 }
227
TEST_F(CleanupTest,TwoPredecessors)228 TEST_F(CleanupTest, TwoPredecessors)
229 {
230 GRAPH(GetGraph())
231 {
232 PARAMETER(0, 0).s64();
233 PARAMETER(1, 1).s64();
234 BASIC_BLOCK(2, 3, 4)
235 {
236 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
237 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
238 }
239 BASIC_BLOCK(3, 5)
240 {
241 INST(20, Opcode::SaveState).NoVregs();
242 INST(4, Opcode::CallStatic).v0id().InputsAutoType(20);
243 }
244 BASIC_BLOCK(4, 5)
245 {
246 INST(21, Opcode::SaveState).NoVregs();
247 INST(5, Opcode::CallStatic).v0id().InputsAutoType(21);
248 }
249 BASIC_BLOCK(5, 6) {}
250 BASIC_BLOCK(6, -1)
251 {
252 INST(6, Opcode::ReturnVoid);
253 }
254 }
255
256 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
257
258 auto graph = CreateEmptyGraph();
259 GRAPH(graph)
260 {
261 PARAMETER(0, 0).s64();
262 PARAMETER(1, 1).s64();
263 BASIC_BLOCK(2, 3, 4)
264 {
265 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
266 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
267 }
268 BASIC_BLOCK(3, 6)
269 {
270 INST(20, Opcode::SaveState).NoVregs();
271 INST(4, Opcode::CallStatic).v0id().InputsAutoType(20);
272 }
273 BASIC_BLOCK(4, 6)
274 {
275 INST(21, Opcode::SaveState).NoVregs();
276 INST(5, Opcode::CallStatic).v0id().InputsAutoType(21);
277 }
278 BASIC_BLOCK(6, -1)
279 {
280 INST(6, Opcode::ReturnVoid);
281 }
282 }
283 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
284 }
285
TEST_F(CleanupTest,TwoPredecessorsPhi)286 TEST_F(CleanupTest, TwoPredecessorsPhi)
287 {
288 GRAPH(GetGraph())
289 {
290 PARAMETER(0, 0).s64();
291 PARAMETER(1, 1).s64();
292 BASIC_BLOCK(2, 3, 7)
293 {
294 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
295 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
296 }
297 BASIC_BLOCK(3, 4, 5)
298 {
299 INST(4, Opcode::Add).s64().Inputs(0, 1);
300 INST(5, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
301 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
302 }
303 BASIC_BLOCK(4, 6)
304 {
305 INST(20, Opcode::SaveState).NoVregs();
306 INST(7, Opcode::CallStatic).v0id().InputsAutoType(20);
307 }
308 BASIC_BLOCK(5, 6)
309 {
310 INST(21, Opcode::SaveState).NoVregs();
311 INST(8, Opcode::CallStatic).v0id().InputsAutoType(21);
312 }
313 BASIC_BLOCK(6, 7) {}
314 BASIC_BLOCK(7, -1)
315 {
316 INST(9, Opcode::Phi).s64().Inputs({{2, 1}, {6, 4}});
317 INST(10, Opcode::Return).s64().Inputs(9);
318 }
319 }
320
321 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
322
323 auto graph = CreateEmptyGraph();
324 GRAPH(graph)
325 {
326 PARAMETER(0, 0).s64();
327 PARAMETER(1, 1).s64();
328 BASIC_BLOCK(2, 3, 7)
329 {
330 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
331 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
332 }
333 BASIC_BLOCK(3, 4, 5)
334 {
335 INST(4, Opcode::Add).s64().Inputs(0, 1);
336 INST(5, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
337 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
338 }
339 BASIC_BLOCK(4, 7)
340 {
341 INST(20, Opcode::SaveState).NoVregs();
342 INST(7, Opcode::CallStatic).v0id().InputsAutoType(20);
343 }
344 BASIC_BLOCK(5, 7)
345 {
346 INST(21, Opcode::SaveState).NoVregs();
347 INST(8, Opcode::CallStatic).v0id().InputsAutoType(21);
348 }
349 BASIC_BLOCK(7, -1)
350 {
351 INST(9, Opcode::Phi).s64().Inputs({{2, 1}, {4, 4}, {5, 4}});
352 INST(10, Opcode::Return).s64().Inputs(9);
353 }
354 }
355 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
356 }
357
TEST_F(CleanupTest,TriangleNoPhi)358 TEST_F(CleanupTest, TriangleNoPhi)
359 {
360 GRAPH(GetGraph())
361 {
362 PARAMETER(0, 0).s64();
363 PARAMETER(1, 1).s64();
364 BASIC_BLOCK(2, 3, 4)
365 {
366 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
367 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
368 }
369 BASIC_BLOCK(3, 4) {}
370 BASIC_BLOCK(4, -1)
371 {
372 INST(4, Opcode::ReturnVoid);
373 }
374 }
375
376 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
377
378 auto graph = CreateEmptyGraph();
379 GRAPH(graph)
380 {
381 BASIC_BLOCK(4, -1)
382 {
383 INST(4, Opcode::ReturnVoid);
384 }
385 }
386 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
387 }
388
TEST_F(CleanupTest,DiamondSamePhi)389 TEST_F(CleanupTest, DiamondSamePhi)
390 {
391 GRAPH(GetGraph())
392 {
393 PARAMETER(0, 0).s64();
394 PARAMETER(1, 1).s64();
395 BASIC_BLOCK(2, 3, 4)
396 {
397 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
398 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
399 }
400 BASIC_BLOCK(3, 5) {}
401 BASIC_BLOCK(4, 5) {}
402 BASIC_BLOCK(5, -1)
403 {
404 INST(4, Opcode::Phi).s64().Inputs({{3, 1}, {4, 1}});
405 INST(5, Opcode::Return).s64().Inputs(4);
406 }
407 }
408
409 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
410
411 auto graph = CreateEmptyGraph();
412 GRAPH(graph)
413 {
414 PARAMETER(1, 1).s64();
415 BASIC_BLOCK(5, -1)
416 {
417 INST(5, Opcode::Return).s64().Inputs(1);
418 }
419 }
420 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
421 }
422
TEST_F(CleanupTest,JointTriangle)423 TEST_F(CleanupTest, JointTriangle)
424 {
425 GRAPH(GetGraph())
426 {
427 PARAMETER(0, 0).s64();
428 PARAMETER(1, 1).s64();
429 BASIC_BLOCK(2, 3, 5)
430 {
431 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
432 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
433 }
434 BASIC_BLOCK(3, 4, 5)
435 {
436 INST(4, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
437 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4);
438 }
439 BASIC_BLOCK(4, 5) {}
440 BASIC_BLOCK(5, -1)
441 {
442 INST(6, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}, {4, 0}});
443 INST(7, Opcode::Return).s64().Inputs(6);
444 }
445 }
446
447 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
448
449 auto graph = CreateEmptyGraph();
450 GRAPH(graph)
451 {
452 PARAMETER(0, 0).s64();
453 PARAMETER(1, 1).s64();
454 BASIC_BLOCK(2, 3, 5)
455 {
456 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0);
457 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
458 }
459 BASIC_BLOCK(3, 5) {}
460 BASIC_BLOCK(5, -1)
461 {
462 INST(6, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}});
463 INST(7, Opcode::Return).s64().Inputs(6);
464 }
465 }
466 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
467 }
468
TEST_F(CleanupTest,TriangleProhibited)469 TEST_F(CleanupTest, TriangleProhibited)
470 {
471 GRAPH(GetGraph())
472 {
473 PARAMETER(0, 0).s64();
474 PARAMETER(1, 1).s64();
475 BASIC_BLOCK(2, 3, 4)
476 {
477 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
478 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
479 }
480 BASIC_BLOCK(3, 4) {}
481 BASIC_BLOCK(4, -1)
482 {
483 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}});
484 INST(5, Opcode::Return).s64().Inputs(4);
485 }
486 }
487
488 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
489
490 auto graph = CreateEmptyGraph();
491 GRAPH(graph)
492 {
493 PARAMETER(0, 0).s64();
494 PARAMETER(1, 1).s64();
495 BASIC_BLOCK(2, 3, 4)
496 {
497 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
498 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
499 }
500 BASIC_BLOCK(3, 4) {}
501 BASIC_BLOCK(4, -1)
502 {
503 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}});
504 INST(5, Opcode::Return).s64().Inputs(4);
505 }
506 }
507 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
508 }
509
TEST_F(CleanupTest,InfiniteLoop)510 TEST_F(CleanupTest, InfiniteLoop)
511 {
512 GRAPH(GetGraph())
513 {
514 PARAMETER(0, 0).s64();
515 PARAMETER(1, 1).s64();
516 BASIC_BLOCK(2, 3, 4)
517 {
518 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
519 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
520 }
521 BASIC_BLOCK(3, 3) {}
522 BASIC_BLOCK(4, -1)
523 {
524 INST(4, Opcode::ReturnVoid);
525 }
526 }
527
528 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
529
530 auto graph = CreateEmptyGraph();
531 GRAPH(graph)
532 {
533 PARAMETER(0, 0).s64();
534 PARAMETER(1, 1).s64();
535 BASIC_BLOCK(2, 3, 4)
536 {
537 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
538 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
539 }
540 BASIC_BLOCK(3, 3) {}
541 BASIC_BLOCK(4, -1)
542 {
543 INST(4, Opcode::ReturnVoid);
544 }
545 }
546 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
547 }
548
TEST_F(CleanupTest,JointDiamond)549 TEST_F(CleanupTest, JointDiamond)
550 {
551 GRAPH(GetGraph())
552 {
553 PARAMETER(0, 0).u64();
554 PARAMETER(1, 1).u64();
555 BASIC_BLOCK(2, 3, 6)
556 {
557 INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1);
558 }
559 BASIC_BLOCK(3, 4, 5)
560 {
561 INST(3, Opcode::Mul).u64().Inputs(0, 0);
562 INST(4, Opcode::Mul).u64().Inputs(1, 1);
563 INST(5, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(4, 1);
564 }
565 BASIC_BLOCK(4, 7) {}
566 BASIC_BLOCK(5, 7) {}
567 BASIC_BLOCK(6, 7)
568 {
569 INST(20, Opcode::SaveState).NoVregs();
570 INST(6, Opcode::CallStatic).v0id().InputsAutoType(20);
571 }
572 BASIC_BLOCK(7, -1)
573 {
574 INST(7, Opcode::Phi).u64().Inputs({{6, 0}, {4, 3}, {5, 3}});
575 INST(8, Opcode::Return).u64().Inputs(7);
576 }
577 }
578
579 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
580
581 auto graph = CreateEmptyGraph();
582 GRAPH(graph)
583 {
584 PARAMETER(0, 0).u64();
585 PARAMETER(1, 1).u64();
586 BASIC_BLOCK(2, 3, 6)
587 {
588 INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1);
589 }
590 BASIC_BLOCK(3, 7)
591 {
592 INST(3, Opcode::Mul).u64().Inputs(0, 0);
593 }
594 BASIC_BLOCK(6, 7)
595 {
596 INST(20, Opcode::SaveState).NoVregs();
597 INST(6, Opcode::CallStatic).v0id().InputsAutoType(20);
598 }
599 BASIC_BLOCK(7, -1)
600 {
601 INST(7, Opcode::Phi).u64().Inputs({{6, 0}, {3, 3}});
602 INST(8, Opcode::Return).u64().Inputs(7);
603 }
604 }
605 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
606 }
607
TEST_F(CleanupTest,JoinLoopBackEdgeWithMultiPreds)608 TEST_F(CleanupTest, JoinLoopBackEdgeWithMultiPreds)
609 {
610 GRAPH(GetGraph())
611 {
612 PARAMETER(0, 0).u64();
613 PARAMETER(1, 1).u64();
614 PARAMETER(2, 2).u64();
615 BASIC_BLOCK(2, 3, 7)
616 {
617 INST(4, Opcode::Phi).u64().Inputs(0, 9);
618 INST(5, Opcode::If).SrcType(DataType::UINT64).CC(CC_LE).Inputs(4, 1);
619 }
620 BASIC_BLOCK(3, 4, 5)
621 {
622 INST(6, Opcode::If).SrcType(DataType::UINT64).CC(CC_LE).Inputs(4, 2);
623 }
624 BASIC_BLOCK(4, 6)
625 {
626 INST(7, Opcode::Mul).u64().Inputs(4, 1);
627 }
628 BASIC_BLOCK(5, 6)
629 {
630 INST(8, Opcode::Mul).u64().Inputs(4, 2);
631 }
632 BASIC_BLOCK(6, 2)
633 {
634 INST(9, Opcode::Phi).u64().Inputs(7, 8);
635 // loop back-edge
636 }
637 BASIC_BLOCK(7, -1)
638 {
639 INST(11, Opcode::Return).u64().Inputs(4);
640 }
641 }
642
643 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
644 ASSERT_TRUE(GetGraph()->GetAnalysis<LoopAnalyzer>().IsValid());
645
646 auto loop = BB(2).GetLoop();
647 ASSERT_EQ(loop->GetHeader(), &BB(2));
648 ASSERT_EQ(loop->GetBackEdges().size(), 2);
649 ASSERT_TRUE(loop->HasBackEdge(&BB(4)));
650 ASSERT_TRUE(loop->HasBackEdge(&BB(5)));
651 }
652
TEST_F(CleanupTest,DiamondBecomeEmpty)653 TEST_F(CleanupTest, DiamondBecomeEmpty)
654 {
655 GRAPH(GetGraph())
656 {
657 PARAMETER(0, 0).b();
658 BASIC_BLOCK(2, 3, 4)
659 {
660 INST(1, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(0);
661 }
662 BASIC_BLOCK(3, 5) {}
663 BASIC_BLOCK(4, 5) {}
664 BASIC_BLOCK(5, -1)
665 {
666 INST(2, Opcode::ReturnVoid);
667 }
668 }
669
670 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
671
672 auto graph = CreateEmptyGraph();
673 GRAPH(graph)
674 {
675 BASIC_BLOCK(5, -1)
676 {
677 INST(2, Opcode::ReturnVoid);
678 }
679 }
680 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
681 }
682
TEST_F(CleanupTest,CarefulDCE)683 TEST_F(CleanupTest, CarefulDCE)
684 {
685 GRAPH(GetGraph())
686 {
687 BASIC_BLOCK(2, 3, 4)
688 {
689 INST(20, Opcode::SaveState).NoVregs();
690 INST(0, Opcode::CallStatic).b().InputsAutoType(20);
691 INST(1, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(0);
692 }
693 BASIC_BLOCK(3, 4) {}
694 BASIC_BLOCK(4, -1)
695 {
696 INST(2, Opcode::ReturnVoid);
697 }
698 }
699
700 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
701
702 auto graph = CreateEmptyGraph();
703 GRAPH(graph)
704 {
705 BASIC_BLOCK(2, -1)
706 {
707 INST(20, Opcode::SaveState).NoVregs();
708 INST(0, Opcode::CallStatic).b().InputsAutoType(20);
709 INST(1, Opcode::ReturnVoid);
710 }
711 }
712 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
713 }
714
TEST_F(CleanupTest,CarefulDCE2)715 TEST_F(CleanupTest, CarefulDCE2)
716 {
717 GRAPH(GetGraph())
718 {
719 PARAMETER(0, 0).u64();
720 PARAMETER(1, 1).u64();
721 BASIC_BLOCK(2, 3, 40)
722 {
723 INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(0, 1);
724 }
725 BASIC_BLOCK(40, 5) {}
726 BASIC_BLOCK(3, 5) {}
727 BASIC_BLOCK(5, 6, 7)
728 {
729 INST(3, Opcode::Phi).u64().Inputs({{40, 0}, {3, 1}});
730 INST(4, Opcode::IfImm).SrcType(DataType::UINT64).CC(CC_NE).Imm(0).Inputs(3);
731 }
732 BASIC_BLOCK(6, 7) {}
733 BASIC_BLOCK(7, -1)
734 {
735 INST(5, Opcode::ReturnVoid);
736 }
737 }
738
739 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
740
741 auto graph = CreateEmptyGraph();
742 GRAPH(graph)
743 {
744 BASIC_BLOCK(2, -1)
745 {
746 INST(0, Opcode::ReturnVoid);
747 }
748 }
749 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
750 }
751
TEST_F(CleanupTest,Delete)752 TEST_F(CleanupTest, Delete)
753 {
754 GRAPH(GetGraph())
755 {
756 CONSTANT(0, 12);
757 CONSTANT(1, 13);
758
759 BASIC_BLOCK(2, -1)
760 {
761 INST(2, Opcode::Neg).u64().Inputs(1);
762 INST(3, Opcode::Add).u64().Inputs(0, 2);
763 INST(4, Opcode::Return).u64().Inputs(2);
764 }
765 }
766
767 // Delete Insts 0 and 3
768 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
769
770 ASSERT_TRUE(CheckInputs(INS(2), {1}));
771 ASSERT_TRUE(CheckInputs(INS(4), {2}));
772
773 ASSERT_TRUE(CheckUsers(INS(1), {2}));
774 ASSERT_TRUE(CheckUsers(INS(2), {4}));
775 ASSERT_TRUE(CheckUsers(INS(4), {}));
776 }
777
TEST_F(CleanupTest,NotRemoved)778 TEST_F(CleanupTest, NotRemoved)
779 {
780 GRAPH(GetGraph())
781 {
782 CONSTANT(0, 11);
783 CONSTANT(1, 12);
784 CONSTANT(2, 13);
785
786 BASIC_BLOCK(2, -1)
787 {
788 INST(3, Opcode::Add).u64().Inputs(0, 1);
789 INST(4, Opcode::Neg).u64().Inputs(3);
790 INST(5, Opcode::Sub).u64().Inputs(4, 2);
791 INST(6, Opcode::Return).u64().Inputs(5);
792 }
793 }
794
795 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
796
797 ASSERT_TRUE(CheckInputs(INS(3), {0, 1}));
798 ASSERT_TRUE(CheckInputs(INS(4), {3}));
799 ASSERT_TRUE(CheckInputs(INS(5), {4, 2}));
800 ASSERT_TRUE(CheckInputs(INS(6), {5}));
801
802 ASSERT_TRUE(CheckUsers(INS(0), {3}));
803 ASSERT_TRUE(CheckUsers(INS(1), {3}));
804 ASSERT_TRUE(CheckUsers(INS(2), {5}));
805 ASSERT_TRUE(CheckUsers(INS(3), {4}));
806 ASSERT_TRUE(CheckUsers(INS(4), {5}));
807 ASSERT_TRUE(CheckUsers(INS(5), {6}));
808 }
809
TEST_F(CleanupTest,Loop)810 TEST_F(CleanupTest, Loop)
811 {
812 GRAPH(GetGraph())
813 {
814 CONSTANT(0, 0);
815 CONSTANT(1, 1);
816 BASIC_BLOCK(2, 3)
817 {
818 INST(2, Opcode::Phi).u64().Inputs(0, 5);
819 INST(3, Opcode::Phi).u64().Inputs(1, 6);
820 }
821 BASIC_BLOCK(3, 4, 5)
822 {
823 INST(4, Opcode::Add).u64().Inputs(2, 3);
824 INST(11, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1);
825 INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11);
826 }
827 BASIC_BLOCK(4, 2)
828 {
829 INST(5, Opcode::Neg).u64().Inputs(3);
830 INST(6, Opcode::Neg).u64().Inputs(4);
831 // Must be removed
832 INST(7, Opcode::Add).u64().Inputs(5, 6);
833 }
834 BASIC_BLOCK(5, -1)
835 {
836 // Unused instruction
837 INST(8, Opcode::Neg).u64().Inputs(4);
838 INST(9, Opcode::Return).u64().Inputs(4);
839 }
840 }
841
842 // Delete Insts 7 and 8
843 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
844
845 ASSERT_TRUE(CheckInputs(INS(2), {0, 5}));
846 ASSERT_TRUE(CheckInputs(INS(3), {1, 6}));
847 ASSERT_TRUE(CheckInputs(INS(4), {2, 3}));
848 ASSERT_TRUE(CheckInputs(INS(5), {3}));
849 ASSERT_TRUE(CheckInputs(INS(6), {4}));
850 ASSERT_TRUE(CheckInputs(INS(9), {4}));
851
852 ASSERT_TRUE(CheckUsers(INS(0), {2, 11}));
853 ASSERT_TRUE(CheckUsers(INS(1), {3, 11}));
854 ASSERT_TRUE(CheckUsers(INS(2), {4}));
855 ASSERT_TRUE(CheckUsers(INS(3), {4, 5}));
856 ASSERT_TRUE(CheckUsers(INS(4), {6, 9}));
857 ASSERT_TRUE(CheckUsers(INS(5), {2}));
858 ASSERT_TRUE(CheckUsers(INS(6), {3}));
859 }
860
TEST_F(CleanupTest,Loop1)861 TEST_F(CleanupTest, Loop1)
862 {
863 GRAPH(GetGraph())
864 {
865 CONSTANT(0, 0);
866 CONSTANT(1, 1);
867
868 BASIC_BLOCK(2, 2, 3)
869 {
870 // Unused instructions
871 INST(2, Opcode::Phi).u64().Inputs(1, 3);
872 INST(3, Opcode::Add).u64().Inputs(2, 1);
873 INST(6, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 0);
874 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6);
875 }
876 BASIC_BLOCK(3, -1)
877 {
878 // Unused instruction
879 INST(4, Opcode::Neg).u64().Inputs(0);
880 INST(5, Opcode::Return).u64().Inputs(4);
881 }
882 }
883
884 // Delete Insts 1, 2 and 3
885 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
886
887 ASSERT_EQ(INS(0).GetNext(), nullptr);
888 ASSERT_FALSE(BB(2).IsEmpty());
889 }
890
891 /*
892 * Test Graph:
893 * [0]
894 * |
895 * v
896 * /-------[2]-------\
897 * | |
898 * v v
899 * [3] [4]
900 * / \ / \
901 * v \ / |
902 * [8]<---->[7] \->[5]<-/ |
903 * | | |
904 * | \--->[6]<---/
905 * | |
906 * \---------->[9]<----/
907 * |
908 * v
909 * [1]
910 */
911
TEST_F(CleanupTest,PhiInputs1)912 TEST_F(CleanupTest, PhiInputs1)
913 {
914 GRAPH(GetGraph())
915 {
916 CONSTANT(0, 0);
917 CONSTANT(18, 2);
918 CONSTANT(1, 1);
919 BASIC_BLOCK(2, 3, 4)
920 {
921 INST(2, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1);
922 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
923 }
924 BASIC_BLOCK(3, 7, 5)
925 {
926 INST(4, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1);
927 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4);
928 }
929 BASIC_BLOCK(4, 5, 6)
930 {
931 INST(6, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1);
932 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6);
933 }
934
935 BASIC_BLOCK(5, 6)
936 {
937 INST(8, Opcode::Phi).u64().Inputs({{4, 0}, {3, 0}});
938 }
939 BASIC_BLOCK(6, 9)
940 {
941 INST(10, Opcode::Phi).u64().Inputs({{4, 0}, {5, 8}});
942 }
943 BASIC_BLOCK(7, 8, 9)
944 {
945 INST(12, Opcode::Phi).u64().Inputs({{8, 12}, {3, 0}});
946 INST(13, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1);
947 INST(14, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(13);
948 }
949 BASIC_BLOCK(8, 7) {}
950 BASIC_BLOCK(9, -1)
951 {
952 INST(16, Opcode::Phi).u64().Inputs({{6, 10}, {7, 12}});
953 INST(17, Opcode::Return).u64().Inputs(16);
954 }
955 }
956
957 // Delete all phi instructions
958 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
959
960 ASSERT_TRUE(CheckInputs(INS(17), {0}));
961 ASSERT_TRUE(CheckUsers(INS(0), {17}));
962 }
963
964 /*
965 * Test Graph:
966 * [0]
967 * |
968 * v
969 * /---------[2]---------\
970 * | |
971 * v v
972 * [3] [4]
973 * | |
974 * \-------->[5]<--------/
975 * |
976 * |->[6]<----\
977 * | | |
978 * | v |
979 * \->[7]-----/
980 * |
981 * v
982 * [8]
983 * |
984 * v
985 * [1]
986 */
987
TEST_F(CleanupTest,PhiInputs2)988 TEST_F(CleanupTest, PhiInputs2)
989 {
990 GRAPH(GetGraph())
991 {
992 CONSTANT(0, 0);
993 CONSTANT(1, 1);
994 CONSTANT(6, 2);
995 CONSTANT(7, 3);
996 BASIC_BLOCK(2, 3, 4)
997 {
998 INST(8, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7);
999 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8);
1000 }
1001 BASIC_BLOCK(3, 5) {}
1002 BASIC_BLOCK(4, 5) {}
1003 BASIC_BLOCK(5, 6, 7)
1004 {
1005 INST(2, Opcode::Phi).u64().Inputs(0, 1);
1006 INST(12, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7);
1007 INST(13, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(12);
1008 }
1009 BASIC_BLOCK(6, 7)
1010 {
1011 INST(3, Opcode::Phi).u64().Inputs({{7, 4}, {5, 2}});
1012 }
1013 BASIC_BLOCK(7, 6, 8)
1014 {
1015 INST(4, Opcode::Phi).u64().Inputs({{6, 3}, {5, 2}});
1016 INST(15, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7);
1017 INST(16, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(15);
1018 }
1019 BASIC_BLOCK(8, -1)
1020 {
1021 INST(5, Opcode::Return).u64().Inputs(4);
1022 }
1023 }
1024
1025 // Delete 3 and 4 phi (replace with v2p in return)
1026 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1027
1028 ASSERT_TRUE(CheckInputs(INS(2), {0, 1}));
1029 ASSERT_TRUE(CheckInputs(INS(5), {2}));
1030
1031 ASSERT_TRUE(CheckUsers(INS(0), {2}));
1032 ASSERT_TRUE(CheckUsers(INS(1), {2}));
1033 ASSERT_TRUE(CheckUsers(INS(2), {5}));
1034
1035 auto graph = CreateEmptyGraph();
1036 GRAPH(graph)
1037 {
1038 CONSTANT(0, 0);
1039 CONSTANT(1, 1);
1040 CONSTANT(6, 2);
1041 CONSTANT(7, 3);
1042 BASIC_BLOCK(2, 5, 4)
1043 {
1044 INST(8, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7);
1045 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8);
1046 }
1047 BASIC_BLOCK(4, 5) {}
1048 BASIC_BLOCK(5, 7)
1049 {
1050 INST(2, Opcode::Phi).u64().Inputs(0, 1);
1051 }
1052 BASIC_BLOCK(7, 7, 8)
1053 {
1054 INST(15, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7);
1055 INST(16, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(15);
1056 }
1057 BASIC_BLOCK(8, -1)
1058 {
1059 INST(5, Opcode::Return).u64().Inputs(2);
1060 }
1061 }
1062 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1063 }
1064
TEST_F(CleanupTest,NullPtr)1065 TEST_F(CleanupTest, NullPtr)
1066 {
1067 GRAPH(GetGraph())
1068 {
1069 CONSTANT(0, 0);
1070 CONSTANT(1, nullptr);
1071
1072 BASIC_BLOCK(2, -1)
1073 {
1074 INST(2, Opcode::Return).u64().Inputs(0);
1075 }
1076 }
1077
1078 ASSERT_TRUE(GetGraph()->HasNullPtrInst());
1079 // Delete NullPtr
1080 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1081 ASSERT_FALSE(GetGraph()->HasNullPtrInst());
1082 }
1083
TEST_F(CleanupTest,JustReturnLeft)1084 TEST_F(CleanupTest, JustReturnLeft)
1085 {
1086 GRAPH(GetGraph())
1087 {
1088 PARAMETER(0, 0).u64();
1089 CONSTANT(1, 1);
1090 CONSTANT(2, 2);
1091 CONSTANT(3, 3);
1092 CONSTANT(4, 4);
1093 BASIC_BLOCK(2, 3, 4)
1094 {
1095 INST(5, Opcode::Add).u64().Inputs(1, 4);
1096 INST(6, Opcode::Add).u64().Inputs(2, 3);
1097 INST(7, Opcode::Compare).b().Inputs(0, 3);
1098 INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7);
1099 }
1100 BASIC_BLOCK(3, 4) {}
1101 BASIC_BLOCK(4, -1)
1102 {
1103 INST(9, Opcode::Phi).u64().Inputs({{2, 6}, {3, 5}});
1104 INST(10, Opcode::Return).u64().Inputs(0);
1105 }
1106 }
1107
1108 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1109
1110 auto graph = CreateEmptyGraph();
1111 GRAPH(graph)
1112 {
1113 PARAMETER(0, 0).u64();
1114 BASIC_BLOCK(2, -1)
1115 {
1116 INST(10, Opcode::Return).u64().Inputs(0);
1117 }
1118 }
1119 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1120 }
1121
TEST_F(CleanupTest,RemovingPhiFromTheSameBlock)1122 TEST_F(CleanupTest, RemovingPhiFromTheSameBlock)
1123 {
1124 auto graph = CreateEmptyGraph();
1125 GRAPH(graph)
1126 {
1127 PARAMETER(0, 0).u64();
1128 PARAMETER(1, 1).u64();
1129 CONSTANT(2, 1);
1130 BASIC_BLOCK(2, 2, 3)
1131 {
1132 INST(5, Opcode::Phi).u64().Inputs(1, 6);
1133 INST(6, Opcode::Phi).u64().Inputs(0, 6);
1134 INST(7, Opcode::Phi).u64().Inputs(0, 8);
1135 INST(8, Opcode::Add).u64().Inputs(7, 2);
1136 INST(9, Opcode::Compare).b().CC(CC_NE).Inputs(8, 1);
1137 INST(10, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(9);
1138 }
1139 BASIC_BLOCK(3, -1)
1140 {
1141 INST(11, Opcode::Add).u64().Inputs(5, 6);
1142 INST(12, Opcode::Return).u64().Inputs(11);
1143 }
1144 }
1145 ASSERT_TRUE(graph->RunPass<Cleanup>());
1146 }
1147
TEST_F(CleanupTest,CallDiscardReturnValue)1148 TEST_F(CleanupTest, CallDiscardReturnValue)
1149 {
1150 GRAPH(GetGraph())
1151 {
1152 BASIC_BLOCK(2, -1)
1153 {
1154 INST(20, Opcode::SaveState).NoVregs();
1155 INST(0, Opcode::CallStatic).s32().InputsAutoType(20);
1156 INST(1, Opcode::ReturnVoid).v0id();
1157 }
1158 }
1159 ASSERT_FALSE(INS(0).HasUsers());
1160 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
1161 ASSERT_TRUE(INS(0).GetOpcode() == Opcode::CallStatic);
1162 }
1163
TEST_F(CleanupTest,CallReturnVoid)1164 TEST_F(CleanupTest, CallReturnVoid)
1165 {
1166 GRAPH(GetGraph())
1167 {
1168 BASIC_BLOCK(2, -1)
1169 {
1170 INST(20, Opcode::SaveState).NoVregs();
1171 INST(0, Opcode::CallStatic).v0id().InputsAutoType(20);
1172 INST(1, Opcode::ReturnVoid).v0id();
1173 }
1174 }
1175 ASSERT_FALSE(INS(0).HasUsers());
1176 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
1177 ASSERT_TRUE(INS(0).GetOpcode() == Opcode::CallStatic);
1178 }
1179
TEST_F(CleanupTest,StoreObject)1180 TEST_F(CleanupTest, StoreObject)
1181 {
1182 GRAPH(GetGraph())
1183 {
1184 PARAMETER(0, 0).ref();
1185 PARAMETER(1, 1).s32();
1186
1187 BASIC_BLOCK(2, -1)
1188 {
1189 INST(2, Opcode::SaveState).Inputs(0, 1, 1).SrcVregs({0, 1, 2});
1190 INST(3, Opcode::NullCheck).ref().Inputs(0, 2);
1191 INST(4, Opcode::StoreObject).s32().Inputs(3, 1);
1192 INST(5, Opcode::ReturnVoid).v0id();
1193 }
1194 }
1195 ASSERT_FALSE(INS(4).HasUsers());
1196 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
1197 ASSERT_TRUE(INS(4).GetOpcode() == Opcode::StoreObject);
1198 }
1199
TEST_F(CleanupTest,OneBlock)1200 TEST_F(CleanupTest, OneBlock)
1201 {
1202 GRAPH(GetGraph())
1203 {
1204 BASIC_BLOCK(2, -1)
1205 {
1206 INST(0, Opcode::ReturnVoid);
1207 }
1208 }
1209
1210 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>());
1211
1212 auto graph = CreateEmptyGraph();
1213 GRAPH(graph)
1214 {
1215 BASIC_BLOCK(2, -1)
1216 {
1217 INST(0, Opcode::ReturnVoid);
1218 }
1219 }
1220 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1221 }
1222
TEST_F(CleanupTest,TwoBlocks)1223 TEST_F(CleanupTest, TwoBlocks)
1224 {
1225 GRAPH(GetGraph())
1226 {
1227 CONSTANT(0, 12);
1228 CONSTANT(1, 13);
1229
1230 BASIC_BLOCK(2, 3)
1231 {
1232 INST(2, Opcode::Neg).u64().Inputs(1);
1233 INST(3, Opcode::Add).u64().Inputs(0, 2);
1234 }
1235
1236 BASIC_BLOCK(3, -1)
1237 {
1238 INST(4, Opcode::Add).u64().Inputs(2, 3);
1239 INST(5, Opcode::Return).u64().Inputs(4);
1240 }
1241 }
1242
1243 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1244
1245 auto graph = CreateEmptyGraph();
1246 GRAPH(graph)
1247 {
1248 CONSTANT(0, 12);
1249 CONSTANT(1, 13);
1250
1251 BASIC_BLOCK(2, -1)
1252 {
1253 INST(2, Opcode::Neg).u64().Inputs(1);
1254 INST(3, Opcode::Add).u64().Inputs(0, 2);
1255 INST(4, Opcode::Add).u64().Inputs(2, 3);
1256 INST(5, Opcode::Return).u64().Inputs(4);
1257 }
1258 }
1259 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1260 }
1261
TEST_F(CleanupTest,SameBlockPhiTwice)1262 TEST_F(CleanupTest, SameBlockPhiTwice)
1263 {
1264 GRAPH(GetGraph())
1265 {
1266 CONSTANT(0, 12).s64();
1267 CONSTANT(1, 13).s64();
1268
1269 BASIC_BLOCK(2, 3, 4)
1270 {
1271 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1);
1272 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
1273 }
1274
1275 BASIC_BLOCK(3, 5)
1276 {
1277 INST(4, Opcode::Neg).u64().Inputs(0);
1278 INST(5, Opcode::Neg).u64().Inputs(1);
1279 }
1280
1281 BASIC_BLOCK(4, 5)
1282 {
1283 INST(7, Opcode::Neg).u64().Inputs(1);
1284 INST(8, Opcode::Neg).u64().Inputs(0);
1285 }
1286
1287 BASIC_BLOCK(5, 6)
1288 {
1289 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}, {6, 15}});
1290 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}, {6, 16}});
1291 INST(12, Opcode::Neg).u64().Inputs(10);
1292 INST(13, Opcode::Add).u64().Inputs(10, 11);
1293 }
1294
1295 BASIC_BLOCK(6, 5, -1)
1296 {
1297 INST(15, Opcode::Add).u64().Inputs(0, 1);
1298 INST(16, Opcode::Neg).u64().Inputs(0);
1299 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
1300 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17);
1301 }
1302 }
1303
1304 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1305
1306 auto graph = CreateEmptyGraph();
1307 GRAPH(graph)
1308 {
1309 CONSTANT(0, 12).s64();
1310 CONSTANT(1, 13).s64();
1311
1312 BASIC_BLOCK(7, 6) {}
1313
1314 BASIC_BLOCK(6, 6, -1)
1315 {
1316 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0);
1317 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17);
1318 }
1319 }
1320 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1321 }
1322
TEST_F(CleanupTest,TwoBlocksLoop)1323 TEST_F(CleanupTest, TwoBlocksLoop)
1324 {
1325 GRAPH(GetGraph())
1326 {
1327 CONSTANT(0, 12).s64();
1328 CONSTANT(1, 13).s64();
1329
1330 BASIC_BLOCK(2, 3, 4)
1331 {
1332 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1);
1333 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
1334 }
1335
1336 BASIC_BLOCK(3, 5)
1337 {
1338 INST(4, Opcode::Neg).u64().Inputs(0);
1339 INST(5, Opcode::Neg).u64().Inputs(1);
1340 }
1341
1342 BASIC_BLOCK(4, 5)
1343 {
1344 INST(7, Opcode::Neg).u64().Inputs(1);
1345 INST(8, Opcode::Neg).u64().Inputs(0);
1346 }
1347
1348 BASIC_BLOCK(5, 6)
1349 {
1350 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}, {6, 15}});
1351 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}, {6, 16}});
1352 INST(12, Opcode::Neg).u64().Inputs(10);
1353 INST(13, Opcode::Add).u64().Inputs(10, 11);
1354 }
1355
1356 BASIC_BLOCK(6, 5, -1)
1357 {
1358 INST(15, Opcode::Add).u64().Inputs(12, 13);
1359 INST(16, Opcode::Neg).u64().Inputs(12);
1360 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(15, 16);
1361 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17);
1362 }
1363 }
1364
1365 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1366
1367 auto graph = CreateEmptyGraph();
1368 GRAPH(graph)
1369 {
1370 CONSTANT(0, 12).s64();
1371 CONSTANT(1, 13).s64();
1372
1373 BASIC_BLOCK(2, 3, 4)
1374 {
1375 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1);
1376 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
1377 }
1378
1379 BASIC_BLOCK(3, 7)
1380 {
1381 INST(4, Opcode::Neg).u64().Inputs(0);
1382 INST(5, Opcode::Neg).u64().Inputs(1);
1383 }
1384
1385 BASIC_BLOCK(4, 7)
1386 {
1387 INST(7, Opcode::Neg).u64().Inputs(1);
1388 INST(8, Opcode::Neg).u64().Inputs(0);
1389 }
1390
1391 BASIC_BLOCK(7, 5)
1392 {
1393 INST(19, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}});
1394 INST(20, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}});
1395 }
1396
1397 BASIC_BLOCK(5, 5, -1)
1398 {
1399 INST(10, Opcode::Phi).u64().Inputs({{7, 19}, {5, 15}});
1400 INST(11, Opcode::Phi).u64().Inputs({{7, 20}, {5, 16}});
1401 INST(12, Opcode::Neg).u64().Inputs(10);
1402 INST(13, Opcode::Add).u64().Inputs(10, 11);
1403 INST(15, Opcode::Add).u64().Inputs(12, 13);
1404 INST(16, Opcode::Neg).u64().Inputs(12);
1405 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(15, 16);
1406 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17);
1407 }
1408 }
1409 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1410 }
1411
TEST_F(CleanupTest,TwoLoopsPreHeader)1412 TEST_F(CleanupTest, TwoLoopsPreHeader)
1413 {
1414 GRAPH(GetGraph())
1415 {
1416 CONSTANT(0, 12).s64();
1417 CONSTANT(1, 13).s64();
1418 PARAMETER(8, 0).b();
1419
1420 BASIC_BLOCK(2, 3)
1421 {
1422 INST(2, Opcode::Neg).u64().Inputs(0);
1423 }
1424
1425 BASIC_BLOCK(3, 4, 5)
1426 {
1427 INST(4, Opcode::Neg).u64().Inputs(0);
1428 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8);
1429 }
1430
1431 BASIC_BLOCK(4, 4, -1)
1432 {
1433 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 1);
1434 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6);
1435 }
1436
1437 BASIC_BLOCK(5, 5, -1)
1438 {
1439 INST(10, Opcode::Compare).b().CC(CC_GT).SrcType(DataType::Type::UINT64).Inputs(4, 2);
1440 INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
1441 }
1442 }
1443
1444 ASSERT_EQ(&BB(3), BB(4).GetLoop()->GetPreHeader());
1445 ASSERT_EQ(&BB(3), BB(5).GetLoop()->GetPreHeader());
1446 ASSERT_EQ(1U, BB(4).GetLoop()->GetBlocks().size());
1447 ASSERT_EQ(1U, BB(5).GetLoop()->GetBlocks().size());
1448 ASSERT_EQ(4U, BB(4).GetLoop()->GetOuterLoop()->GetBlocks().size());
1449 ASSERT_EQ(4U, BB(5).GetLoop()->GetOuterLoop()->GetBlocks().size());
1450
1451 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1452
1453 auto graph = CreateEmptyGraph();
1454 GRAPH(graph)
1455 {
1456 CONSTANT(0, 12).s64();
1457 CONSTANT(1, 13).s64();
1458 PARAMETER(8, 0).b();
1459
1460 BASIC_BLOCK(2, 4, 5)
1461 {
1462 INST(2, Opcode::Neg).u64().Inputs(0);
1463 INST(4, Opcode::Neg).u64().Inputs(0);
1464 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8);
1465 }
1466
1467 BASIC_BLOCK(4, 4, -1)
1468 {
1469 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 1);
1470 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6);
1471 }
1472
1473 BASIC_BLOCK(5, 5, -1)
1474 {
1475 INST(10, Opcode::Compare).b().CC(CC_GT).SrcType(DataType::Type::UINT64).Inputs(4, 2);
1476 INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10);
1477 }
1478 }
1479 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1480
1481 EXPECT_EQ(&BB(2), BB(4).GetLoop()->GetPreHeader());
1482 EXPECT_EQ(&BB(2), BB(5).GetLoop()->GetPreHeader());
1483 EXPECT_EQ(1U, BB(4).GetLoop()->GetBlocks().size());
1484 EXPECT_EQ(1U, BB(5).GetLoop()->GetBlocks().size());
1485 EXPECT_EQ(3U, BB(4).GetLoop()->GetOuterLoop()->GetBlocks().size());
1486 EXPECT_EQ(3U, BB(5).GetLoop()->GetOuterLoop()->GetBlocks().size());
1487 }
1488
TEST_F(CleanupTest,LoopBackEdge)1489 TEST_F(CleanupTest, LoopBackEdge)
1490 {
1491 GRAPH(GetGraph())
1492 {
1493 CONSTANT(0, 12).s64();
1494 CONSTANT(1, 13).s64();
1495
1496 BASIC_BLOCK(2, 3)
1497 {
1498 INST(2, Opcode::Neg).u64().Inputs(0);
1499 }
1500
1501 BASIC_BLOCK(3, 2, -1)
1502 {
1503 INST(4, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(1, 2);
1504 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4);
1505 }
1506 }
1507
1508 ASSERT_TRUE(BB(3).GetLoop()->HasBackEdge(&BB(3)));
1509 ASSERT_EQ(2U, BB(3).GetLoop()->GetBlocks().size());
1510
1511 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1512
1513 auto graph = CreateEmptyGraph();
1514 GRAPH(graph)
1515 {
1516 CONSTANT(0, 12).s64();
1517 CONSTANT(1, 13).s64();
1518
1519 BASIC_BLOCK(2, 2, -1)
1520 {
1521 INST(2, Opcode::Neg).u64().Inputs(0);
1522 INST(4, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(1, 2);
1523 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4);
1524 }
1525 }
1526 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1527
1528 EXPECT_TRUE(BB(2).GetLoop()->HasBackEdge(&BB(2)));
1529 EXPECT_EQ(1U, BB(2).GetLoop()->GetBlocks().size());
1530 }
1531
TEST_F(CleanupTest,LoopMiddleBlock)1532 TEST_F(CleanupTest, LoopMiddleBlock)
1533 {
1534 GRAPH(GetGraph())
1535 {
1536 CONSTANT(0, 12).s64();
1537 CONSTANT(1, 13).s64();
1538
1539 BASIC_BLOCK(2, 3)
1540 {
1541 INST(2, Opcode::Neg).u64().Inputs(0);
1542 }
1543
1544 BASIC_BLOCK(3, 4)
1545 {
1546 INST(4, Opcode::Neg).u64().Inputs(1);
1547 }
1548
1549 BASIC_BLOCK(4, 2, -1)
1550 {
1551 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 4);
1552 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6);
1553 }
1554 }
1555
1556 ASSERT_EQ(3U, BB(2).GetLoop()->GetBlocks().size());
1557 ASSERT_EQ(3U, BB(2).GetLoop()->GetOuterLoop()->GetBlocks().size());
1558
1559 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1560
1561 auto graph = CreateEmptyGraph();
1562 GRAPH(graph)
1563 {
1564 CONSTANT(0, 12).s64();
1565 CONSTANT(1, 13).s64();
1566
1567 BASIC_BLOCK(2, 2, -1)
1568 {
1569 INST(2, Opcode::Neg).u64().Inputs(0);
1570 INST(4, Opcode::Neg).u64().Inputs(1);
1571 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 4);
1572 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6);
1573 }
1574 }
1575 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1576
1577 EXPECT_EQ(1U, BB(2).GetLoop()->GetBlocks().size());
1578 EXPECT_EQ(3U, BB(2).GetLoop()->GetOuterLoop()->GetBlocks().size());
1579 }
1580
TEST_F(CleanupTest,ThreeBlocks)1581 TEST_F(CleanupTest, ThreeBlocks)
1582 {
1583 GRAPH(GetGraph())
1584 {
1585 CONSTANT(0, 12);
1586 CONSTANT(1, 13);
1587
1588 BASIC_BLOCK(2, 3)
1589 {
1590 INST(2, Opcode::Neg).u64().Inputs(1);
1591 INST(3, Opcode::Add).u64().Inputs(0, 2);
1592 }
1593
1594 BASIC_BLOCK(3, 4)
1595 {
1596 INST(4, Opcode::Neg).u64().Inputs(0);
1597 INST(5, Opcode::Add).u64().Inputs(1, 4);
1598 }
1599
1600 BASIC_BLOCK(4, -1)
1601 {
1602 INST(6, Opcode::Add).u64().Inputs(3, 5);
1603 INST(7, Opcode::Return).u64().Inputs(6);
1604 }
1605 }
1606
1607 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1608
1609 auto graph = CreateEmptyGraph();
1610 GRAPH(graph)
1611 {
1612 CONSTANT(0, 12);
1613 CONSTANT(1, 13);
1614
1615 BASIC_BLOCK(2, -1)
1616 {
1617 INST(2, Opcode::Neg).u64().Inputs(1);
1618 INST(3, Opcode::Add).u64().Inputs(0, 2);
1619 INST(4, Opcode::Neg).u64().Inputs(0);
1620 INST(5, Opcode::Add).u64().Inputs(1, 4);
1621 INST(6, Opcode::Add).u64().Inputs(3, 5);
1622 INST(7, Opcode::Return).u64().Inputs(6);
1623 }
1624 }
1625 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1626 }
1627
TEST_F(CleanupTest,TwoBlocksAndPhi)1628 TEST_F(CleanupTest, TwoBlocksAndPhi)
1629 {
1630 GRAPH(GetGraph())
1631 {
1632 CONSTANT(0, 12).s64();
1633 CONSTANT(1, 13).s64();
1634
1635 BASIC_BLOCK(2, 3, 4)
1636 {
1637 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1);
1638 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
1639 }
1640
1641 BASIC_BLOCK(3, 5)
1642 {
1643 INST(4, Opcode::Neg).u64().Inputs(0);
1644 INST(5, Opcode::Neg).u64().Inputs(1);
1645 }
1646
1647 BASIC_BLOCK(4, 5)
1648 {
1649 INST(7, Opcode::Neg).u64().Inputs(1);
1650 INST(8, Opcode::Neg).u64().Inputs(0);
1651 }
1652
1653 BASIC_BLOCK(5, 6)
1654 {
1655 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}});
1656 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}});
1657 INST(12, Opcode::Neg).u64().Inputs(10);
1658 INST(13, Opcode::Add).u64().Inputs(10, 11);
1659 }
1660
1661 BASIC_BLOCK(6, 7, 8)
1662 {
1663 INST(15, Opcode::Add).u64().Inputs(12, 13);
1664 INST(16, Opcode::Neg).u64().Inputs(12);
1665 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(16, 15);
1666 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17);
1667 }
1668
1669 BASIC_BLOCK(7, 8)
1670 {
1671 INST(19, Opcode::Add).u64().Inputs(0, 1);
1672 }
1673
1674 BASIC_BLOCK(8, -1)
1675 {
1676 INST(21, Opcode::Phi).u64().Inputs({{6, 16}, {7, 19}});
1677 INST(22, Opcode::Add).u64().Inputs(21, 1);
1678 INST(23, Opcode::Return).u64().Inputs(22);
1679 }
1680 }
1681
1682 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
1683
1684 auto graph = CreateEmptyGraph();
1685 GRAPH(graph)
1686 {
1687 CONSTANT(0, 12).s64();
1688 CONSTANT(1, 13).s64();
1689
1690 BASIC_BLOCK(2, 3, 4)
1691 {
1692 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1);
1693 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
1694 }
1695
1696 BASIC_BLOCK(3, 5)
1697 {
1698 INST(4, Opcode::Neg).u64().Inputs(0);
1699 INST(5, Opcode::Neg).u64().Inputs(1);
1700 }
1701
1702 BASIC_BLOCK(4, 5)
1703 {
1704 INST(7, Opcode::Neg).u64().Inputs(1);
1705 INST(8, Opcode::Neg).u64().Inputs(0);
1706 }
1707
1708 BASIC_BLOCK(5, 7, 8)
1709 {
1710 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}});
1711 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}});
1712 INST(12, Opcode::Neg).u64().Inputs(10);
1713 INST(13, Opcode::Add).u64().Inputs(10, 11);
1714 INST(15, Opcode::Add).u64().Inputs(12, 13);
1715 INST(16, Opcode::Neg).u64().Inputs(12);
1716 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(16, 15);
1717 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17);
1718 }
1719
1720 BASIC_BLOCK(7, 8)
1721 {
1722 INST(19, Opcode::Add).u64().Inputs(0, 1);
1723 }
1724
1725 BASIC_BLOCK(8, -1)
1726 {
1727 INST(21, Opcode::Phi).u64().Inputs(16, 19);
1728 INST(22, Opcode::Add).u64().Inputs(21, 1);
1729 INST(23, Opcode::Return).u64().Inputs(22);
1730 }
1731 }
1732 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1733 }
1734 } // namespace panda::compiler
1735