1/** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "unit_test.h" 17 18#include "optimizer/optimizations/cleanup.h" 19 20namespace panda::compiler { 21class CleanupTest : public GraphTest { 22}; 23 24TEST_F(CleanupTest, Simple) 25{ 26 GRAPH(GetGraph()) 27 { 28 BASIC_BLOCK(2, 3) {} 29 BASIC_BLOCK(3, -1) 30 { 31 INST(0, Opcode::ReturnVoid); 32 } 33 } 34 35 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 36 37 auto graph = CreateEmptyGraph(); 38 GRAPH(graph) 39 { 40 BASIC_BLOCK(3, -1) 41 { 42 INST(0, Opcode::ReturnVoid); 43 } 44 } 45 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 46} 47 48TEST_F(CleanupTest, BothHasPhi) 49{ 50 GRAPH(GetGraph()) 51 { 52 PARAMETER(0, 0).s64(); 53 PARAMETER(1, 1).s64(); 54 BASIC_BLOCK(2, 3, 6) 55 { 56 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LE).Inputs(0, 1); 57 } 58 BASIC_BLOCK(3, 4, 5) 59 { 60 INST(3, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_EQ).Inputs(0, 1); 61 } 62 BASIC_BLOCK(4, 5) 63 { 64 INST(4, Opcode::Add).s64().Inputs(0, 1); 65 } 66 BASIC_BLOCK(5, 6) 67 { 68 INST(5, Opcode::Phi).s64().Inputs({{3, 1}, {4, 4}}); 69 } 70 BASIC_BLOCK(6, -1) 71 { 72 INST(6, Opcode::Phi).s64().Inputs({{2, 0}, {5, 5}}); 73 INST(7, Opcode::Return).s64().Inputs(6); 74 } 75 } 76 77 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 78 79 auto graph = CreateEmptyGraph(); 80 GRAPH(graph) 81 { 82 PARAMETER(0, 0).s64(); 83 PARAMETER(1, 1).s64(); 84 BASIC_BLOCK(2, 3, 6) 85 { 86 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LE).Inputs(0, 1); 87 } 88 BASIC_BLOCK(3, 4, 6) 89 { 90 INST(3, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_EQ).Inputs(0, 1); 91 } 92 BASIC_BLOCK(4, 6) 93 { 94 INST(4, Opcode::Add).s64().Inputs(0, 1); 95 } 96 BASIC_BLOCK(6, -1) 97 { 98 INST(5, Opcode::Phi).s64().Inputs({{2, 0}, {3, 1}, {4, 4}}); 99 INST(6, Opcode::Return).s64().Inputs(5); 100 } 101 } 102 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 103} 104 105TEST_F(CleanupTest, HasPhi) 106{ 107 GRAPH(GetGraph()) 108 { 109 PARAMETER(0, 0).s64(); 110 PARAMETER(1, 1).s64(); 111 BASIC_BLOCK(2, 3, 4) 112 { 113 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0, 1); 114 } 115 BASIC_BLOCK(3, 4) 116 { 117 INST(3, Opcode::Add).s64().Inputs(0, 1); 118 } 119 BASIC_BLOCK(4, 5) 120 { 121 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 3}}); 122 } 123 BASIC_BLOCK(5, -1) 124 { 125 INST(6, Opcode::Return).s64().Inputs(4); 126 } 127 } 128 129 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 130 131 auto graph = CreateEmptyGraph(); 132 GRAPH(graph) 133 { 134 PARAMETER(0, 0).s64(); 135 PARAMETER(1, 1).s64(); 136 BASIC_BLOCK(2, 3, 5) 137 { 138 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0, 1); 139 } 140 BASIC_BLOCK(3, 5) 141 { 142 INST(3, Opcode::Add).s64().Inputs(0, 1); 143 } 144 BASIC_BLOCK(5, -1) 145 { 146 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 3}}); 147 INST(6, Opcode::Return).s64().Inputs(4); 148 } 149 } 150 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 151} 152 153TEST_F(CleanupTest, DeadPhi) 154{ 155 GRAPH(GetGraph()) 156 { 157 PARAMETER(0, 0).s64(); 158 PARAMETER(1, 1).s64(); 159 BASIC_BLOCK(2, 3, 6) 160 { 161 INST(2, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_NE).Inputs(0, 1); 162 } 163 BASIC_BLOCK(3, 4, 5) 164 { 165 INST(3, Opcode::If).SrcType(DataType::Type::INT64).CC(CC_LT).Inputs(0, 1); 166 } 167 BASIC_BLOCK(4, 5) {} 168 BASIC_BLOCK(5, 6) 169 { 170 INST(4, Opcode::Phi).s64().Inputs({{3, 0}, {4, 1}}); 171 } 172 BASIC_BLOCK(6, -1) 173 { 174 INST(5, Opcode::ReturnVoid); 175 } 176 } 177 178 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 179 180 auto graph = CreateEmptyGraph(); 181 GRAPH(graph) 182 { 183 BASIC_BLOCK(2, -1) 184 { 185 INST(2, Opcode::ReturnVoid); 186 } 187 } 188 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 189} 190 191TEST_F(CleanupTest, LoopPreHeader) 192{ 193 GRAPH(GetGraph()) 194 { 195 PARAMETER(0, 0).s64(); 196 PARAMETER(1, 1).s64(); 197 BASIC_BLOCK(2, 3) {} 198 BASIC_BLOCK(3, 3, -1) 199 { 200 INST(3, Opcode::Neg).s64().Inputs(0); 201 INST(5, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 3); 202 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5); 203 } 204 } 205 206 ASSERT_EQ(&BB(2), BB(3).GetLoop()->GetPreHeader()); 207 ASSERT_EQ(1U, BB(3).GetLoop()->GetBlocks().size()); 208 ASSERT_EQ(3U, BB(3).GetLoop()->GetOuterLoop()->GetBlocks().size()); 209 210 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 211 212 auto graph = CreateEmptyGraph(); 213 GRAPH(graph) 214 { 215 PARAMETER(0, 0).s64(); 216 PARAMETER(1, 1).s64(); 217 BASIC_BLOCK(2, 3) {} 218 BASIC_BLOCK(3, 3, -1) 219 { 220 INST(3, Opcode::Neg).s64().Inputs(0); 221 INST(5, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 3); 222 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5); 223 } 224 } 225 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 226} 227 228TEST_F(CleanupTest, TwoPredecessors) 229{ 230 GRAPH(GetGraph()) 231 { 232 PARAMETER(0, 0).s64(); 233 PARAMETER(1, 1).s64(); 234 BASIC_BLOCK(2, 3, 4) 235 { 236 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 237 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 238 } 239 BASIC_BLOCK(3, 5) 240 { 241 INST(20, Opcode::SaveState).NoVregs(); 242 INST(4, Opcode::CallStatic).v0id().InputsAutoType(20); 243 } 244 BASIC_BLOCK(4, 5) 245 { 246 INST(21, Opcode::SaveState).NoVregs(); 247 INST(5, Opcode::CallStatic).v0id().InputsAutoType(21); 248 } 249 BASIC_BLOCK(5, 6) {} 250 BASIC_BLOCK(6, -1) 251 { 252 INST(6, Opcode::ReturnVoid); 253 } 254 } 255 256 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 257 258 auto graph = CreateEmptyGraph(); 259 GRAPH(graph) 260 { 261 PARAMETER(0, 0).s64(); 262 PARAMETER(1, 1).s64(); 263 BASIC_BLOCK(2, 3, 4) 264 { 265 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 266 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 267 } 268 BASIC_BLOCK(3, 6) 269 { 270 INST(20, Opcode::SaveState).NoVregs(); 271 INST(4, Opcode::CallStatic).v0id().InputsAutoType(20); 272 } 273 BASIC_BLOCK(4, 6) 274 { 275 INST(21, Opcode::SaveState).NoVregs(); 276 INST(5, Opcode::CallStatic).v0id().InputsAutoType(21); 277 } 278 BASIC_BLOCK(6, -1) 279 { 280 INST(6, Opcode::ReturnVoid); 281 } 282 } 283 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 284} 285 286TEST_F(CleanupTest, TwoPredecessorsPhi) 287{ 288 GRAPH(GetGraph()) 289 { 290 PARAMETER(0, 0).s64(); 291 PARAMETER(1, 1).s64(); 292 BASIC_BLOCK(2, 3, 7) 293 { 294 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 295 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 296 } 297 BASIC_BLOCK(3, 4, 5) 298 { 299 INST(4, Opcode::Add).s64().Inputs(0, 1); 300 INST(5, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 301 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5); 302 } 303 BASIC_BLOCK(4, 6) 304 { 305 INST(20, Opcode::SaveState).NoVregs(); 306 INST(7, Opcode::CallStatic).v0id().InputsAutoType(20); 307 } 308 BASIC_BLOCK(5, 6) 309 { 310 INST(21, Opcode::SaveState).NoVregs(); 311 INST(8, Opcode::CallStatic).v0id().InputsAutoType(21); 312 } 313 BASIC_BLOCK(6, 7) {} 314 BASIC_BLOCK(7, -1) 315 { 316 INST(9, Opcode::Phi).s64().Inputs({{2, 1}, {6, 4}}); 317 INST(10, Opcode::Return).s64().Inputs(9); 318 } 319 } 320 321 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 322 323 auto graph = CreateEmptyGraph(); 324 GRAPH(graph) 325 { 326 PARAMETER(0, 0).s64(); 327 PARAMETER(1, 1).s64(); 328 BASIC_BLOCK(2, 3, 7) 329 { 330 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 331 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 332 } 333 BASIC_BLOCK(3, 4, 5) 334 { 335 INST(4, Opcode::Add).s64().Inputs(0, 1); 336 INST(5, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 337 INST(6, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(5); 338 } 339 BASIC_BLOCK(4, 7) 340 { 341 INST(20, Opcode::SaveState).NoVregs(); 342 INST(7, Opcode::CallStatic).v0id().InputsAutoType(20); 343 } 344 BASIC_BLOCK(5, 7) 345 { 346 INST(21, Opcode::SaveState).NoVregs(); 347 INST(8, Opcode::CallStatic).v0id().InputsAutoType(21); 348 } 349 BASIC_BLOCK(7, -1) 350 { 351 INST(9, Opcode::Phi).s64().Inputs({{2, 1}, {4, 4}, {5, 4}}); 352 INST(10, Opcode::Return).s64().Inputs(9); 353 } 354 } 355 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 356} 357 358TEST_F(CleanupTest, TriangleNoPhi) 359{ 360 GRAPH(GetGraph()) 361 { 362 PARAMETER(0, 0).s64(); 363 PARAMETER(1, 1).s64(); 364 BASIC_BLOCK(2, 3, 4) 365 { 366 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 367 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 368 } 369 BASIC_BLOCK(3, 4) {} 370 BASIC_BLOCK(4, -1) 371 { 372 INST(4, Opcode::ReturnVoid); 373 } 374 } 375 376 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 377 378 auto graph = CreateEmptyGraph(); 379 GRAPH(graph) 380 { 381 BASIC_BLOCK(4, -1) 382 { 383 INST(4, Opcode::ReturnVoid); 384 } 385 } 386 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 387} 388 389TEST_F(CleanupTest, DiamondSamePhi) 390{ 391 GRAPH(GetGraph()) 392 { 393 PARAMETER(0, 0).s64(); 394 PARAMETER(1, 1).s64(); 395 BASIC_BLOCK(2, 3, 4) 396 { 397 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 398 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 399 } 400 BASIC_BLOCK(3, 5) {} 401 BASIC_BLOCK(4, 5) {} 402 BASIC_BLOCK(5, -1) 403 { 404 INST(4, Opcode::Phi).s64().Inputs({{3, 1}, {4, 1}}); 405 INST(5, Opcode::Return).s64().Inputs(4); 406 } 407 } 408 409 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 410 411 auto graph = CreateEmptyGraph(); 412 GRAPH(graph) 413 { 414 PARAMETER(1, 1).s64(); 415 BASIC_BLOCK(5, -1) 416 { 417 INST(5, Opcode::Return).s64().Inputs(1); 418 } 419 } 420 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 421} 422 423TEST_F(CleanupTest, JointTriangle) 424{ 425 GRAPH(GetGraph()) 426 { 427 PARAMETER(0, 0).s64(); 428 PARAMETER(1, 1).s64(); 429 BASIC_BLOCK(2, 3, 5) 430 { 431 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 432 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 433 } 434 BASIC_BLOCK(3, 4, 5) 435 { 436 INST(4, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 437 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4); 438 } 439 BASIC_BLOCK(4, 5) {} 440 BASIC_BLOCK(5, -1) 441 { 442 INST(6, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}, {4, 0}}); 443 INST(7, Opcode::Return).s64().Inputs(6); 444 } 445 } 446 447 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 448 449 auto graph = CreateEmptyGraph(); 450 GRAPH(graph) 451 { 452 PARAMETER(0, 0).s64(); 453 PARAMETER(1, 1).s64(); 454 BASIC_BLOCK(2, 3, 5) 455 { 456 INST(2, Opcode::Compare).b().CC(CC_LE).SrcType(DataType::Type::INT64).Inputs(1, 0); 457 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 458 } 459 BASIC_BLOCK(3, 5) {} 460 BASIC_BLOCK(5, -1) 461 { 462 INST(6, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}}); 463 INST(7, Opcode::Return).s64().Inputs(6); 464 } 465 } 466 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 467} 468 469TEST_F(CleanupTest, TriangleProhibited) 470{ 471 GRAPH(GetGraph()) 472 { 473 PARAMETER(0, 0).s64(); 474 PARAMETER(1, 1).s64(); 475 BASIC_BLOCK(2, 3, 4) 476 { 477 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 478 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 479 } 480 BASIC_BLOCK(3, 4) {} 481 BASIC_BLOCK(4, -1) 482 { 483 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}}); 484 INST(5, Opcode::Return).s64().Inputs(4); 485 } 486 } 487 488 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 489 490 auto graph = CreateEmptyGraph(); 491 GRAPH(graph) 492 { 493 PARAMETER(0, 0).s64(); 494 PARAMETER(1, 1).s64(); 495 BASIC_BLOCK(2, 3, 4) 496 { 497 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 498 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 499 } 500 BASIC_BLOCK(3, 4) {} 501 BASIC_BLOCK(4, -1) 502 { 503 INST(4, Opcode::Phi).s64().Inputs({{2, 1}, {3, 0}}); 504 INST(5, Opcode::Return).s64().Inputs(4); 505 } 506 } 507 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 508} 509 510TEST_F(CleanupTest, InfiniteLoop) 511{ 512 GRAPH(GetGraph()) 513 { 514 PARAMETER(0, 0).s64(); 515 PARAMETER(1, 1).s64(); 516 BASIC_BLOCK(2, 3, 4) 517 { 518 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 519 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 520 } 521 BASIC_BLOCK(3, 3) {} 522 BASIC_BLOCK(4, -1) 523 { 524 INST(4, Opcode::ReturnVoid); 525 } 526 } 527 528 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 529 530 auto graph = CreateEmptyGraph(); 531 GRAPH(graph) 532 { 533 PARAMETER(0, 0).s64(); 534 PARAMETER(1, 1).s64(); 535 BASIC_BLOCK(2, 3, 4) 536 { 537 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 538 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 539 } 540 BASIC_BLOCK(3, 3) {} 541 BASIC_BLOCK(4, -1) 542 { 543 INST(4, Opcode::ReturnVoid); 544 } 545 } 546 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 547} 548 549TEST_F(CleanupTest, JointDiamond) 550{ 551 GRAPH(GetGraph()) 552 { 553 PARAMETER(0, 0).u64(); 554 PARAMETER(1, 1).u64(); 555 BASIC_BLOCK(2, 3, 6) 556 { 557 INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1); 558 } 559 BASIC_BLOCK(3, 4, 5) 560 { 561 INST(3, Opcode::Mul).u64().Inputs(0, 0); 562 INST(4, Opcode::Mul).u64().Inputs(1, 1); 563 INST(5, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(4, 1); 564 } 565 BASIC_BLOCK(4, 7) {} 566 BASIC_BLOCK(5, 7) {} 567 BASIC_BLOCK(6, 7) 568 { 569 INST(20, Opcode::SaveState).NoVregs(); 570 INST(6, Opcode::CallStatic).v0id().InputsAutoType(20); 571 } 572 BASIC_BLOCK(7, -1) 573 { 574 INST(7, Opcode::Phi).u64().Inputs({{6, 0}, {4, 3}, {5, 3}}); 575 INST(8, Opcode::Return).u64().Inputs(7); 576 } 577 } 578 579 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 580 581 auto graph = CreateEmptyGraph(); 582 GRAPH(graph) 583 { 584 PARAMETER(0, 0).u64(); 585 PARAMETER(1, 1).u64(); 586 BASIC_BLOCK(2, 3, 6) 587 { 588 INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GE).Inputs(0, 1); 589 } 590 BASIC_BLOCK(3, 7) 591 { 592 INST(3, Opcode::Mul).u64().Inputs(0, 0); 593 } 594 BASIC_BLOCK(6, 7) 595 { 596 INST(20, Opcode::SaveState).NoVregs(); 597 INST(6, Opcode::CallStatic).v0id().InputsAutoType(20); 598 } 599 BASIC_BLOCK(7, -1) 600 { 601 INST(7, Opcode::Phi).u64().Inputs({{6, 0}, {3, 3}}); 602 INST(8, Opcode::Return).u64().Inputs(7); 603 } 604 } 605 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 606} 607 608TEST_F(CleanupTest, JoinLoopBackEdgeWithMultiPreds) 609{ 610 GRAPH(GetGraph()) 611 { 612 PARAMETER(0, 0).u64(); 613 PARAMETER(1, 1).u64(); 614 PARAMETER(2, 2).u64(); 615 BASIC_BLOCK(2, 3, 7) 616 { 617 INST(4, Opcode::Phi).u64().Inputs(0, 9); 618 INST(5, Opcode::If).SrcType(DataType::UINT64).CC(CC_LE).Inputs(4, 1); 619 } 620 BASIC_BLOCK(3, 4, 5) 621 { 622 INST(6, Opcode::If).SrcType(DataType::UINT64).CC(CC_LE).Inputs(4, 2); 623 } 624 BASIC_BLOCK(4, 6) 625 { 626 INST(7, Opcode::Mul).u64().Inputs(4, 1); 627 } 628 BASIC_BLOCK(5, 6) 629 { 630 INST(8, Opcode::Mul).u64().Inputs(4, 2); 631 } 632 BASIC_BLOCK(6, 2) 633 { 634 INST(9, Opcode::Phi).u64().Inputs(7, 8); 635 // loop back-edge 636 } 637 BASIC_BLOCK(7, -1) 638 { 639 INST(11, Opcode::Return).u64().Inputs(4); 640 } 641 } 642 643 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 644 ASSERT_TRUE(GetGraph()->GetAnalysis<LoopAnalyzer>().IsValid()); 645 646 auto loop = BB(2).GetLoop(); 647 ASSERT_EQ(loop->GetHeader(), &BB(2)); 648 ASSERT_EQ(loop->GetBackEdges().size(), 2); 649 ASSERT_TRUE(loop->HasBackEdge(&BB(4))); 650 ASSERT_TRUE(loop->HasBackEdge(&BB(5))); 651} 652 653TEST_F(CleanupTest, DiamondBecomeEmpty) 654{ 655 GRAPH(GetGraph()) 656 { 657 PARAMETER(0, 0).b(); 658 BASIC_BLOCK(2, 3, 4) 659 { 660 INST(1, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(0); 661 } 662 BASIC_BLOCK(3, 5) {} 663 BASIC_BLOCK(4, 5) {} 664 BASIC_BLOCK(5, -1) 665 { 666 INST(2, Opcode::ReturnVoid); 667 } 668 } 669 670 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 671 672 auto graph = CreateEmptyGraph(); 673 GRAPH(graph) 674 { 675 BASIC_BLOCK(5, -1) 676 { 677 INST(2, Opcode::ReturnVoid); 678 } 679 } 680 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 681} 682 683TEST_F(CleanupTest, CarefulDCE) 684{ 685 GRAPH(GetGraph()) 686 { 687 BASIC_BLOCK(2, 3, 4) 688 { 689 INST(20, Opcode::SaveState).NoVregs(); 690 INST(0, Opcode::CallStatic).b().InputsAutoType(20); 691 INST(1, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(0); 692 } 693 BASIC_BLOCK(3, 4) {} 694 BASIC_BLOCK(4, -1) 695 { 696 INST(2, Opcode::ReturnVoid); 697 } 698 } 699 700 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 701 702 auto graph = CreateEmptyGraph(); 703 GRAPH(graph) 704 { 705 BASIC_BLOCK(2, -1) 706 { 707 INST(20, Opcode::SaveState).NoVregs(); 708 INST(0, Opcode::CallStatic).b().InputsAutoType(20); 709 INST(1, Opcode::ReturnVoid); 710 } 711 } 712 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 713} 714 715TEST_F(CleanupTest, CarefulDCE2) 716{ 717 GRAPH(GetGraph()) 718 { 719 PARAMETER(0, 0).u64(); 720 PARAMETER(1, 1).u64(); 721 BASIC_BLOCK(2, 3, 40) 722 { 723 INST(2, Opcode::If).SrcType(DataType::UINT64).CC(CC_GT).Inputs(0, 1); 724 } 725 BASIC_BLOCK(40, 5) {} 726 BASIC_BLOCK(3, 5) {} 727 BASIC_BLOCK(5, 6, 7) 728 { 729 INST(3, Opcode::Phi).u64().Inputs({{40, 0}, {3, 1}}); 730 INST(4, Opcode::IfImm).SrcType(DataType::UINT64).CC(CC_NE).Imm(0).Inputs(3); 731 } 732 BASIC_BLOCK(6, 7) {} 733 BASIC_BLOCK(7, -1) 734 { 735 INST(5, Opcode::ReturnVoid); 736 } 737 } 738 739 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 740 741 auto graph = CreateEmptyGraph(); 742 GRAPH(graph) 743 { 744 BASIC_BLOCK(2, -1) 745 { 746 INST(0, Opcode::ReturnVoid); 747 } 748 } 749 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 750} 751 752TEST_F(CleanupTest, Delete) 753{ 754 GRAPH(GetGraph()) 755 { 756 CONSTANT(0, 12); 757 CONSTANT(1, 13); 758 759 BASIC_BLOCK(2, -1) 760 { 761 INST(2, Opcode::Neg).u64().Inputs(1); 762 INST(3, Opcode::Add).u64().Inputs(0, 2); 763 INST(4, Opcode::Return).u64().Inputs(2); 764 } 765 } 766 767 // Delete Insts 0 and 3 768 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 769 770 ASSERT_TRUE(CheckInputs(INS(2), {1})); 771 ASSERT_TRUE(CheckInputs(INS(4), {2})); 772 773 ASSERT_TRUE(CheckUsers(INS(1), {2})); 774 ASSERT_TRUE(CheckUsers(INS(2), {4})); 775 ASSERT_TRUE(CheckUsers(INS(4), {})); 776} 777 778TEST_F(CleanupTest, NotRemoved) 779{ 780 GRAPH(GetGraph()) 781 { 782 CONSTANT(0, 11); 783 CONSTANT(1, 12); 784 CONSTANT(2, 13); 785 786 BASIC_BLOCK(2, -1) 787 { 788 INST(3, Opcode::Add).u64().Inputs(0, 1); 789 INST(4, Opcode::Neg).u64().Inputs(3); 790 INST(5, Opcode::Sub).u64().Inputs(4, 2); 791 INST(6, Opcode::Return).u64().Inputs(5); 792 } 793 } 794 795 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 796 797 ASSERT_TRUE(CheckInputs(INS(3), {0, 1})); 798 ASSERT_TRUE(CheckInputs(INS(4), {3})); 799 ASSERT_TRUE(CheckInputs(INS(5), {4, 2})); 800 ASSERT_TRUE(CheckInputs(INS(6), {5})); 801 802 ASSERT_TRUE(CheckUsers(INS(0), {3})); 803 ASSERT_TRUE(CheckUsers(INS(1), {3})); 804 ASSERT_TRUE(CheckUsers(INS(2), {5})); 805 ASSERT_TRUE(CheckUsers(INS(3), {4})); 806 ASSERT_TRUE(CheckUsers(INS(4), {5})); 807 ASSERT_TRUE(CheckUsers(INS(5), {6})); 808} 809 810TEST_F(CleanupTest, Loop) 811{ 812 GRAPH(GetGraph()) 813 { 814 CONSTANT(0, 0); 815 CONSTANT(1, 1); 816 BASIC_BLOCK(2, 3) 817 { 818 INST(2, Opcode::Phi).u64().Inputs(0, 5); 819 INST(3, Opcode::Phi).u64().Inputs(1, 6); 820 } 821 BASIC_BLOCK(3, 4, 5) 822 { 823 INST(4, Opcode::Add).u64().Inputs(2, 3); 824 INST(11, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 1); 825 INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11); 826 } 827 BASIC_BLOCK(4, 2) 828 { 829 INST(5, Opcode::Neg).u64().Inputs(3); 830 INST(6, Opcode::Neg).u64().Inputs(4); 831 // Must be removed 832 INST(7, Opcode::Add).u64().Inputs(5, 6); 833 } 834 BASIC_BLOCK(5, -1) 835 { 836 // Unused instruction 837 INST(8, Opcode::Neg).u64().Inputs(4); 838 INST(9, Opcode::Return).u64().Inputs(4); 839 } 840 } 841 842 // Delete Insts 7 and 8 843 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 844 845 ASSERT_TRUE(CheckInputs(INS(2), {0, 5})); 846 ASSERT_TRUE(CheckInputs(INS(3), {1, 6})); 847 ASSERT_TRUE(CheckInputs(INS(4), {2, 3})); 848 ASSERT_TRUE(CheckInputs(INS(5), {3})); 849 ASSERT_TRUE(CheckInputs(INS(6), {4})); 850 ASSERT_TRUE(CheckInputs(INS(9), {4})); 851 852 ASSERT_TRUE(CheckUsers(INS(0), {2, 11})); 853 ASSERT_TRUE(CheckUsers(INS(1), {3, 11})); 854 ASSERT_TRUE(CheckUsers(INS(2), {4})); 855 ASSERT_TRUE(CheckUsers(INS(3), {4, 5})); 856 ASSERT_TRUE(CheckUsers(INS(4), {6, 9})); 857 ASSERT_TRUE(CheckUsers(INS(5), {2})); 858 ASSERT_TRUE(CheckUsers(INS(6), {3})); 859} 860 861TEST_F(CleanupTest, Loop1) 862{ 863 GRAPH(GetGraph()) 864 { 865 CONSTANT(0, 0); 866 CONSTANT(1, 1); 867 868 BASIC_BLOCK(2, 2, 3) 869 { 870 // Unused instructions 871 INST(2, Opcode::Phi).u64().Inputs(1, 3); 872 INST(3, Opcode::Add).u64().Inputs(2, 1); 873 INST(6, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(0, 0); 874 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); 875 } 876 BASIC_BLOCK(3, -1) 877 { 878 // Unused instruction 879 INST(4, Opcode::Neg).u64().Inputs(0); 880 INST(5, Opcode::Return).u64().Inputs(4); 881 } 882 } 883 884 // Delete Insts 1, 2 and 3 885 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 886 887 ASSERT_EQ(INS(0).GetNext(), nullptr); 888 ASSERT_FALSE(BB(2).IsEmpty()); 889} 890 891/* 892 * Test Graph: 893 * [0] 894 * | 895 * v 896 * /-------[2]-------\ 897 * | | 898 * v v 899 * [3] [4] 900 * / \ / \ 901 * v \ / | 902 * [8]<---->[7] \->[5]<-/ | 903 * | | | 904 * | \--->[6]<---/ 905 * | | 906 * \---------->[9]<----/ 907 * | 908 * v 909 * [1] 910 */ 911 912TEST_F(CleanupTest, PhiInputs1) 913{ 914 GRAPH(GetGraph()) 915 { 916 CONSTANT(0, 0); 917 CONSTANT(18, 2); 918 CONSTANT(1, 1); 919 BASIC_BLOCK(2, 3, 4) 920 { 921 INST(2, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1); 922 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 923 } 924 BASIC_BLOCK(3, 7, 5) 925 { 926 INST(4, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1); 927 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4); 928 } 929 BASIC_BLOCK(4, 5, 6) 930 { 931 INST(6, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1); 932 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); 933 } 934 935 BASIC_BLOCK(5, 6) 936 { 937 INST(8, Opcode::Phi).u64().Inputs({{4, 0}, {3, 0}}); 938 } 939 BASIC_BLOCK(6, 9) 940 { 941 INST(10, Opcode::Phi).u64().Inputs({{4, 0}, {5, 8}}); 942 } 943 BASIC_BLOCK(7, 8, 9) 944 { 945 INST(12, Opcode::Phi).u64().Inputs({{8, 12}, {3, 0}}); 946 INST(13, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(18, 1); 947 INST(14, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(13); 948 } 949 BASIC_BLOCK(8, 7) {} 950 BASIC_BLOCK(9, -1) 951 { 952 INST(16, Opcode::Phi).u64().Inputs({{6, 10}, {7, 12}}); 953 INST(17, Opcode::Return).u64().Inputs(16); 954 } 955 } 956 957 // Delete all phi instructions 958 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 959 960 ASSERT_TRUE(CheckInputs(INS(17), {0})); 961 ASSERT_TRUE(CheckUsers(INS(0), {17})); 962} 963 964/* 965 * Test Graph: 966 * [0] 967 * | 968 * v 969 * /---------[2]---------\ 970 * | | 971 * v v 972 * [3] [4] 973 * | | 974 * \-------->[5]<--------/ 975 * | 976 * |->[6]<----\ 977 * | | | 978 * | v | 979 * \->[7]-----/ 980 * | 981 * v 982 * [8] 983 * | 984 * v 985 * [1] 986 */ 987 988TEST_F(CleanupTest, PhiInputs2) 989{ 990 GRAPH(GetGraph()) 991 { 992 CONSTANT(0, 0); 993 CONSTANT(1, 1); 994 CONSTANT(6, 2); 995 CONSTANT(7, 3); 996 BASIC_BLOCK(2, 3, 4) 997 { 998 INST(8, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7); 999 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8); 1000 } 1001 BASIC_BLOCK(3, 5) {} 1002 BASIC_BLOCK(4, 5) {} 1003 BASIC_BLOCK(5, 6, 7) 1004 { 1005 INST(2, Opcode::Phi).u64().Inputs(0, 1); 1006 INST(12, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7); 1007 INST(13, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(12); 1008 } 1009 BASIC_BLOCK(6, 7) 1010 { 1011 INST(3, Opcode::Phi).u64().Inputs({{7, 4}, {5, 2}}); 1012 } 1013 BASIC_BLOCK(7, 6, 8) 1014 { 1015 INST(4, Opcode::Phi).u64().Inputs({{6, 3}, {5, 2}}); 1016 INST(15, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7); 1017 INST(16, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(15); 1018 } 1019 BASIC_BLOCK(8, -1) 1020 { 1021 INST(5, Opcode::Return).u64().Inputs(4); 1022 } 1023 } 1024 1025 // Delete 3 and 4 phi (replace with v2p in return) 1026 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1027 1028 ASSERT_TRUE(CheckInputs(INS(2), {0, 1})); 1029 ASSERT_TRUE(CheckInputs(INS(5), {2})); 1030 1031 ASSERT_TRUE(CheckUsers(INS(0), {2})); 1032 ASSERT_TRUE(CheckUsers(INS(1), {2})); 1033 ASSERT_TRUE(CheckUsers(INS(2), {5})); 1034 1035 auto graph = CreateEmptyGraph(); 1036 GRAPH(graph) 1037 { 1038 CONSTANT(0, 0); 1039 CONSTANT(1, 1); 1040 CONSTANT(6, 2); 1041 CONSTANT(7, 3); 1042 BASIC_BLOCK(2, 5, 4) 1043 { 1044 INST(8, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7); 1045 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8); 1046 } 1047 BASIC_BLOCK(4, 5) {} 1048 BASIC_BLOCK(5, 7) 1049 { 1050 INST(2, Opcode::Phi).u64().Inputs(0, 1); 1051 } 1052 BASIC_BLOCK(7, 7, 8) 1053 { 1054 INST(15, Opcode::Compare).b().SrcType(DataType::Type::INT64).Inputs(6, 7); 1055 INST(16, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(15); 1056 } 1057 BASIC_BLOCK(8, -1) 1058 { 1059 INST(5, Opcode::Return).u64().Inputs(2); 1060 } 1061 } 1062 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1063} 1064 1065TEST_F(CleanupTest, NullPtr) 1066{ 1067 GRAPH(GetGraph()) 1068 { 1069 CONSTANT(0, 0); 1070 CONSTANT(1, nullptr); 1071 1072 BASIC_BLOCK(2, -1) 1073 { 1074 INST(2, Opcode::Return).u64().Inputs(0); 1075 } 1076 } 1077 1078 ASSERT_TRUE(GetGraph()->HasNullPtrInst()); 1079 // Delete NullPtr 1080 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1081 ASSERT_FALSE(GetGraph()->HasNullPtrInst()); 1082} 1083 1084TEST_F(CleanupTest, JustReturnLeft) 1085{ 1086 GRAPH(GetGraph()) 1087 { 1088 PARAMETER(0, 0).u64(); 1089 CONSTANT(1, 1); 1090 CONSTANT(2, 2); 1091 CONSTANT(3, 3); 1092 CONSTANT(4, 4); 1093 BASIC_BLOCK(2, 3, 4) 1094 { 1095 INST(5, Opcode::Add).u64().Inputs(1, 4); 1096 INST(6, Opcode::Add).u64().Inputs(2, 3); 1097 INST(7, Opcode::Compare).b().Inputs(0, 3); 1098 INST(8, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(7); 1099 } 1100 BASIC_BLOCK(3, 4) {} 1101 BASIC_BLOCK(4, -1) 1102 { 1103 INST(9, Opcode::Phi).u64().Inputs({{2, 6}, {3, 5}}); 1104 INST(10, Opcode::Return).u64().Inputs(0); 1105 } 1106 } 1107 1108 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1109 1110 auto graph = CreateEmptyGraph(); 1111 GRAPH(graph) 1112 { 1113 PARAMETER(0, 0).u64(); 1114 BASIC_BLOCK(2, -1) 1115 { 1116 INST(10, Opcode::Return).u64().Inputs(0); 1117 } 1118 } 1119 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1120} 1121 1122TEST_F(CleanupTest, RemovingPhiFromTheSameBlock) 1123{ 1124 auto graph = CreateEmptyGraph(); 1125 GRAPH(graph) 1126 { 1127 PARAMETER(0, 0).u64(); 1128 PARAMETER(1, 1).u64(); 1129 CONSTANT(2, 1); 1130 BASIC_BLOCK(2, 2, 3) 1131 { 1132 INST(5, Opcode::Phi).u64().Inputs(1, 6); 1133 INST(6, Opcode::Phi).u64().Inputs(0, 6); 1134 INST(7, Opcode::Phi).u64().Inputs(0, 8); 1135 INST(8, Opcode::Add).u64().Inputs(7, 2); 1136 INST(9, Opcode::Compare).b().CC(CC_NE).Inputs(8, 1); 1137 INST(10, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(9); 1138 } 1139 BASIC_BLOCK(3, -1) 1140 { 1141 INST(11, Opcode::Add).u64().Inputs(5, 6); 1142 INST(12, Opcode::Return).u64().Inputs(11); 1143 } 1144 } 1145 ASSERT_TRUE(graph->RunPass<Cleanup>()); 1146} 1147 1148TEST_F(CleanupTest, CallDiscardReturnValue) 1149{ 1150 GRAPH(GetGraph()) 1151 { 1152 BASIC_BLOCK(2, -1) 1153 { 1154 INST(20, Opcode::SaveState).NoVregs(); 1155 INST(0, Opcode::CallStatic).s32().InputsAutoType(20); 1156 INST(1, Opcode::ReturnVoid).v0id(); 1157 } 1158 } 1159 ASSERT_FALSE(INS(0).HasUsers()); 1160 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 1161 ASSERT_TRUE(INS(0).GetOpcode() == Opcode::CallStatic); 1162} 1163 1164TEST_F(CleanupTest, CallReturnVoid) 1165{ 1166 GRAPH(GetGraph()) 1167 { 1168 BASIC_BLOCK(2, -1) 1169 { 1170 INST(20, Opcode::SaveState).NoVregs(); 1171 INST(0, Opcode::CallStatic).v0id().InputsAutoType(20); 1172 INST(1, Opcode::ReturnVoid).v0id(); 1173 } 1174 } 1175 ASSERT_FALSE(INS(0).HasUsers()); 1176 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 1177 ASSERT_TRUE(INS(0).GetOpcode() == Opcode::CallStatic); 1178} 1179 1180TEST_F(CleanupTest, StoreObject) 1181{ 1182 GRAPH(GetGraph()) 1183 { 1184 PARAMETER(0, 0).ref(); 1185 PARAMETER(1, 1).s32(); 1186 1187 BASIC_BLOCK(2, -1) 1188 { 1189 INST(2, Opcode::SaveState).Inputs(0, 1, 1).SrcVregs({0, 1, 2}); 1190 INST(3, Opcode::NullCheck).ref().Inputs(0, 2); 1191 INST(4, Opcode::StoreObject).s32().Inputs(3, 1); 1192 INST(5, Opcode::ReturnVoid).v0id(); 1193 } 1194 } 1195 ASSERT_FALSE(INS(4).HasUsers()); 1196 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 1197 ASSERT_TRUE(INS(4).GetOpcode() == Opcode::StoreObject); 1198} 1199 1200TEST_F(CleanupTest, OneBlock) 1201{ 1202 GRAPH(GetGraph()) 1203 { 1204 BASIC_BLOCK(2, -1) 1205 { 1206 INST(0, Opcode::ReturnVoid); 1207 } 1208 } 1209 1210 ASSERT_FALSE(GetGraph()->RunPass<Cleanup>()); 1211 1212 auto graph = CreateEmptyGraph(); 1213 GRAPH(graph) 1214 { 1215 BASIC_BLOCK(2, -1) 1216 { 1217 INST(0, Opcode::ReturnVoid); 1218 } 1219 } 1220 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1221} 1222 1223TEST_F(CleanupTest, TwoBlocks) 1224{ 1225 GRAPH(GetGraph()) 1226 { 1227 CONSTANT(0, 12); 1228 CONSTANT(1, 13); 1229 1230 BASIC_BLOCK(2, 3) 1231 { 1232 INST(2, Opcode::Neg).u64().Inputs(1); 1233 INST(3, Opcode::Add).u64().Inputs(0, 2); 1234 } 1235 1236 BASIC_BLOCK(3, -1) 1237 { 1238 INST(4, Opcode::Add).u64().Inputs(2, 3); 1239 INST(5, Opcode::Return).u64().Inputs(4); 1240 } 1241 } 1242 1243 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1244 1245 auto graph = CreateEmptyGraph(); 1246 GRAPH(graph) 1247 { 1248 CONSTANT(0, 12); 1249 CONSTANT(1, 13); 1250 1251 BASIC_BLOCK(2, -1) 1252 { 1253 INST(2, Opcode::Neg).u64().Inputs(1); 1254 INST(3, Opcode::Add).u64().Inputs(0, 2); 1255 INST(4, Opcode::Add).u64().Inputs(2, 3); 1256 INST(5, Opcode::Return).u64().Inputs(4); 1257 } 1258 } 1259 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1260} 1261 1262TEST_F(CleanupTest, SameBlockPhiTwice) 1263{ 1264 GRAPH(GetGraph()) 1265 { 1266 CONSTANT(0, 12).s64(); 1267 CONSTANT(1, 13).s64(); 1268 1269 BASIC_BLOCK(2, 3, 4) 1270 { 1271 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1); 1272 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 1273 } 1274 1275 BASIC_BLOCK(3, 5) 1276 { 1277 INST(4, Opcode::Neg).u64().Inputs(0); 1278 INST(5, Opcode::Neg).u64().Inputs(1); 1279 } 1280 1281 BASIC_BLOCK(4, 5) 1282 { 1283 INST(7, Opcode::Neg).u64().Inputs(1); 1284 INST(8, Opcode::Neg).u64().Inputs(0); 1285 } 1286 1287 BASIC_BLOCK(5, 6) 1288 { 1289 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}, {6, 15}}); 1290 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}, {6, 16}}); 1291 INST(12, Opcode::Neg).u64().Inputs(10); 1292 INST(13, Opcode::Add).u64().Inputs(10, 11); 1293 } 1294 1295 BASIC_BLOCK(6, 5, -1) 1296 { 1297 INST(15, Opcode::Add).u64().Inputs(0, 1); 1298 INST(16, Opcode::Neg).u64().Inputs(0); 1299 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 1300 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17); 1301 } 1302 } 1303 1304 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1305 1306 auto graph = CreateEmptyGraph(); 1307 GRAPH(graph) 1308 { 1309 CONSTANT(0, 12).s64(); 1310 CONSTANT(1, 13).s64(); 1311 1312 BASIC_BLOCK(7, 6) {} 1313 1314 BASIC_BLOCK(6, 6, -1) 1315 { 1316 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(1, 0); 1317 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17); 1318 } 1319 } 1320 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1321} 1322 1323TEST_F(CleanupTest, TwoBlocksLoop) 1324{ 1325 GRAPH(GetGraph()) 1326 { 1327 CONSTANT(0, 12).s64(); 1328 CONSTANT(1, 13).s64(); 1329 1330 BASIC_BLOCK(2, 3, 4) 1331 { 1332 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1); 1333 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 1334 } 1335 1336 BASIC_BLOCK(3, 5) 1337 { 1338 INST(4, Opcode::Neg).u64().Inputs(0); 1339 INST(5, Opcode::Neg).u64().Inputs(1); 1340 } 1341 1342 BASIC_BLOCK(4, 5) 1343 { 1344 INST(7, Opcode::Neg).u64().Inputs(1); 1345 INST(8, Opcode::Neg).u64().Inputs(0); 1346 } 1347 1348 BASIC_BLOCK(5, 6) 1349 { 1350 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}, {6, 15}}); 1351 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}, {6, 16}}); 1352 INST(12, Opcode::Neg).u64().Inputs(10); 1353 INST(13, Opcode::Add).u64().Inputs(10, 11); 1354 } 1355 1356 BASIC_BLOCK(6, 5, -1) 1357 { 1358 INST(15, Opcode::Add).u64().Inputs(12, 13); 1359 INST(16, Opcode::Neg).u64().Inputs(12); 1360 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(15, 16); 1361 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17); 1362 } 1363 } 1364 1365 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1366 1367 auto graph = CreateEmptyGraph(); 1368 GRAPH(graph) 1369 { 1370 CONSTANT(0, 12).s64(); 1371 CONSTANT(1, 13).s64(); 1372 1373 BASIC_BLOCK(2, 3, 4) 1374 { 1375 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1); 1376 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 1377 } 1378 1379 BASIC_BLOCK(3, 7) 1380 { 1381 INST(4, Opcode::Neg).u64().Inputs(0); 1382 INST(5, Opcode::Neg).u64().Inputs(1); 1383 } 1384 1385 BASIC_BLOCK(4, 7) 1386 { 1387 INST(7, Opcode::Neg).u64().Inputs(1); 1388 INST(8, Opcode::Neg).u64().Inputs(0); 1389 } 1390 1391 BASIC_BLOCK(7, 5) 1392 { 1393 INST(19, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}}); 1394 INST(20, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}}); 1395 } 1396 1397 BASIC_BLOCK(5, 5, -1) 1398 { 1399 INST(10, Opcode::Phi).u64().Inputs({{7, 19}, {5, 15}}); 1400 INST(11, Opcode::Phi).u64().Inputs({{7, 20}, {5, 16}}); 1401 INST(12, Opcode::Neg).u64().Inputs(10); 1402 INST(13, Opcode::Add).u64().Inputs(10, 11); 1403 INST(15, Opcode::Add).u64().Inputs(12, 13); 1404 INST(16, Opcode::Neg).u64().Inputs(12); 1405 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(15, 16); 1406 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17); 1407 } 1408 } 1409 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1410} 1411 1412TEST_F(CleanupTest, TwoLoopsPreHeader) 1413{ 1414 GRAPH(GetGraph()) 1415 { 1416 CONSTANT(0, 12).s64(); 1417 CONSTANT(1, 13).s64(); 1418 PARAMETER(8, 0).b(); 1419 1420 BASIC_BLOCK(2, 3) 1421 { 1422 INST(2, Opcode::Neg).u64().Inputs(0); 1423 } 1424 1425 BASIC_BLOCK(3, 4, 5) 1426 { 1427 INST(4, Opcode::Neg).u64().Inputs(0); 1428 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8); 1429 } 1430 1431 BASIC_BLOCK(4, 4, -1) 1432 { 1433 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 1); 1434 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); 1435 } 1436 1437 BASIC_BLOCK(5, 5, -1) 1438 { 1439 INST(10, Opcode::Compare).b().CC(CC_GT).SrcType(DataType::Type::UINT64).Inputs(4, 2); 1440 INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10); 1441 } 1442 } 1443 1444 ASSERT_EQ(&BB(3), BB(4).GetLoop()->GetPreHeader()); 1445 ASSERT_EQ(&BB(3), BB(5).GetLoop()->GetPreHeader()); 1446 ASSERT_EQ(1U, BB(4).GetLoop()->GetBlocks().size()); 1447 ASSERT_EQ(1U, BB(5).GetLoop()->GetBlocks().size()); 1448 ASSERT_EQ(4U, BB(4).GetLoop()->GetOuterLoop()->GetBlocks().size()); 1449 ASSERT_EQ(4U, BB(5).GetLoop()->GetOuterLoop()->GetBlocks().size()); 1450 1451 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1452 1453 auto graph = CreateEmptyGraph(); 1454 GRAPH(graph) 1455 { 1456 CONSTANT(0, 12).s64(); 1457 CONSTANT(1, 13).s64(); 1458 PARAMETER(8, 0).b(); 1459 1460 BASIC_BLOCK(2, 4, 5) 1461 { 1462 INST(2, Opcode::Neg).u64().Inputs(0); 1463 INST(4, Opcode::Neg).u64().Inputs(0); 1464 INST(9, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(8); 1465 } 1466 1467 BASIC_BLOCK(4, 4, -1) 1468 { 1469 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 1); 1470 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); 1471 } 1472 1473 BASIC_BLOCK(5, 5, -1) 1474 { 1475 INST(10, Opcode::Compare).b().CC(CC_GT).SrcType(DataType::Type::UINT64).Inputs(4, 2); 1476 INST(11, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(10); 1477 } 1478 } 1479 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1480 1481 EXPECT_EQ(&BB(2), BB(4).GetLoop()->GetPreHeader()); 1482 EXPECT_EQ(&BB(2), BB(5).GetLoop()->GetPreHeader()); 1483 EXPECT_EQ(1U, BB(4).GetLoop()->GetBlocks().size()); 1484 EXPECT_EQ(1U, BB(5).GetLoop()->GetBlocks().size()); 1485 EXPECT_EQ(3U, BB(4).GetLoop()->GetOuterLoop()->GetBlocks().size()); 1486 EXPECT_EQ(3U, BB(5).GetLoop()->GetOuterLoop()->GetBlocks().size()); 1487} 1488 1489TEST_F(CleanupTest, LoopBackEdge) 1490{ 1491 GRAPH(GetGraph()) 1492 { 1493 CONSTANT(0, 12).s64(); 1494 CONSTANT(1, 13).s64(); 1495 1496 BASIC_BLOCK(2, 3) 1497 { 1498 INST(2, Opcode::Neg).u64().Inputs(0); 1499 } 1500 1501 BASIC_BLOCK(3, 2, -1) 1502 { 1503 INST(4, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(1, 2); 1504 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4); 1505 } 1506 } 1507 1508 ASSERT_TRUE(BB(3).GetLoop()->HasBackEdge(&BB(3))); 1509 ASSERT_EQ(2U, BB(3).GetLoop()->GetBlocks().size()); 1510 1511 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1512 1513 auto graph = CreateEmptyGraph(); 1514 GRAPH(graph) 1515 { 1516 CONSTANT(0, 12).s64(); 1517 CONSTANT(1, 13).s64(); 1518 1519 BASIC_BLOCK(2, 2, -1) 1520 { 1521 INST(2, Opcode::Neg).u64().Inputs(0); 1522 INST(4, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(1, 2); 1523 INST(5, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(4); 1524 } 1525 } 1526 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1527 1528 EXPECT_TRUE(BB(2).GetLoop()->HasBackEdge(&BB(2))); 1529 EXPECT_EQ(1U, BB(2).GetLoop()->GetBlocks().size()); 1530} 1531 1532TEST_F(CleanupTest, LoopMiddleBlock) 1533{ 1534 GRAPH(GetGraph()) 1535 { 1536 CONSTANT(0, 12).s64(); 1537 CONSTANT(1, 13).s64(); 1538 1539 BASIC_BLOCK(2, 3) 1540 { 1541 INST(2, Opcode::Neg).u64().Inputs(0); 1542 } 1543 1544 BASIC_BLOCK(3, 4) 1545 { 1546 INST(4, Opcode::Neg).u64().Inputs(1); 1547 } 1548 1549 BASIC_BLOCK(4, 2, -1) 1550 { 1551 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 4); 1552 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); 1553 } 1554 } 1555 1556 ASSERT_EQ(3U, BB(2).GetLoop()->GetBlocks().size()); 1557 ASSERT_EQ(3U, BB(2).GetLoop()->GetOuterLoop()->GetBlocks().size()); 1558 1559 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1560 1561 auto graph = CreateEmptyGraph(); 1562 GRAPH(graph) 1563 { 1564 CONSTANT(0, 12).s64(); 1565 CONSTANT(1, 13).s64(); 1566 1567 BASIC_BLOCK(2, 2, -1) 1568 { 1569 INST(2, Opcode::Neg).u64().Inputs(0); 1570 INST(4, Opcode::Neg).u64().Inputs(1); 1571 INST(6, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(2, 4); 1572 INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); 1573 } 1574 } 1575 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1576 1577 EXPECT_EQ(1U, BB(2).GetLoop()->GetBlocks().size()); 1578 EXPECT_EQ(3U, BB(2).GetLoop()->GetOuterLoop()->GetBlocks().size()); 1579} 1580 1581TEST_F(CleanupTest, ThreeBlocks) 1582{ 1583 GRAPH(GetGraph()) 1584 { 1585 CONSTANT(0, 12); 1586 CONSTANT(1, 13); 1587 1588 BASIC_BLOCK(2, 3) 1589 { 1590 INST(2, Opcode::Neg).u64().Inputs(1); 1591 INST(3, Opcode::Add).u64().Inputs(0, 2); 1592 } 1593 1594 BASIC_BLOCK(3, 4) 1595 { 1596 INST(4, Opcode::Neg).u64().Inputs(0); 1597 INST(5, Opcode::Add).u64().Inputs(1, 4); 1598 } 1599 1600 BASIC_BLOCK(4, -1) 1601 { 1602 INST(6, Opcode::Add).u64().Inputs(3, 5); 1603 INST(7, Opcode::Return).u64().Inputs(6); 1604 } 1605 } 1606 1607 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1608 1609 auto graph = CreateEmptyGraph(); 1610 GRAPH(graph) 1611 { 1612 CONSTANT(0, 12); 1613 CONSTANT(1, 13); 1614 1615 BASIC_BLOCK(2, -1) 1616 { 1617 INST(2, Opcode::Neg).u64().Inputs(1); 1618 INST(3, Opcode::Add).u64().Inputs(0, 2); 1619 INST(4, Opcode::Neg).u64().Inputs(0); 1620 INST(5, Opcode::Add).u64().Inputs(1, 4); 1621 INST(6, Opcode::Add).u64().Inputs(3, 5); 1622 INST(7, Opcode::Return).u64().Inputs(6); 1623 } 1624 } 1625 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1626} 1627 1628TEST_F(CleanupTest, TwoBlocksAndPhi) 1629{ 1630 GRAPH(GetGraph()) 1631 { 1632 CONSTANT(0, 12).s64(); 1633 CONSTANT(1, 13).s64(); 1634 1635 BASIC_BLOCK(2, 3, 4) 1636 { 1637 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1); 1638 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 1639 } 1640 1641 BASIC_BLOCK(3, 5) 1642 { 1643 INST(4, Opcode::Neg).u64().Inputs(0); 1644 INST(5, Opcode::Neg).u64().Inputs(1); 1645 } 1646 1647 BASIC_BLOCK(4, 5) 1648 { 1649 INST(7, Opcode::Neg).u64().Inputs(1); 1650 INST(8, Opcode::Neg).u64().Inputs(0); 1651 } 1652 1653 BASIC_BLOCK(5, 6) 1654 { 1655 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}}); 1656 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}}); 1657 INST(12, Opcode::Neg).u64().Inputs(10); 1658 INST(13, Opcode::Add).u64().Inputs(10, 11); 1659 } 1660 1661 BASIC_BLOCK(6, 7, 8) 1662 { 1663 INST(15, Opcode::Add).u64().Inputs(12, 13); 1664 INST(16, Opcode::Neg).u64().Inputs(12); 1665 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(16, 15); 1666 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17); 1667 } 1668 1669 BASIC_BLOCK(7, 8) 1670 { 1671 INST(19, Opcode::Add).u64().Inputs(0, 1); 1672 } 1673 1674 BASIC_BLOCK(8, -1) 1675 { 1676 INST(21, Opcode::Phi).u64().Inputs({{6, 16}, {7, 19}}); 1677 INST(22, Opcode::Add).u64().Inputs(21, 1); 1678 INST(23, Opcode::Return).u64().Inputs(22); 1679 } 1680 } 1681 1682 ASSERT_TRUE(GetGraph()->RunPass<Cleanup>()); 1683 1684 auto graph = CreateEmptyGraph(); 1685 GRAPH(graph) 1686 { 1687 CONSTANT(0, 12).s64(); 1688 CONSTANT(1, 13).s64(); 1689 1690 BASIC_BLOCK(2, 3, 4) 1691 { 1692 INST(2, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::INT64).Inputs(0, 1); 1693 INST(3, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(2); 1694 } 1695 1696 BASIC_BLOCK(3, 5) 1697 { 1698 INST(4, Opcode::Neg).u64().Inputs(0); 1699 INST(5, Opcode::Neg).u64().Inputs(1); 1700 } 1701 1702 BASIC_BLOCK(4, 5) 1703 { 1704 INST(7, Opcode::Neg).u64().Inputs(1); 1705 INST(8, Opcode::Neg).u64().Inputs(0); 1706 } 1707 1708 BASIC_BLOCK(5, 7, 8) 1709 { 1710 INST(10, Opcode::Phi).u64().Inputs({{3, 4}, {4, 7}}); 1711 INST(11, Opcode::Phi).u64().Inputs({{3, 5}, {4, 8}}); 1712 INST(12, Opcode::Neg).u64().Inputs(10); 1713 INST(13, Opcode::Add).u64().Inputs(10, 11); 1714 INST(15, Opcode::Add).u64().Inputs(12, 13); 1715 INST(16, Opcode::Neg).u64().Inputs(12); 1716 INST(17, Opcode::Compare).b().CC(CC_LT).SrcType(DataType::Type::UINT64).Inputs(16, 15); 1717 INST(18, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(17); 1718 } 1719 1720 BASIC_BLOCK(7, 8) 1721 { 1722 INST(19, Opcode::Add).u64().Inputs(0, 1); 1723 } 1724 1725 BASIC_BLOCK(8, -1) 1726 { 1727 INST(21, Opcode::Phi).u64().Inputs(16, 19); 1728 INST(22, Opcode::Add).u64().Inputs(21, 1); 1729 INST(23, Opcode::Return).u64().Inputs(22); 1730 } 1731 } 1732 ASSERT_TRUE(GraphComparator().Compare(GetGraph(), graph)); 1733} 1734} // namespace panda::compiler 1735