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