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