• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 ark::compiler {
20 class IfConversionTest : public GraphTest {
21 public:
IfConversionTest()22     IfConversionTest()
23     {
24         SetGraphArch(ark::RUNTIME_ARCH);
25 #ifndef NDEBUG
26         // GraphChecker hack: LowLevel instructions may appear only after Lowering pass:
27         GetGraph()->SetLowLevelInstructionsEnabled();
28 #endif
29     }
30     Graph *CreateExpectedJointTriangleImm();
31     Graph *CreateExpJointTriangleWithTrickFloatPhi();
32     Graph *CreateExpectedJointDiamondImm();
33     Graph *CreateExpectedJointDiamond();
34     Graph *CreateExpJointDiamondWithDroppedSelect();
35 };
36 
37 // NOLINTBEGIN(readability-magic-numbers)
38 /*
39  * Test Graph:
40  *              [entry}
41  *                 |
42  *            /---[2]---\
43  *            |         |
44  *           [3]        |
45  *            |         |
46  *            \---[4]---/
47  *                 |
48  *               [exit]
49  */
TEST_F(IfConversionTest,TriangleTrueImm)50 TEST_F(IfConversionTest, TriangleTrueImm)
51 {
52     GRAPH(GetGraph())
53     {
54         PARAMETER(0U, 0U).u64();
55         CONSTANT(1U, 10U);
56         CONSTANT(2U, 2U);
57         BASIC_BLOCK(2U, 3U, 4U)
58         {
59             INST(3U, Opcode::Compare).b().CC(CC_B).Inputs(0U, 1U);
60             INST(4U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(3U);
61         }
62         BASIC_BLOCK(3U, 4U)
63         {
64             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
65         }
66         BASIC_BLOCK(4U, -1L)
67         {
68             INST(6U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 5U}});
69             INST(7U, Opcode::Return).u64().Inputs(6U);
70         }
71     }
72 
73     GetGraph()->RunPass<IfConversion>();
74 
75     auto graph = CreateEmptyGraph();
76     GRAPH(graph)
77     {
78         PARAMETER(0U, 0U).u64();
79         CONSTANT(1U, 10U);
80         CONSTANT(2U, 2U);
81         BASIC_BLOCK(2U, -1L)
82         {
83             INST(3U, Opcode::Compare).b().CC(CC_B).Inputs(0U, 1U);
84             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
85             INST(4U, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(5U, 0U, 3U);
86             INST(7U, Opcode::Return).u64().Inputs(4U);
87         }
88     }
89     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
90 }
91 
TEST_F(IfConversionTest,TriangleTrue)92 TEST_F(IfConversionTest, TriangleTrue)
93 {
94     GRAPH(GetGraph())
95     {
96         PARAMETER(0U, 0U).u64();
97         CONSTANT(1U, 10U);
98         CONSTANT(2U, 2U);
99         BASIC_BLOCK(2U, 3U, 4U)
100         {
101             INST(3U, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(0U, 1U);
102         }
103         BASIC_BLOCK(3U, 4U)
104         {
105             INST(4U, Opcode::Mul).u64().Inputs(0U, 2U);
106         }
107         BASIC_BLOCK(4U, -1L)
108         {
109             INST(5U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 4U}});
110             INST(6U, Opcode::Return).u64().Inputs(5U);
111         }
112     }
113 
114     GetGraph()->RunPass<IfConversion>();
115 
116     auto graph = CreateEmptyGraph();
117     GRAPH(graph)
118     {
119         PARAMETER(0U, 0U).u64();
120         CONSTANT(1U, 10U);
121         CONSTANT(2U, 2U);
122         BASIC_BLOCK(2U, -1L)
123         {
124             INST(4U, Opcode::Mul).u64().Inputs(0U, 2U);
125             INST(3U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(4U, 0U, 0U, 1U);
126             INST(6U, Opcode::Return).u64().Inputs(3U);
127         }
128     }
129     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
130 }
131 
132 /*
133  * Test Graph:
134  *              [entry}
135  *                 |
136  *            /---[2]---\
137  *            |         |
138  *            |        [3]
139  *            |         |
140  *            \---[4]---/
141  *                 |
142  *               [exit]
143  */
TEST_F(IfConversionTest,TriangleFalseImm)144 TEST_F(IfConversionTest, TriangleFalseImm)
145 {
146     GRAPH(GetGraph())
147     {
148         PARAMETER(0U, 0U).u64();
149         CONSTANT(1U, 10U);
150         CONSTANT(2U, 2U);
151         BASIC_BLOCK(2U, 4U, 3U)
152         {
153             INST(3U, Opcode::Compare).b().CC(CC_AE).Inputs(0U, 1U);
154             INST(4U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(3U);
155         }
156         BASIC_BLOCK(3U, 4U)
157         {
158             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
159         }
160         BASIC_BLOCK(4U, -1L)
161         {
162             INST(6U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 5U}});
163             INST(7U, Opcode::Return).u64().Inputs(6U);
164         }
165     }
166 
167     GetGraph()->RunPass<IfConversion>();
168 
169     auto graph = CreateEmptyGraph();
170     GRAPH(graph)
171     {
172         PARAMETER(0U, 0U).u64();
173         CONSTANT(1U, 10U);
174         CONSTANT(2U, 2U);
175         BASIC_BLOCK(2U, -1L)
176         {
177             INST(3U, Opcode::Compare).b().CC(CC_AE).Inputs(0U, 1U);
178             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
179             INST(4U, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(0U, 5U, 3U);
180             INST(7U, Opcode::Return).u64().Inputs(4U);
181         }
182     }
183     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
184 }
185 
TEST_F(IfConversionTest,TriangleFalse)186 TEST_F(IfConversionTest, TriangleFalse)
187 {
188     GRAPH(GetGraph())
189     {
190         PARAMETER(0U, 0U).u64();
191         CONSTANT(1U, 10U);
192         CONSTANT(2U, 2U);
193         BASIC_BLOCK(2U, 4U, 3U)
194         {
195             INST(3U, Opcode::If).SrcType(DataType::UINT64).CC(CC_LT).Inputs(0U, 1U);
196         }
197         BASIC_BLOCK(3U, 4U)
198         {
199             INST(4U, Opcode::Mul).u64().Inputs(0U, 2U);
200         }
201         BASIC_BLOCK(4U, -1L)
202         {
203             INST(5U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 4U}});
204             INST(6U, Opcode::Return).u64().Inputs(5U);
205         }
206     }
207 
208     GetGraph()->RunPass<IfConversion>();
209 
210     auto graph = CreateEmptyGraph();
211     GRAPH(graph)
212     {
213         PARAMETER(0U, 0U).u64();
214         CONSTANT(1U, 10U);
215         CONSTANT(2U, 2U);
216         BASIC_BLOCK(2U, -1L)
217         {
218             INST(4U, Opcode::Mul).u64().Inputs(0U, 2U);
219             INST(3U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_LT).Inputs(0U, 4U, 0U, 1U);
220             INST(6U, Opcode::Return).u64().Inputs(3U);
221         }
222     }
223     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
224 }
225 
CreateExpectedJointTriangleImm()226 Graph *IfConversionTest::CreateExpectedJointTriangleImm()
227 {
228     auto graph = CreateEmptyGraph();
229     GRAPH(graph)
230     {
231         PARAMETER(0U, 0U).u64();
232         CONSTANT(1U, 10U);
233         CONSTANT(2U, 2U);
234         BASIC_BLOCK(2U, 3U, 5U)
235         {
236             INST(3U, Opcode::Compare).b().Inputs(0U, 1U);
237             INST(4U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(3U);
238         }
239         BASIC_BLOCK(3U, 5U)
240         {
241             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
242             INST(6U, Opcode::Compare).b().Inputs(5U, 1U);
243             INST(8U, Opcode::Mul).u64().Inputs(5U, 2U);
244             INST(7U, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(8U, 5U, 6U);
245         }
246         BASIC_BLOCK(5U, -1L)
247         {
248             INST(9U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 7U}});
249             INST(10U, Opcode::Return).u64().Inputs(9U);
250         }
251     }
252     return graph;
253 }
254 
255 /*
256  * Test Graph:
257  *              [entry}
258  *                 |
259  *            /---[2]---\
260  *            |         |
261  *        /--[3]--\     |
262  *        |       |     |
263  *       [4]      |     |
264  *        |       |     |
265  *        \------[5]----/
266  *                |
267  *              [exit]
268  */
TEST_F(IfConversionTest,JointTriangleImm)269 TEST_F(IfConversionTest, JointTriangleImm)
270 {
271     GRAPH(GetGraph())
272     {
273         PARAMETER(0U, 0U).u64();
274         CONSTANT(1U, 10U);
275         CONSTANT(2U, 2U);
276         BASIC_BLOCK(2U, 3U, 5U)
277         {
278             INST(3U, Opcode::Compare).b().Inputs(0U, 1U);
279             INST(4U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(3U);
280         }
281         BASIC_BLOCK(3U, 4U, 5U)
282         {
283             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
284             INST(6U, Opcode::Compare).b().Inputs(5U, 1U);
285             INST(7U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(6U);
286         }
287         BASIC_BLOCK(4U, 5U)
288         {
289             INST(8U, Opcode::Mul).u64().Inputs(5U, 2U);
290         }
291         BASIC_BLOCK(5U, -1L)
292         {
293             INST(9U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 5U}, {4U, 8U}});
294             INST(10U, Opcode::Return).u64().Inputs(9U);
295         }
296     }
297 
298     GetGraph()->RunPass<IfConversion>();
299 
300     auto graph = CreateExpectedJointTriangleImm();
301     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
302 }
303 
TEST_F(IfConversionTest,TriangleTwice)304 TEST_F(IfConversionTest, TriangleTwice)
305 {
306     GRAPH(GetGraph())
307     {
308         PARAMETER(0U, 0U).u64();
309         PARAMETER(1U, 1U).u64();
310         PARAMETER(2U, 2U).u64();
311         BASIC_BLOCK(2U, 3U, 5U)
312         {
313             INST(3U, Opcode::Mul).u64().Inputs(0U, 1U);
314             INST(4U, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(3U, 1U);
315         }
316         BASIC_BLOCK(3U, 4U, 5U)
317         {
318             INST(5U, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(3U, 2U);
319         }
320         BASIC_BLOCK(4U, 5U)
321         {
322             INST(6U, Opcode::Mul).u64().Inputs(3U, 2U);
323         }
324         BASIC_BLOCK(5U, -1L)
325         {
326             INST(7U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 3U}, {4U, 6U}});
327             INST(8U, Opcode::Return).u64().Inputs(7U);
328         }
329     }
330 
331     GetGraph()->RunPass<IfConversion>();
332 
333     auto graph = CreateEmptyGraph();
334     GRAPH(graph)
335     {
336         PARAMETER(0U, 0U).u64();
337         PARAMETER(1U, 1U).u64();
338         PARAMETER(2U, 2U).u64();
339         BASIC_BLOCK(2U, -1L)
340         {
341             INST(3U, Opcode::Mul).u64().Inputs(0U, 1U);
342             INST(6U, Opcode::Mul).u64().Inputs(3U, 2U);
343             INST(5U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(6U, 3U, 3U, 2U);
344             INST(4U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(5U, 0U, 3U, 1U);
345             INST(8U, Opcode::Return).u64().Inputs(4U);
346         }
347     }
348     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
349 }
350 
CreateExpJointTriangleWithTrickFloatPhi()351 Graph *IfConversionTest::CreateExpJointTriangleWithTrickFloatPhi()
352 {
353     auto graph = CreateEmptyGraph();
354     GRAPH(graph)
355     {
356         PARAMETER(0U, 0U).u64();
357         PARAMETER(1U, 1U).f64();
358         CONSTANT(2U, 10U);
359         BASIC_BLOCK(2U, 3U, 5U)
360         {
361             INST(3U, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(0U, 2U);
362         }
363         BASIC_BLOCK(3U, 5U)
364         {
365             INST(4U, Opcode::Mul).f64().Inputs(1U, 1U);
366             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
367             INST(7U, Opcode::Mul).u64().Inputs(5U, 2U);
368             INST(6U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_NE).Inputs(7U, 5U, 5U, 2U);
369         }
370         BASIC_BLOCK(5U, -1L)
371         {
372             INST(8U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 6U}});
373             INST(9U, Opcode::Phi).f64().Inputs({{2U, 1U}, {3U, 4U}});
374             INST(10U, Opcode::Mul).f64().Inputs(9U, 9U);
375             INST(20U, Opcode::SaveState).NoVregs();
376             INST(11U, Opcode::CallStatic).u64().InputsAutoType(8U, 10U, 20U);
377             INST(12U, Opcode::Return).u64().Inputs(11U);
378         }
379     }
380     return graph;
381 }
382 
TEST_F(IfConversionTest,JointTriangleWithTrickFloatPhi)383 TEST_F(IfConversionTest, JointTriangleWithTrickFloatPhi)
384 {
385     GRAPH(GetGraph())
386     {
387         PARAMETER(0U, 0U).u64();
388         PARAMETER(1U, 1U).f64();
389         CONSTANT(2U, 10U);
390         BASIC_BLOCK(2U, 3U, 5U)
391         {
392             INST(3U, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(0U, 2U);
393         }
394         BASIC_BLOCK(3U, 4U, 5U)
395         {
396             INST(4U, Opcode::Mul).f64().Inputs(1U, 1U);
397             INST(5U, Opcode::Mul).u64().Inputs(0U, 2U);
398             INST(6U, Opcode::If).SrcType(DataType::UINT64).CC(CC_NE).Inputs(5U, 2U);
399         }
400         BASIC_BLOCK(4U, 5U)
401         {
402             INST(7U, Opcode::Mul).u64().Inputs(5U, 2U);
403         }
404         BASIC_BLOCK(5U, -1L)
405         {
406             INST(8U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 5U}, {4U, 7U}});
407             INST(9U, Opcode::Phi).f64().Inputs({{2U, 1U}, {3U, 4U}, {4U, 4U}});
408             INST(10U, Opcode::Mul).f64().Inputs(9U, 9U);
409             INST(20U, Opcode::SaveState).NoVregs();
410             INST(11U, Opcode::CallStatic).u64().InputsAutoType(8U, 10U, 20U);
411             INST(12U, Opcode::Return).u64().Inputs(11U);
412         }
413     }
414 
415     GetGraph()->RunPass<IfConversion>();
416 
417     auto graph = CreateExpJointTriangleWithTrickFloatPhi();
418     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
419 }
420 
421 /*
422  * Test Graph:
423  *              [entry}
424  *                 |
425  *            /---[2]---\
426  *            |         |
427  *           [3]       [4]
428  *            |         |
429  *            \---[5]---/
430  *                 |
431  *               [exit]
432  */
TEST_F(IfConversionTest,DiamondImm)433 TEST_F(IfConversionTest, DiamondImm)
434 {
435     GRAPH(GetGraph())
436     {
437         PARAMETER(0U, 0U).u32();
438         PARAMETER(1U, 1U).u32();
439         CONSTANT(2U, 0U);
440         BASIC_BLOCK(2U, 3U, 4U)
441         {
442             INST(3U, Opcode::Compare).b().Inputs(1U, 2U);
443             INST(4U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(3U);
444         }
445         BASIC_BLOCK(4U, 5U)
446         {
447             INST(5U, Opcode::Add).u32().Inputs(0U, 1U);
448         }
449         BASIC_BLOCK(3U, 5U)
450         {
451             INST(7U, Opcode::Sub).u32().Inputs(0U, 1U);
452         }
453         BASIC_BLOCK(5U, -1L)
454         {
455             INST(8U, Opcode::Phi).u32().Inputs({{4U, 5U}, {3U, 7U}});
456             INST(9U, Opcode::Return).u32().Inputs(8U);
457         }
458     }
459 
460     GetGraph()->RunPass<IfConversion>();
461 
462     auto graph = CreateEmptyGraph();
463     GRAPH(graph)
464     {
465         PARAMETER(0U, 0U).u32();
466         PARAMETER(1U, 1U).u32();
467         CONSTANT(2U, 0U);
468         BASIC_BLOCK(2U, -1L)
469         {
470             INST(3U, Opcode::Compare).b().Inputs(1U, 2U);
471             INST(7U, Opcode::Sub).u32().Inputs(0U, 1U);
472             INST(5U, Opcode::Add).u32().Inputs(0U, 1U);
473             INST(4U, Opcode::SelectImm).u32().SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(7U, 5U, 3U);
474             INST(9U, Opcode::Return).u32().Inputs(4U);
475         }
476     }
477     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
478 }
479 
CreateExpectedJointDiamondImm()480 Graph *IfConversionTest::CreateExpectedJointDiamondImm()
481 {
482     auto graph = CreateEmptyGraph();
483     GRAPH(graph)
484     {
485         PARAMETER(0U, 0U).u64();
486         PARAMETER(1U, 1U).u64();
487         BASIC_BLOCK(2U, 3U, 6U)
488         {
489             INST(2U, Opcode::Compare).b().Inputs(0U, 1U);
490             INST(3U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(2U);
491         }
492         BASIC_BLOCK(3U, 6U)
493         {
494             INST(4U, Opcode::Mul).u64().Inputs(0U, 0U);
495             INST(5U, Opcode::Compare).b().Inputs(4U, 1U);
496             INST(7U, Opcode::Mul).u64().Inputs(4U, 1U);
497             INST(8U, Opcode::Mul).u64().Inputs(4U, 0U);
498             INST(6U, Opcode::SelectImm).u64().SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(7U, 8U, 5U);
499         }
500         BASIC_BLOCK(6U, -1L)
501         {
502             INST(9U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 6U}});
503             INST(10U, Opcode::Return).u64().Inputs(9U);
504         }
505     }
506     return graph;
507 }
508 
509 /*
510  * Test Graph:
511  *              [entry}
512  *                 |
513  *            /---[2]---\
514  *            |         |
515  *        /--[3]--\     |
516  *        |       |     |
517  *       [4]     [5]    |
518  *        |       |     |
519  *        \------[6]----/
520  *                |
521  *              [exit]
522  */
TEST_F(IfConversionTest,JointDiamondImm)523 TEST_F(IfConversionTest, JointDiamondImm)
524 {
525     GRAPH(GetGraph())
526     {
527         PARAMETER(0U, 0U).u64();
528         PARAMETER(1U, 1U).u64();
529         BASIC_BLOCK(2U, 3U, 6U)
530         {
531             INST(2U, Opcode::Compare).b().Inputs(0U, 1U);
532             INST(3U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(2U);
533         }
534         BASIC_BLOCK(3U, 4U, 5U)
535         {
536             INST(4U, Opcode::Mul).u64().Inputs(0U, 0U);
537             INST(5U, Opcode::Compare).b().Inputs(4U, 1U);
538             INST(6U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(5U);
539         }
540         BASIC_BLOCK(4U, 6U)
541         {
542             INST(7U, Opcode::Mul).u64().Inputs(4U, 1U);
543         }
544         BASIC_BLOCK(5U, 6U)
545         {
546             INST(8U, Opcode::Mul).u64().Inputs(4U, 0U);
547         }
548         BASIC_BLOCK(6U, -1L)
549         {
550             INST(9U, Opcode::Phi).u64().Inputs({{2U, 0U}, {4U, 7U}, {5U, 8U}});
551             INST(10U, Opcode::Return).u64().Inputs(9U);
552         }
553     }
554 
555     GetGraph()->RunPass<IfConversion>();
556 
557     auto graph = CreateExpectedJointDiamondImm();
558     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
559 }
560 
CreateExpectedJointDiamond()561 Graph *IfConversionTest::CreateExpectedJointDiamond()
562 {
563     auto graph = CreateEmptyGraph();
564     GRAPH(graph)
565     {
566         PARAMETER(0U, 0U).u64();
567         PARAMETER(1U, 1U).u64();
568         BASIC_BLOCK(2U, 3U, 6U)
569         {
570             INST(2U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0U, 1U);
571         }
572         BASIC_BLOCK(3U, 6U)
573         {
574             INST(3U, Opcode::Mul).u64().Inputs(0U, 0U);
575             INST(5U, Opcode::Mul).u64().Inputs(3U, 1U);
576             INST(6U, Opcode::Mul).u64().Inputs(3U, 0U);
577             INST(4U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_GT).Inputs(5U, 6U, 3U, 1U);
578         }
579         BASIC_BLOCK(6U, -1L)
580         {
581             INST(7U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 4U}});
582             INST(8U, Opcode::Return).u64().Inputs(7U);
583         }
584     }
585     return graph;
586 }
587 
TEST_F(IfConversionTest,JointDiamond)588 TEST_F(IfConversionTest, JointDiamond)
589 {
590     GRAPH(GetGraph())
591     {
592         PARAMETER(0U, 0U).u64();
593         PARAMETER(1U, 1U).u64();
594         BASIC_BLOCK(2U, 3U, 6U)
595         {
596             INST(2U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0U, 1U);
597         }
598         BASIC_BLOCK(3U, 4U, 5U)
599         {
600             INST(3U, Opcode::Mul).u64().Inputs(0U, 0U);
601             INST(4U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(3U, 1U);
602         }
603         BASIC_BLOCK(4U, 6U)
604         {
605             INST(5U, Opcode::Mul).u64().Inputs(3U, 1U);
606         }
607         BASIC_BLOCK(5U, 6U)
608         {
609             INST(6U, Opcode::Mul).u64().Inputs(3U, 0U);
610         }
611         BASIC_BLOCK(6U, -1L)
612         {
613             INST(7U, Opcode::Phi).u64().Inputs({{2U, 0U}, {4U, 5U}, {5U, 6U}});
614             INST(8U, Opcode::Return).u64().Inputs(7U);
615         }
616     }
617 
618     GetGraph()->RunPass<IfConversion>();
619 
620     auto graph = CreateExpectedJointDiamond();
621     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
622 }
623 
CreateExpJointDiamondWithDroppedSelect()624 Graph *IfConversionTest::CreateExpJointDiamondWithDroppedSelect()
625 {
626     auto graph = CreateEmptyGraph();
627     GRAPH(graph)
628     {
629         PARAMETER(0U, 0U).u64();
630         PARAMETER(1U, 1U).u64();
631         BASIC_BLOCK(2U, 3U, 6U)
632         {
633             INST(2U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0U, 1U);
634         }
635         BASIC_BLOCK(3U, 6U)
636         {
637             INST(3U, Opcode::Mul).u64().Inputs(0U, 0U);
638             INST(5U, Opcode::Mul).u64().Inputs(3U, 1U);
639             INST(6U, Opcode::Mul).u64().Inputs(3U, 0U);
640             INST(4U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_GT).Inputs(5U, 6U, 3U, 1U);
641             // Second Select not needed
642         }
643         BASIC_BLOCK(6U, -1L)
644         {
645             INST(7U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 4U}});
646             INST(8U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 3U}});
647             INST(9U, Opcode::Add).u64().Inputs(7U, 8U);
648             INST(10U, Opcode::Return).u64().Inputs(9U);
649         }
650     }
651     return graph;
652 }
653 
TEST_F(IfConversionTest,JointDiamondWithDroppedSelect)654 TEST_F(IfConversionTest, JointDiamondWithDroppedSelect)
655 {
656     GRAPH(GetGraph())
657     {
658         PARAMETER(0U, 0U).u64();
659         PARAMETER(1U, 1U).u64();
660         BASIC_BLOCK(2U, 3U, 6U)
661         {
662             INST(2U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0U, 1U);
663         }
664         BASIC_BLOCK(3U, 4U, 5U)
665         {
666             INST(3U, Opcode::Mul).u64().Inputs(0U, 0U);
667             INST(4U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(3U, 1U);
668         }
669         BASIC_BLOCK(4U, 6U)
670         {
671             INST(5U, Opcode::Mul).u64().Inputs(3U, 1U);
672         }
673         BASIC_BLOCK(5U, 6U)
674         {
675             INST(6U, Opcode::Mul).u64().Inputs(3U, 0U);
676         }
677         BASIC_BLOCK(6U, -1L)
678         {
679             INST(7U, Opcode::Phi).u64().Inputs({{2U, 0U}, {4U, 5U}, {5U, 6U}});
680             INST(8U, Opcode::Phi).u64().Inputs({{2U, 0U}, {4U, 3U}, {5U, 3U}});
681             INST(9U, Opcode::Add).u64().Inputs(7U, 8U);
682             INST(10U, Opcode::Return).u64().Inputs(9U);
683         }
684     }
685 
686     GetGraph()->RunPass<IfConversion>();
687 
688     auto graph = CreateExpJointDiamondWithDroppedSelect();
689     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
690 }
691 
TEST_F(IfConversionTest,JointDiamondRunTwice)692 TEST_F(IfConversionTest, JointDiamondRunTwice)
693 {
694     GRAPH(GetGraph())
695     {
696         PARAMETER(0U, 0U).u64();
697         PARAMETER(1U, 1U).u64();
698         BASIC_BLOCK(2U, 3U, 6U)
699         {
700             INST(2U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0U, 1U);
701         }
702         BASIC_BLOCK(3U, 4U, 5U)
703         {
704             INST(3U, Opcode::Mul).u64().Inputs(0U, 0U);
705             INST(4U, Opcode::Mul).u64().Inputs(1U, 1U);
706             INST(5U, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(4U, 1U);
707         }
708         BASIC_BLOCK(4U, 6U) {}
709         BASIC_BLOCK(5U, 6U) {}
710         BASIC_BLOCK(6U, -1L)
711         {
712             INST(6U, Opcode::Phi).u64().Inputs({{2U, 0U}, {4U, 3U}, {5U, 3U}});
713             INST(7U, Opcode::Return).u64().Inputs(6U);
714         }
715     }
716 
717     ASSERT_TRUE(GetGraph()->RunPass<IfConversion>());
718     ASSERT_TRUE(GetGraph()->RunPass<Cleanup>());
719 
720     auto graph = CreateEmptyGraph();
721     GRAPH(graph)
722     {
723         PARAMETER(0U, 0U).u64();
724         PARAMETER(1U, 1U).u64();
725         BASIC_BLOCK(2U, -1L)
726         {
727             INST(3U, Opcode::Mul).u64().Inputs(0U, 0U);
728             INST(2U, Opcode::Select).u64().SrcType(DataType::UINT64).CC(CC_GE).Inputs(3U, 0U, 0U, 1U);
729             INST(7U, Opcode::Return).u64().Inputs(2U);
730         }
731     }
732     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
733 }
734 
735 /*
736  *  No conversion allowed cases below.
737  */
TEST_F(IfConversionTest,TriangleWithCall)738 TEST_F(IfConversionTest, TriangleWithCall)
739 {
740     GRAPH(GetGraph())
741     {
742         PARAMETER(0U, 0U).u64();
743         CONSTANT(1U, 10U);
744         CONSTANT(2U, 2U);
745         BASIC_BLOCK(2U, 3U, 4U)
746         {
747             INST(3U, Opcode::Compare).b().Inputs(0U, 1U);
748             INST(4U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(3U);
749         }
750         BASIC_BLOCK(3U, 4U)
751         {
752             INST(20U, Opcode::SaveState).NoVregs();
753             INST(5U, Opcode::CallStatic).u64().InputsAutoType(0U, 2U, 20U);
754         }
755         BASIC_BLOCK(4U, -1L)
756         {
757             INST(6U, Opcode::Phi).u64().Inputs({{2U, 0U}, {3U, 5U}});
758             INST(7U, Opcode::Return).u64().Inputs(6U);
759         }
760     }
761 
762     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
763 }
764 
TEST_F(IfConversionTest,DiamondThreeOperations)765 TEST_F(IfConversionTest, DiamondThreeOperations)
766 {
767     GRAPH(GetGraph())
768     {
769         PARAMETER(0U, 0U).u32();
770         PARAMETER(1U, 1U).u32();
771         CONSTANT(2U, 42U);
772         CONSTANT(3U, 0U);
773         BASIC_BLOCK(2U, 3U, 4U)
774         {
775             INST(4U, Opcode::Compare).b().Inputs(1U, 3U);
776             INST(5U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(4U);
777         }
778         BASIC_BLOCK(4U, 5U)
779         {
780             INST(6U, Opcode::Add).u32().Inputs(0U, 1U);
781         }
782         BASIC_BLOCK(3U, 5U)
783         {
784             INST(7U, Opcode::Add).u32().Inputs(0U, 2U);
785             INST(8U, Opcode::Sub).u32().Inputs(7U, 1U);
786         }
787         BASIC_BLOCK(5U, -1L)
788         {
789             INST(9U, Opcode::Phi).u32().Inputs({{4U, 6U}, {3U, 8U}});
790             INST(10U, Opcode::Return).u32().Inputs(9U);
791         }
792     }
793 
794     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
795 }
796 
TEST_F(IfConversionTest,DiamondThreePhis)797 TEST_F(IfConversionTest, DiamondThreePhis)
798 {
799     GRAPH(GetGraph())
800     {
801         PARAMETER(0U, 0U).u32();
802         PARAMETER(1U, 1U).u32();
803         CONSTANT(2U, 42U);
804         CONSTANT(3U, 0U);
805         BASIC_BLOCK(2U, 3U, 4U)
806         {
807             INST(6U, Opcode::Add).u32().Inputs(0U, 1U);
808             INST(7U, Opcode::Add).u32().Inputs(0U, 2U);
809             INST(8U, Opcode::Sub).u32().Inputs(7U, 1U);
810             INST(4U, Opcode::Compare).b().Inputs(1U, 3U);
811             INST(5U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(4U);
812         }
813         BASIC_BLOCK(4U, 5U) {}
814         BASIC_BLOCK(3U, 5U) {}
815         BASIC_BLOCK(5U, -1L)
816         {
817             INST(9U, Opcode::Phi).u32().Inputs({{4U, 6U}, {3U, 8U}});
818             INST(10U, Opcode::Phi).u32().Inputs({{4U, 6U}, {3U, 7U}});
819             INST(11U, Opcode::Phi).u32().Inputs({{4U, 7U}, {3U, 8U}});
820             INST(12U, Opcode::Add).u32().Inputs(9U, 10U);
821             INST(13U, Opcode::Add).u32().Inputs(11U, 12U);
822             INST(14U, Opcode::Return).u32().Inputs(13U);
823         }
824     }
825 
826     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
827 }
828 
TEST_F(IfConversionTest,TriangleFloat)829 TEST_F(IfConversionTest, TriangleFloat)
830 {
831     GRAPH(GetGraph())
832     {
833         PARAMETER(0U, 0U).f64();
834         PARAMETER(1U, 1U).f64();
835         PARAMETER(2U, 2U).f64();
836         BASIC_BLOCK(2U, 3U, 4U)
837         {
838             INST(3U, Opcode::Cmp).s32().SrcType(DataType::FLOAT64).Inputs(0U, 1U);
839             INST(4U, Opcode::IfImm).SrcType(DataType::INT32).CC(CC_NE).Imm(0U).Inputs(3U);
840         }
841         BASIC_BLOCK(3U, 4U)
842         {
843             INST(5U, Opcode::Mul).f64().Inputs(0U, 2U);
844         }
845         BASIC_BLOCK(4U, -1L)
846         {
847             INST(6U, Opcode::Phi).f64().Inputs({{2U, 0U}, {3U, 5U}});
848             INST(7U, Opcode::Return).f64().Inputs(6U);
849         }
850     }
851 
852     ASSERT_EQ(GetGraph()->RunPass<IfConversion>(), GetGraph()->GetEncoder()->CanEncodeFloatSelect());
853 }
854 
TEST_F(IfConversionTest,TrianglePhiFloat)855 TEST_F(IfConversionTest, TrianglePhiFloat)
856 {
857     GRAPH(GetGraph())
858     {
859         PARAMETER(0U, 0U).f64();
860         PARAMETER(1U, 1U).f64();
861         PARAMETER(2U, 2U).f64();
862         BASIC_BLOCK(2U, 3U, 4U)
863         {
864             INST(5U, Opcode::Mul).f64().Inputs(0U, 2U);
865             INST(3U, Opcode::Cmp).s32().SrcType(DataType::FLOAT64).Inputs(0U, 1U);
866             INST(4U, Opcode::IfImm).SrcType(DataType::INT32).CC(CC_NE).Imm(0U).Inputs(3U);
867         }
868         BASIC_BLOCK(3U, 4U) {}  // Instructions 5 moved up manually
869         BASIC_BLOCK(4U, -1L)
870         {
871             INST(6U, Opcode::Phi).f64().Inputs({{2U, 0U}, {3U, 5U}});
872             INST(7U, Opcode::Return).f64().Inputs(6U);
873         }
874     }
875 
876     ASSERT_EQ(GetGraph()->RunPass<IfConversion>(), GetGraph()->GetEncoder()->CanEncodeFloatSelect());
877 }
878 
TEST_F(IfConversionTest,LoopInvariantPreventTriangle)879 TEST_F(IfConversionTest, LoopInvariantPreventTriangle)
880 {
881     GRAPH(GetGraph())
882     {
883         PARAMETER(1U, 1U).ptr();
884         CONSTANT(3U, 0x64U).i64();
885         CONSTANT(4U, 0U).i64();
886         CONSTANT(5U, 1U).i64();
887         CONSTANT(30U, 2U).i64();
888 
889         BASIC_BLOCK(30U, 2U, 7U)
890         {
891             INST(8U, Opcode::Load).b().Inputs(1U, 4U);
892             INST(11U, Opcode::Load).b().Inputs(1U, 5U);
893             INST(32U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(8U);
894         }
895 
896         BASIC_BLOCK(7U, 15U, 2U)
897         {
898             INST(34U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(11U);
899         }
900 
901         BASIC_BLOCK(15U, 2U) {}
902 
903         BASIC_BLOCK(2U, 20U, 4U)
904         {
905             INST(41U, Opcode::Phi).b().Inputs(5U, 5U, 4U);
906             INST(23U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(8U);
907         }
908 
909         BASIC_BLOCK(4U, 20U, 18U)
910         {
911             INST(25U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(11U);
912         }
913 
914         BASIC_BLOCK(18U, 20U) {}
915 
916         BASIC_BLOCK(20U, 16U)
917         {
918             INST(43U, Opcode::Phi).b().Inputs(5U, 5U, 4U);
919         }
920 
921         BASIC_BLOCK(16U, 3U, 5U)
922         {
923             INST(13U, Opcode::Phi).i32().Inputs(4U, 53U);
924             INST(14U, Opcode::Phi).i32().Inputs(5U, 37U);
925             INST(44U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(43U);
926         }
927 
928         BASIC_BLOCK(5U, 3U)
929         {
930             INST(26U, Opcode::Add).i32().Inputs(13U, 14U);
931         }
932 
933         BASIC_BLOCK(3U, 6U, 8U)
934         {
935             INST(27U, Opcode::Phi).i32().Inputs(14U, 26U);
936             INST(52U, Opcode::AddI).i32().Imm(2U).Inputs(27U);
937             INST(29U, Opcode::Add).i32().Inputs(27U, 30U);
938             INST(42U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(41U);
939         }
940 
941         BASIC_BLOCK(6U, 8U)
942         {
943             INST(36U, Opcode::Sub).i32().Inputs(52U, 13U);
944         }
945 
946         BASIC_BLOCK(8U, 31U, 16U)
947         {
948             INST(37U, Opcode::Phi).i32().Inputs(52U, 36U);
949             INST(53U, Opcode::AddI).i32().Imm(1U).Inputs(13U);
950             INST(39U, Opcode::Add).i32().Inputs(13U, 5U);
951             INST(21U, Opcode::IfImm).SrcType(DataType::INT32).CC(CC_GE).Imm(0x64U).Inputs(53U);
952         }
953 
954         BASIC_BLOCK(31U, -1L)
955         {
956             INST(40U, Opcode::Return).i32().Inputs(37U);
957         }
958     }
959     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
960 }
961 
TEST_F(IfConversionTest,LoopInvariantPreventDiamond)962 TEST_F(IfConversionTest, LoopInvariantPreventDiamond)
963 {
964     GRAPH(GetGraph())
965     {
966         PARAMETER(1U, 1U).ptr();
967         CONSTANT(3U, 0x64U).i64();
968         CONSTANT(4U, 0U).i64();
969         CONSTANT(5U, 1U).i64();
970         CONSTANT(30U, 2U).i64();
971 
972         BASIC_BLOCK(30U, 2U, 7U)
973         {
974             INST(8U, Opcode::Load).b().Inputs(1U, 4U);
975             INST(11U, Opcode::Load).b().Inputs(1U, 5U);
976             INST(32U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(8U);
977         }
978 
979         BASIC_BLOCK(7U, 15U, 2U)
980         {
981             INST(34U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(11U);
982         }
983 
984         BASIC_BLOCK(15U, 2U) {}
985 
986         BASIC_BLOCK(2U, 20U, 4U)
987         {
988             INST(41U, Opcode::Phi).b().Inputs(5U, 5U, 4U);
989             INST(23U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(8U);
990         }
991 
992         BASIC_BLOCK(4U, 20U, 18U)
993         {
994             INST(25U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(11U);
995         }
996 
997         BASIC_BLOCK(18U, 20U) {}
998 
999         BASIC_BLOCK(20U, 16U)
1000         {
1001             INST(43U, Opcode::Phi).b().Inputs(5U, 5U, 4U);
1002         }
1003 
1004         BASIC_BLOCK(16U, 32U, 5U)
1005         {
1006             INST(13U, Opcode::Phi).i32().Inputs(4U, 53U);
1007             INST(14U, Opcode::Phi).i32().Inputs(5U, 37U);
1008             INST(44U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(43U);
1009         }
1010 
1011         BASIC_BLOCK(5U, 3U)
1012         {
1013             INST(26U, Opcode::Add).i32().Inputs(13U, 14U);
1014         }
1015 
1016         BASIC_BLOCK(32U, 3U)
1017         {
1018             INST(126U, Opcode::Sub).i32().Inputs(13U, 14U);
1019         }
1020 
1021         BASIC_BLOCK(3U, 6U, 33U)
1022         {
1023             INST(27U, Opcode::Phi).i32().Inputs(26U, 126U);
1024             INST(52U, Opcode::AddI).i32().Imm(2U).Inputs(27U);
1025             INST(29U, Opcode::Add).i32().Inputs(27U, 30U);
1026             INST(42U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0U).Inputs(41U);
1027         }
1028 
1029         BASIC_BLOCK(6U, 8U)
1030         {
1031             INST(36U, Opcode::Sub).i32().Inputs(52U, 13U);
1032         }
1033 
1034         BASIC_BLOCK(33U, 8U)
1035         {
1036             INST(136U, Opcode::Sub).i32().Inputs(13U, 52U);
1037         }
1038 
1039         BASIC_BLOCK(8U, 31U, 16U)
1040         {
1041             INST(37U, Opcode::Phi).i32().Inputs(36U, 136U);
1042             INST(53U, Opcode::AddI).i32().Imm(1U).Inputs(13U);
1043             INST(39U, Opcode::Add).i32().Inputs(13U, 5U);
1044             INST(21U, Opcode::IfImm).SrcType(DataType::INT32).CC(CC_GE).Imm(0x64U).Inputs(53U);
1045         }
1046 
1047         BASIC_BLOCK(31U, -1L)
1048         {
1049             INST(40U, Opcode::Return).i32().Inputs(37U);
1050         }
1051     }
1052     ASSERT_FALSE(GetGraph()->RunPass<IfConversion>());
1053 }
1054 
TEST_F(IfConversionTest,NonLoopInvariantNotPreventConversion)1055 TEST_F(IfConversionTest, NonLoopInvariantNotPreventConversion)
1056 {
1057     GRAPH(GetGraph())
1058     {
1059         PARAMETER(1U, 1U).ptr();
1060         PARAMETER(2U, 2U).i64();
1061         PARAMETER(3U, 3U).i64();
1062         CONSTANT(12U, 1U).i64();
1063         CONSTANT(13U, 0U).i64();
1064         CONSTANT(80U, 10U).i64();
1065 
1066         BASIC_BLOCK(6U, 31U, 5U)
1067         {
1068             INST(16U, Opcode::Phi).i32().Inputs(12U, 62U);
1069             INST(21U, Opcode::Load).i32().Inputs(1U, 12U);
1070             INST(22U, Opcode::Compare).b().SrcType(DataType::INT32).CC(CC_LE).Inputs(21U, 16U);
1071             INST(23U, Opcode::IfImm).SrcType(DataType::BOOL).Imm(0U).Inputs(22U);
1072         }
1073 
1074         BASIC_BLOCK(5U, 3U, 4U)
1075         {
1076             INST(28U, Opcode::Phi).i64().Inputs(13U, 49U);
1077             INST(37U, Opcode::Load).b().Inputs(1U, 13U);
1078             INST(39U, Opcode::IfImm).SrcType(DataType::BOOL).Imm(0U).Inputs(37U);
1079         }
1080 
1081         BASIC_BLOCK(4U, 21U, 20U)
1082         {
1083             INST(93U, Opcode::Load).i32().Inputs(1U, 2U);
1084             INST(94U, Opcode::Compare).b().SrcType(DataType::INT32).Inputs(93U, 80U);
1085             INST(95U, Opcode::IfImm).SrcType(DataType::BOOL).Imm(0U).Inputs(94U);
1086         }
1087 
1088         BASIC_BLOCK(20U, 21U) {}
1089 
1090         BASIC_BLOCK(21U, 22U, 23U)
1091         {
1092             INST(96U, Opcode::Phi).i32().Inputs(12U, 13U);
1093             INST(99U, Opcode::Load).i32().Inputs(1U, 3U);
1094             INST(101U, Opcode::If).SrcType(DataType::INT32).CC(CC_NE).Inputs(80U, 99U);
1095         }
1096 
1097         BASIC_BLOCK(23U, 22U) {}
1098 
1099         BASIC_BLOCK(22U, 18U, 25U)
1100         {
1101             INST(102U, Opcode::Phi).i32().Inputs(12U, 13U);
1102             INST(103U, Opcode::And).i32().Inputs(102U, 96U);
1103             INST(104U, Opcode::Compare).b().SrcType(DataType::INT32).Inputs(103U, 13U);
1104             INST(105U, Opcode::If).SrcType(DataType::INT32).CC(CC_NE).Inputs(13U, 103U);
1105         }
1106 
1107         BASIC_BLOCK(25U, -1L)
1108         {
1109             INST(106U, Opcode::SaveState).Inputs(102U, 96U).SrcVregs({0U, 1U});
1110             INST(107U, Opcode::LoadAndInitClass).ref().Inputs(106U);
1111             INST(108U, Opcode::NewObject).ref().Inputs(107U, 106U);
1112             INST(109U, Opcode::SaveState).Inputs(108U).SrcVregs({0U});
1113             INST(113U, Opcode::Throw).Inputs(108U, 109U);
1114         }
1115 
1116         BASIC_BLOCK(18U, 5U)
1117         {
1118             INST(49U, Opcode::Add).i64().Inputs(28U, 12U);
1119         }
1120 
1121         BASIC_BLOCK(3U, 6U)
1122         {
1123             INST(62U, Opcode::Add).i32().Inputs(16U, 12U);
1124         }
1125 
1126         BASIC_BLOCK(31U, -1L)
1127         {
1128             INST(58U, Opcode::Return).i32().Inputs(21U);
1129         }
1130     }
1131     ASSERT_TRUE(GetGraph()->RunPass<IfConversion>());
1132     auto graph = CreateEmptyGraph();
1133     GRAPH(graph)
1134     {
1135         PARAMETER(1U, 1U).ptr();
1136         PARAMETER(2U, 2U).i64();
1137         PARAMETER(3U, 3U).i64();
1138         CONSTANT(12U, 1U).i64();
1139         CONSTANT(13U, 0U).i64();
1140         CONSTANT(80U, 10U).i64();
1141 
1142         BASIC_BLOCK(42U, 6U) {}
1143 
1144         BASIC_BLOCK(6U, 31U, 5U)
1145         {
1146             INST(16U, Opcode::Phi).i32().Inputs(12U, 62U);
1147             INST(21U, Opcode::Load).i32().Inputs(1U, 12U);
1148             INST(22U, Opcode::Compare).b().SrcType(DataType::INT32).CC(CC_LE).Inputs(21U, 16U);
1149             INST(23U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(22U);
1150         }
1151 
1152         BASIC_BLOCK(5U, 3U, 4U)
1153         {
1154             INST(28U, Opcode::Phi).i64().Inputs(13U, 49U);
1155             INST(37U, Opcode::Load).b().Inputs(1U, 13U);
1156             INST(39U, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(37U);
1157         }
1158 
1159         BASIC_BLOCK(4U, 18U, 25U)
1160         {
1161             INST(93U, Opcode::Load).i32().Inputs(1U, 2U);
1162             INST(94U, Opcode::Compare).b().SrcType(DataType::INT32).CC(CC_EQ).Inputs(93U, 80U);
1163             INST(115U, Opcode::SelectImm).i32().SrcType(DataType::BOOL).CC(CC_EQ).Imm(0U).Inputs(12U, 13U, 94U);
1164             INST(99U, Opcode::Load).i32().Inputs(1U, 3U);
1165             INST(114U, Opcode::Select).i32().SrcType(DataType::INT32).CC(CC_NE).Inputs(12U, 13U, 80U, 99U);
1166             INST(103U, Opcode::And).i32().Inputs(114U, 115U);
1167             INST(104U, Opcode::Compare).b().SrcType(DataType::INT32).CC(CC_EQ).Inputs(103U, 13U);
1168             INST(105U, Opcode::If).SrcType(DataType::INT32).CC(CC_NE).Inputs(13U, 103U);
1169         }
1170 
1171         BASIC_BLOCK(25U, -1L)
1172         {
1173             INST(106U, Opcode::SaveState).Inputs(114U, 115U).SrcVregs({0U, 1U});
1174             INST(107U, Opcode::LoadAndInitClass).ref().Inputs(106U);
1175             INST(108U, Opcode::NewObject).ref().Inputs(107U, 106U);
1176             INST(109U, Opcode::SaveState).Inputs(108U).SrcVregs({0U});
1177             INST(113U, Opcode::Throw).Inputs(108U, 109U);
1178         }
1179 
1180         BASIC_BLOCK(18U, 5U)
1181         {
1182             INST(49U, Opcode::Add).i64().Inputs(28U, 12U);
1183         }
1184 
1185         BASIC_BLOCK(3U, 6U)
1186         {
1187             INST(62U, Opcode::Add).i32().Inputs(16U, 12U);
1188         }
1189 
1190         BASIC_BLOCK(31U, -1L)
1191         {
1192             INST(58U, Opcode::Return).i32().Inputs(21U);
1193         }
1194     }
1195     ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph));
1196 }
1197 // NOLINTEND(readability-magic-numbers)
1198 
1199 }  // namespace ark::compiler
1200