• 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 #include "optimizer/optimizations/if_conversion.h"
18 
19 namespace panda::compiler {
20 class IfConversionTest : public GraphTest {
21 #ifndef NDEBUG
22 public:
IfConversionTest()23     IfConversionTest()
24     {
25         // GraphChecker hack: LowLevel instructions may appear only after Lowering pass:
26         GetGraph()->SetLowLevelInstructionsEnabled();
27     }
28 #endif
29 };
30 
31 /*
32  * Test Graph:
33  *              [entry}
34  *                 |
35  *            /---[2]---\
36  *            |         |
37  *           [3]        |
38  *            |         |
39  *            \---[4]---/
40  *                 |
41  *               [exit]
42  */
TEST_F(IfConversionTest,TriangleTrueImm)43 TEST_F(IfConversionTest, TriangleTrueImm)
44 {
45     GRAPH(GetGraph())
46     {
47         PARAMETER(0, 0).u64();
48         CONSTANT(1, 10);
49         CONSTANT(2, 2);
50         BASIC_BLOCK(2, 3, 4)
51         {
52             INST(3, Opcode::Compare).b().CC(CC_B).Inputs(0, 1);
53             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
54         }
55         BASIC_BLOCK(3, 4)
56         {
57             INST(5, Opcode::Mul).u64().Inputs(0, 2);
58         }
59         BASIC_BLOCK(4, -1)
60         {
61             INST(6, Opcode::Phi).u64().Inputs({{2, 0}, {3, 5}});
62             INST(7, Opcode::Return).u64().Inputs(6);
63         }
64     }
65 
66     GetGraph()->RunPass<IfConversion>();
67 
68     auto graph = CreateEmptyGraph();
69     GRAPH(graph)
70     {
71         PARAMETER(0, 0).u64();
72         CONSTANT(1, 10);
73         CONSTANT(2, 2);
74         BASIC_BLOCK(2, -1)
75         {
76             INST(3, Opcode::Compare).b().CC(CC_B).Inputs(0, 1);
77             INST(5, Opcode::Mul).u64().Inputs(0, 2);
78             INST(4, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5, 0, 3);
79             INST(7, Opcode::Return).u64().Inputs(4);
80         }
81     }
82     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
83 }
84 
TEST_F(IfConversionTest,TriangleTrue)85 TEST_F(IfConversionTest, TriangleTrue)
86 {
87     GRAPH(GetGraph())
88     {
89         PARAMETER(0, 0).u64();
90         CONSTANT(1, 10);
91         CONSTANT(2, 2);
92         BASIC_BLOCK(2, 3, 4)
93         {
94             INST(3, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(0, 1);
95         }
96         BASIC_BLOCK(3, 4)
97         {
98             INST(4, Opcode::Mul).u64().Inputs(0, 2);
99         }
100         BASIC_BLOCK(4, -1)
101         {
102             INST(5, Opcode::Phi).u64().Inputs({{2, 0}, {3, 4}});
103             INST(6, Opcode::Return).u64().Inputs(5);
104         }
105     }
106 
107     GetGraph()->RunPass<IfConversion>();
108 
109     auto graph = CreateEmptyGraph();
110     GRAPH(graph)
111     {
112         PARAMETER(0, 0).u64();
113         CONSTANT(1, 10);
114         CONSTANT(2, 2);
115         BASIC_BLOCK(2, -1)
116         {
117             INST(4, Opcode::Mul).u64().Inputs(0, 2);
118             INST(3, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(4, 0, 0, 1);
119             INST(6, Opcode::Return).u64().Inputs(3);
120         }
121     }
122     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
123 }
124 
125 /*
126  * Test Graph:
127  *              [entry}
128  *                 |
129  *            /---[2]---\
130  *            |         |
131  *            |        [3]
132  *            |         |
133  *            \---[4]---/
134  *                 |
135  *               [exit]
136  */
TEST_F(IfConversionTest,TriangleFalseImm)137 TEST_F(IfConversionTest, TriangleFalseImm)
138 {
139     GRAPH(GetGraph())
140     {
141         PARAMETER(0, 0).u64();
142         CONSTANT(1, 10);
143         CONSTANT(2, 2);
144         BASIC_BLOCK(2, 4, 3)
145         {
146             INST(3, Opcode::Compare).b().CC(CC_AE).Inputs(0, 1);
147             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
148         }
149         BASIC_BLOCK(3, 4)
150         {
151             INST(5, Opcode::Mul).u64().Inputs(0, 2);
152         }
153         BASIC_BLOCK(4, -1)
154         {
155             INST(6, Opcode::Phi).u64().Inputs({{2, 0}, {3, 5}});
156             INST(7, Opcode::Return).u64().Inputs(6);
157         }
158     }
159 
160     GetGraph()->RunPass<IfConversion>();
161 
162     auto graph = CreateEmptyGraph();
163     GRAPH(graph)
164     {
165         PARAMETER(0, 0).u64();
166         CONSTANT(1, 10);
167         CONSTANT(2, 2);
168         BASIC_BLOCK(2, -1)
169         {
170             INST(3, Opcode::Compare).b().CC(CC_AE).Inputs(0, 1);
171             INST(5, Opcode::Mul).u64().Inputs(0, 2);
172             INST(4, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(0, 5, 3);
173             INST(7, Opcode::Return).u64().Inputs(4);
174         }
175     }
176     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
177 }
178 
TEST_F(IfConversionTest,TriangleFalse)179 TEST_F(IfConversionTest, TriangleFalse)
180 {
181     GRAPH(GetGraph())
182     {
183         PARAMETER(0, 0).u64();
184         CONSTANT(1, 10);
185         CONSTANT(2, 2);
186         BASIC_BLOCK(2, 4, 3)
187         {
188             INST(3, Opcode::If).SrcType(DataType::UINT64).CC(CC_LT).Inputs(0, 1);
189         }
190         BASIC_BLOCK(3, 4)
191         {
192             INST(4, Opcode::Mul).u64().Inputs(0, 2);
193         }
194         BASIC_BLOCK(4, -1)
195         {
196             INST(5, Opcode::Phi).u64().Inputs({{2, 0}, {3, 4}});
197             INST(6, Opcode::Return).u64().Inputs(5);
198         }
199     }
200 
201     GetGraph()->RunPass<IfConversion>();
202 
203     auto graph = CreateEmptyGraph();
204     GRAPH(graph)
205     {
206         PARAMETER(0, 0).u64();
207         CONSTANT(1, 10);
208         CONSTANT(2, 2);
209         BASIC_BLOCK(2, -1)
210         {
211             INST(4, Opcode::Mul).u64().Inputs(0, 2);
212             INST(3, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_LT).Inputs(0, 4, 0, 1);
213             INST(6, Opcode::Return).u64().Inputs(3);
214         }
215     }
216     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
217 }
218 
219 /*
220  * Test Graph:
221  *              [entry}
222  *                 |
223  *            /---[2]---\
224  *            |         |
225  *        /--[3]--\     |
226  *        |       |     |
227  *       [4]      |     |
228  *        |       |     |
229  *        \------[5]----/
230  *                |
231  *              [exit]
232  */
TEST_F(IfConversionTest,JointTriangleImm)233 TEST_F(IfConversionTest, JointTriangleImm)
234 {
235     GRAPH(GetGraph())
236     {
237         PARAMETER(0, 0).u64();
238         CONSTANT(1, 10);
239         CONSTANT(2, 2);
240         BASIC_BLOCK(2, 3, 5)
241         {
242             INST(3, Opcode::Compare).b().Inputs(0, 1);
243             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
244         }
245         BASIC_BLOCK(3, 4, 5)
246         {
247             INST(5, Opcode::Mul).u64().Inputs(0, 2);
248             INST(6, Opcode::Compare).b().Inputs(5, 1);
249             INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6);
250         }
251         BASIC_BLOCK(4, 5)
252         {
253             INST(8, Opcode::Mul).u64().Inputs(5, 2);
254         }
255         BASIC_BLOCK(5, -1)
256         {
257             INST(9, Opcode::Phi).u64().Inputs({{2, 0}, {3, 5}, {4, 8}});
258             INST(10, Opcode::Return).u64().Inputs(9);
259         }
260     }
261 
262     GetGraph()->RunPass<IfConversion>();
263 
264     auto graph = CreateEmptyGraph();
265     GRAPH(graph)
266     {
267         PARAMETER(0, 0).u64();
268         CONSTANT(1, 10);
269         CONSTANT(2, 2);
270         BASIC_BLOCK(2, 3, 5)
271         {
272             INST(3, Opcode::Compare).b().Inputs(0, 1);
273             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
274         }
275         BASIC_BLOCK(3, 5)
276         {
277             INST(5, Opcode::Mul).u64().Inputs(0, 2);
278             INST(6, Opcode::Compare).b().Inputs(5, 1);
279             INST(8, Opcode::Mul).u64().Inputs(5, 2);
280             INST(7, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8, 5, 6);
281         }
282         BASIC_BLOCK(5, -1)
283         {
284             INST(9, Opcode::Phi).u64().Inputs({{2, 0}, {3, 7}});
285             INST(10, Opcode::Return).u64().Inputs(9);
286         }
287     }
288     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
289 }
290 
TEST_F(IfConversionTest,TriangleTwice)291 TEST_F(IfConversionTest, TriangleTwice)
292 {
293     GRAPH(GetGraph())
294     {
295         PARAMETER(0, 0).u64();
296         PARAMETER(1, 1).u64();
297         PARAMETER(2, 2).u64();
298         BASIC_BLOCK(2, 3, 5)
299         {
300             INST(3, Opcode::Mul).u64().Inputs(0, 1);
301             INST(4, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(3, 1);
302         }
303         BASIC_BLOCK(3, 4, 5)
304         {
305             INST(5, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(3, 2);
306         }
307         BASIC_BLOCK(4, 5)
308         {
309             INST(6, Opcode::Mul).u64().Inputs(3, 2);
310         }
311         BASIC_BLOCK(5, -1)
312         {
313             INST(7, Opcode::Phi).u64().Inputs({{2, 0}, {3, 3}, {4, 6}});
314             INST(8, Opcode::Return).u64().Inputs(7);
315         }
316     }
317 
318     GetGraph()->RunPass<IfConversion>();
319 
320     auto graph = CreateEmptyGraph();
321     GRAPH(graph)
322     {
323         PARAMETER(0, 0).u64();
324         PARAMETER(1, 1).u64();
325         PARAMETER(2, 2).u64();
326         BASIC_BLOCK(2, -1)
327         {
328             INST(3, Opcode::Mul).u64().Inputs(0, 1);
329             INST(6, Opcode::Mul).u64().Inputs(3, 2);
330             INST(5, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(6, 3, 3, 2);
331             INST(4, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(5, 0, 3, 1);
332             INST(8, Opcode::Return).u64().Inputs(4);
333         }
334     }
335     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
336 }
337 
TEST_F(IfConversionTest,JointTriangleWithTrickFloatPhi)338 TEST_F(IfConversionTest, JointTriangleWithTrickFloatPhi)
339 {
340     GRAPH(GetGraph())
341     {
342         PARAMETER(0, 0).u64();
343         PARAMETER(1, 1).f64();
344         CONSTANT(2, 10);
345         BASIC_BLOCK(2, 3, 5)
346         {
347             INST(3, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(0, 2);
348         }
349         BASIC_BLOCK(3, 4, 5)
350         {
351             INST(4, Opcode::Mul).f64().Inputs(1, 1);
352             INST(5, Opcode::Mul).u64().Inputs(0, 2);
353             INST(6, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(5, 2);
354         }
355         BASIC_BLOCK(4, 5)
356         {
357             INST(7, Opcode::Mul).u64().Inputs(5, 2);
358         }
359         BASIC_BLOCK(5, -1)
360         {
361             INST(8, Opcode::Phi).u64().Inputs({{2, 0}, {3, 5}, {4, 7}});
362             INST(9, Opcode::Phi).f64().Inputs({{2, 1}, {3, 4}, {4, 4}});
363             INST(10, Opcode::Mul).f64().Inputs(9, 9);
364             INST(20, Opcode::SaveState).NoVregs();
365             INST(11, Opcode::CallStatic).u64().InputsAutoType(8, 10, 20);
366             INST(12, Opcode::Return).u64().Inputs(11);
367         }
368     }
369 
370     GetGraph()->RunPass<IfConversion>();
371     auto graph = CreateEmptyGraph();
372     GRAPH(graph)
373     {
374         PARAMETER(0, 0).u64();
375         PARAMETER(1, 1).f64();
376         CONSTANT(2, 10);
377         BASIC_BLOCK(2, 3, 5)
378         {
379             INST(3, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(0, 2);
380         }
381         BASIC_BLOCK(3, 5)
382         {
383             INST(4, Opcode::Mul).f64().Inputs(1, 1);
384             INST(5, Opcode::Mul).u64().Inputs(0, 2);
385             INST(7, Opcode::Mul).u64().Inputs(5, 2);
386             INST(6, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(7, 5, 5, 2);
387         }
388         BASIC_BLOCK(5, -1)
389         {
390             INST(8, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
391             INST(9, Opcode::Phi).f64().Inputs({{2, 1}, {3, 4}});
392             INST(10, Opcode::Mul).f64().Inputs(9, 9);
393             INST(20, Opcode::SaveState).NoVregs();
394             INST(11, Opcode::CallStatic).u64().InputsAutoType(8, 10, 20);
395             INST(12, Opcode::Return).u64().Inputs(11);
396         }
397     }
398     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
399 }
400 
401 /*
402  * Test Graph:
403  *              [entry}
404  *                 |
405  *            /---[2]---\
406  *            |         |
407  *           [3]       [4]
408  *            |         |
409  *            \---[5]---/
410  *                 |
411  *               [exit]
412  */
TEST_F(IfConversionTest,DiamondImm)413 TEST_F(IfConversionTest, DiamondImm)
414 {
415     GRAPH(GetGraph())
416     {
417         PARAMETER(0, 0).u32();
418         PARAMETER(1, 1).u32();
419         CONSTANT(2, 0);
420         BASIC_BLOCK(2, 3, 4)
421         {
422             INST(3, Opcode::Compare).b().Inputs(1, 2);
423             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
424         }
425         BASIC_BLOCK(4, 5)
426         {
427             INST(5, Opcode::Add).u32().Inputs(0, 1);
428         }
429         BASIC_BLOCK(3, 5)
430         {
431             INST(7, Opcode::Sub).u32().Inputs(0, 1);
432         }
433         BASIC_BLOCK(5, -1)
434         {
435             INST(8, Opcode::Phi).u32().Inputs({{4, 5}, {3, 7}});
436             INST(9, Opcode::Return).u32().Inputs(8);
437         }
438     }
439 
440     GetGraph()->RunPass<IfConversion>();
441 
442     auto graph = CreateEmptyGraph();
443     GRAPH(graph)
444     {
445         PARAMETER(0, 0).u32();
446         PARAMETER(1, 1).u32();
447         CONSTANT(2, 0);
448         BASIC_BLOCK(2, -1)
449         {
450             INST(3, Opcode::Compare).b().Inputs(1, 2);
451             INST(7, Opcode::Sub).u32().Inputs(0, 1);
452             INST(5, Opcode::Add).u32().Inputs(0, 1);
453             INST(4, Opcode::SelectImm).u32().SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7, 5, 3);
454             INST(9, Opcode::Return).u32().Inputs(4);
455         }
456     }
457     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
458 }
459 
460 /*
461  * Test Graph:
462  *              [entry}
463  *                 |
464  *            /---[2]---\
465  *            |         |
466  *        /--[3]--\     |
467  *        |       |     |
468  *       [4]     [5]    |
469  *        |       |     |
470  *        \------[6]----/
471  *                |
472  *              [exit]
473  */
TEST_F(IfConversionTest,JointDiamondImm)474 TEST_F(IfConversionTest, JointDiamondImm)
475 {
476     GRAPH(GetGraph())
477     {
478         PARAMETER(0, 0).u64();
479         PARAMETER(1, 1).u64();
480         BASIC_BLOCK(2, 3, 6)
481         {
482             INST(2, Opcode::Compare).b().Inputs(0, 1);
483             INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
484         }
485         BASIC_BLOCK(3, 4, 5)
486         {
487             INST(4, Opcode::Mul).u64().Inputs(0, 0);
488             INST(5, Opcode::Compare).b().Inputs(4, 1);
489             INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5);
490         }
491         BASIC_BLOCK(4, 6)
492         {
493             INST(7, Opcode::Mul).u64().Inputs(4, 1);
494         }
495         BASIC_BLOCK(5, 6)
496         {
497             INST(8, Opcode::Mul).u64().Inputs(4, 0);
498         }
499         BASIC_BLOCK(6, -1)
500         {
501             INST(9, Opcode::Phi).u64().Inputs({{2, 0}, {4, 7}, {5, 8}});
502             INST(10, Opcode::Return).u64().Inputs(9);
503         }
504     }
505 
506     GetGraph()->RunPass<IfConversion>();
507 
508     auto graph = CreateEmptyGraph();
509     GRAPH(graph)
510     {
511         PARAMETER(0, 0).u64();
512         PARAMETER(1, 1).u64();
513         BASIC_BLOCK(2, 3, 6)
514         {
515             INST(2, Opcode::Compare).b().Inputs(0, 1);
516             INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2);
517         }
518         BASIC_BLOCK(3, 6)
519         {
520             INST(4, Opcode::Mul).u64().Inputs(0, 0);
521             INST(5, Opcode::Compare).b().Inputs(4, 1);
522             INST(7, Opcode::Mul).u64().Inputs(4, 1);
523             INST(8, Opcode::Mul).u64().Inputs(4, 0);
524             INST(6, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7, 8, 5);
525         }
526         BASIC_BLOCK(6, -1)
527         {
528             INST(9, Opcode::Phi).u64().Inputs({{2, 0}, {3, 6}});
529             INST(10, Opcode::Return).u64().Inputs(9);
530         }
531     }
532     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
533 }
534 
TEST_F(IfConversionTest,JointDiamond)535 TEST_F(IfConversionTest, JointDiamond)
536 {
537     GRAPH(GetGraph())
538     {
539         PARAMETER(0, 0).u64();
540         PARAMETER(1, 1).u64();
541         BASIC_BLOCK(2, 3, 6)
542         {
543             INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1);
544         }
545         BASIC_BLOCK(3, 4, 5)
546         {
547             INST(3, Opcode::Mul).u64().Inputs(0, 0);
548             INST(4, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(3, 1);
549         }
550         BASIC_BLOCK(4, 6)
551         {
552             INST(5, Opcode::Mul).u64().Inputs(3, 1);
553         }
554         BASIC_BLOCK(5, 6)
555         {
556             INST(6, Opcode::Mul).u64().Inputs(3, 0);
557         }
558         BASIC_BLOCK(6, -1)
559         {
560             INST(7, Opcode::Phi).u64().Inputs({{2, 0}, {4, 5}, {5, 6}});
561             INST(8, Opcode::Return).u64().Inputs(7);
562         }
563     }
564 
565     GetGraph()->RunPass<IfConversion>();
566 
567     auto graph = CreateEmptyGraph();
568     GRAPH(graph)
569     {
570         PARAMETER(0, 0).u64();
571         PARAMETER(1, 1).u64();
572         BASIC_BLOCK(2, 3, 6)
573         {
574             INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1);
575         }
576         BASIC_BLOCK(3, 6)
577         {
578             INST(3, Opcode::Mul).u64().Inputs(0, 0);
579             INST(5, Opcode::Mul).u64().Inputs(3, 1);
580             INST(6, Opcode::Mul).u64().Inputs(3, 0);
581             INST(4, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_GT).Inputs(5, 6, 3, 1);
582         }
583         BASIC_BLOCK(6, -1)
584         {
585             INST(7, Opcode::Phi).u64().Inputs({{2, 0}, {3, 4}});
586             INST(8, Opcode::Return).u64().Inputs(7);
587         }
588     }
589     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
590 }
591 
TEST_F(IfConversionTest,JointDiamondWithDroppedSelect)592 TEST_F(IfConversionTest, JointDiamondWithDroppedSelect)
593 {
594     GRAPH(GetGraph())
595     {
596         PARAMETER(0, 0).u64();
597         PARAMETER(1, 1).u64();
598         BASIC_BLOCK(2, 3, 6)
599         {
600             INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1);
601         }
602         BASIC_BLOCK(3, 4, 5)
603         {
604             INST(3, Opcode::Mul).u64().Inputs(0, 0);
605             INST(4, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(3, 1);
606         }
607         BASIC_BLOCK(4, 6)
608         {
609             INST(5, Opcode::Mul).u64().Inputs(3, 1);
610         }
611         BASIC_BLOCK(5, 6)
612         {
613             INST(6, Opcode::Mul).u64().Inputs(3, 0);
614         }
615         BASIC_BLOCK(6, -1)
616         {
617             INST(7, Opcode::Phi).u64().Inputs({{2, 0}, {4, 5}, {5, 6}});
618             INST(8, Opcode::Phi).u64().Inputs({{2, 0}, {4, 3}, {5, 3}});
619             INST(9, Opcode::Add).u64().Inputs(7, 8);
620             INST(10, Opcode::Return).u64().Inputs(9);
621         }
622     }
623 
624     GetGraph()->RunPass<IfConversion>();
625 
626     auto graph = CreateEmptyGraph();
627     GRAPH(graph)
628     {
629         PARAMETER(0, 0).u64();
630         PARAMETER(1, 1).u64();
631         BASIC_BLOCK(2, 3, 6)
632         {
633             INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1);
634         }
635         BASIC_BLOCK(3, 6)
636         {
637             INST(3, Opcode::Mul).u64().Inputs(0, 0);
638             INST(5, Opcode::Mul).u64().Inputs(3, 1);
639             INST(6, Opcode::Mul).u64().Inputs(3, 0);
640             INST(4, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_GT).Inputs(5, 6, 3, 1);
641             // Second Select not needed
642         }
643         BASIC_BLOCK(6, -1)
644         {
645             INST(7, Opcode::Phi).u64().Inputs({{2, 0}, {3, 4}});
646             INST(8, Opcode::Phi).u64().Inputs({{2, 0}, {3, 3}});
647             INST(9, Opcode::Add).u64().Inputs(7, 8);
648             INST(10, Opcode::Return).u64().Inputs(9);
649         }
650     }
651     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
652 }
653 
TEST_F(IfConversionTest,JointDiamondRunTwice)654 TEST_F(IfConversionTest, JointDiamondRunTwice)
655 {
656     GRAPH(GetGraph())
657     {
658         PARAMETER(0, 0).u64();
659         PARAMETER(1, 1).u64();
660         BASIC_BLOCK(2, 3, 6)
661         {
662             INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1);
663         }
664         BASIC_BLOCK(3, 4, 5)
665         {
666             INST(3, Opcode::Mul).u64().Inputs(0, 0);
667             INST(4, Opcode::Mul).u64().Inputs(1, 1);
668             INST(5, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(4, 1);
669         }
670         BASIC_BLOCK(4, 6) {}
671         BASIC_BLOCK(5, 6) {}
672         BASIC_BLOCK(6, -1)
673         {
674             INST(6, Opcode::Phi).u64().Inputs({{2, 0}, {4, 3}, {5, 3}});
675             INST(7, Opcode::Return).u64().Inputs(6);
676         }
677     }
678 
679     ASSERT_TRUE(GetGraph()->RunPass<IfConversion>());
680     ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
681 
682     auto graph = CreateEmptyGraph();
683     GRAPH(graph)
684     {
685         PARAMETER(0, 0).u64();
686         PARAMETER(1, 1).u64();
687         BASIC_BLOCK(2, -1)
688         {
689             INST(3, Opcode::Mul).u64().Inputs(0, 0);
690             INST(2, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_GE).Inputs(3, 0, 0, 1);
691             INST(7, Opcode::Return).u64().Inputs(2);
692         }
693     }
694     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
695 }
696 
697 /*
698  *  No conversion allowed cases below.
699  */
TEST_F(IfConversionTest,TriangleWithCall)700 TEST_F(IfConversionTest, TriangleWithCall)
701 {
702     GRAPH(GetGraph())
703     {
704         PARAMETER(0, 0).u64();
705         CONSTANT(1, 10);
706         CONSTANT(2, 2);
707         BASIC_BLOCK(2, 3, 4)
708         {
709             INST(3, Opcode::Compare).b().Inputs(0, 1);
710             INST(4, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(3);
711         }
712         BASIC_BLOCK(3, 4)
713         {
714             INST(20, Opcode::SaveState).NoVregs();
715             INST(5, Opcode::CallStatic).u64().InputsAutoType(0, 2, 20);
716         }
717         BASIC_BLOCK(4, -1)
718         {
719             INST(6, Opcode::Phi).u64().Inputs({{2, 0}, {3, 5}});
720             INST(7, Opcode::Return).u64().Inputs(6);
721         }
722     }
723 
724     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
725 }
726 
TEST_F(IfConversionTest,DiamondThreeOperations)727 TEST_F(IfConversionTest, DiamondThreeOperations)
728 {
729     GRAPH(GetGraph())
730     {
731         PARAMETER(0, 0).u32();
732         PARAMETER(1, 1).u32();
733         CONSTANT(2, 42);
734         CONSTANT(3, 0);
735         BASIC_BLOCK(2, 3, 4)
736         {
737             INST(4, Opcode::Compare).b().Inputs(1, 3);
738             INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4);
739         }
740         BASIC_BLOCK(4, 5)
741         {
742             INST(6, Opcode::Add).u32().Inputs(0, 1);
743         }
744         BASIC_BLOCK(3, 5)
745         {
746             INST(7, Opcode::Add).u32().Inputs(0, 2);
747             INST(8, Opcode::Sub).u32().Inputs(7, 1);
748         }
749         BASIC_BLOCK(5, -1)
750         {
751             INST(9, Opcode::Phi).u32().Inputs({{4, 6}, {3, 8}});
752             INST(10, Opcode::Return).u32().Inputs(9);
753         }
754     }
755 
756     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
757 }
758 
TEST_F(IfConversionTest,DiamondThreePhis)759 TEST_F(IfConversionTest, DiamondThreePhis)
760 {
761     GRAPH(GetGraph())
762     {
763         PARAMETER(0, 0).u32();
764         PARAMETER(1, 1).u32();
765         CONSTANT(2, 42);
766         CONSTANT(3, 0);
767         BASIC_BLOCK(2, 3, 4)
768         {
769             INST(6, Opcode::Add).u32().Inputs(0, 1);
770             INST(7, Opcode::Add).u32().Inputs(0, 2);
771             INST(8, Opcode::Sub).u32().Inputs(7, 1);
772             INST(4, Opcode::Compare).b().Inputs(1, 3);
773             INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4);
774         }
775         BASIC_BLOCK(4, 5) {}
776         BASIC_BLOCK(3, 5) {}
777         BASIC_BLOCK(5, -1)
778         {
779             INST(9, Opcode::Phi).u32().Inputs({{4, 6}, {3, 8}});
780             INST(10, Opcode::Phi).u32().Inputs({{4, 6}, {3, 7}});
781             INST(11, Opcode::Phi).u32().Inputs({{4, 7}, {3, 8}});
782             INST(12, Opcode::Add).u32().Inputs(9, 10);
783             INST(13, Opcode::Add).u32().Inputs(11, 12);
784             INST(14, Opcode::Return).u32().Inputs(13);
785         }
786     }
787 
788     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
789 }
790 
TEST_F(IfConversionTest,TriangleFloat)791 TEST_F(IfConversionTest, TriangleFloat)
792 {
793     GRAPH(GetGraph())
794     {
795         PARAMETER(0, 0).f64();
796         PARAMETER(1, 1).f64();
797         PARAMETER(2, 2).f64();
798         BASIC_BLOCK(2, 3, 4)
799         {
800             INST(3, Opcode::Cmp).s32().SrcType(DataType::FLOAT64).Inputs(0, 1);
801             INST(4, Opcode::IfImm).SrcType(DataType::INT32).CC(CC_NE).Imm(0).Inputs(3);
802         }
803         BASIC_BLOCK(3, 4)
804         {
805             INST(5, Opcode::Mul).f64().Inputs(0, 2);
806         }
807         BASIC_BLOCK(4, -1)
808         {
809             INST(6, Opcode::Phi).f64().Inputs({{2, 0}, {3, 5}});
810             INST(7, Opcode::Return).f64().Inputs(6);
811         }
812     }
813 
814     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
815 }
816 
TEST_F(IfConversionTest,TrianglePhiFloat)817 TEST_F(IfConversionTest, TrianglePhiFloat)
818 {
819     GRAPH(GetGraph())
820     {
821         PARAMETER(0, 0).f64();
822         PARAMETER(1, 1).f64();
823         PARAMETER(2, 2).f64();
824         BASIC_BLOCK(2, 3, 4)
825         {
826             INST(5, Opcode::Mul).f64().Inputs(0, 2);
827             INST(3, Opcode::Cmp).s32().SrcType(DataType::FLOAT64).Inputs(0, 1);
828             INST(4, Opcode::IfImm).SrcType(DataType::INT32).CC(CC_NE).Imm(0).Inputs(3);
829         }
830         BASIC_BLOCK(3, 4) {}  // Instructions 5 moved up manually
831         BASIC_BLOCK(4, -1)
832         {
833             INST(6, Opcode::Phi).f64().Inputs({{2, 0}, {3, 5}});
834             INST(7, Opcode::Return).f64().Inputs(6);
835         }
836     }
837 
838     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
839 }
840 }  // namespace panda::compiler
841