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