• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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