1 /** 2 * Copyright (c) 2023 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 <cstring> 17 #include <gtest/gtest.h> 18 #include <iomanip> 19 #include <iostream> 20 #include <memory> 21 #include <sstream> 22 #include <string> 23 24 #include "basicblock.h" 25 #include "graph.h" 26 #include "graph_test.h" 27 #include "inst.h" 28 #include "mem/pool_manager.h" 29 #include "optimizer/analysis/loop_analyzer.h" 30 31 using namespace testing::ext; 32 33 namespace panda::compiler { 34 class CompilerBasicBlockTest : public testing::Test { 35 public: SetUpTestCase(void)36 static void SetUpTestCase(void) {} TearDownTestCase(void)37 static void TearDownTestCase(void) {} SetUp()38 void SetUp() {} TearDown()39 void TearDown() {} 40 41 GraphTest graph_test_; 42 }; 43 44 /** 45 * @tc.name: compiler_basicblock_test_001 46 * @tc.desc: Verify the BlocksPathDfsSearch function. 47 * @tc.type: FUNC 48 * @tc.require: issueNumber 49 */ 50 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_001, TestSize.Level1) 51 { 52 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; __anond946d00f0102(Graph* graph, std::string &method_name) 53 graph_test_.TestBuildGraphFromFile(pfile, [&](Graph* graph, std::string &method_name) { 54 Marker mrk = 4; // 4: It's a random number 55 auto start_block = graph->GetStartBlock(); 56 auto end_block = graph->GetEndBlock(); 57 auto value = BlocksPathDfsSearch(mrk, start_block, start_block, end_block); 58 EXPECT_TRUE(value); 59 for (auto bb : graph->GetBlocksRPO()) { 60 if (!bb->IsCatchBegin()) { 61 continue; 62 } 63 64 EXPECT_TRUE(BlocksPathDfsSearch(mrk, start_block, end_block, bb->GetSuccessor(0))); 65 EXPECT_FALSE(BlocksPathDfsSearch(mrk, start_block, bb->GetSuccessor(0), end_block)); 66 EXPECT_FALSE(BlocksPathDfsSearch(mrk, end_block, start_block, bb->GetSuccessor(0))); 67 } 68 }); 69 } 70 71 /** 72 * @tc.name: compiler_basicblock_test_002 73 * @tc.desc: Verify the InsertBlockBefore function. 74 * @tc.type: FUNC 75 * @tc.require: issueNumber 76 */ 77 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_002, TestSize.Level1) 78 { 79 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; 80 const char *test_method_name = "func_main_0"; 81 bool status = false; __anond946d00f0202(Graph* graph, std::string &method_name) 82 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 83 if (test_method_name != method_name) { 84 return; 85 } 86 status = true; 87 for (auto bb : graph->GetBlocksRPO()) { 88 if (!bb->IsTry()) { 89 continue; 90 } 91 graph->GetEndBlock()->InsertBlockBefore(bb->GetPredecessor(0)); 92 graph->GetStartBlock()->InsertBlockBefore(bb->GetPredecessor(0)); 93 } 94 95 EXPECT_TRUE(graph->GetStartBlock()->IsDominate(graph->GetStartBlock())); 96 }); 97 EXPECT_TRUE(status); 98 } 99 100 /** 101 * @tc.name: compiler_basicblock_test_003 102 * @tc.desc: Verify the Clone function. 103 * @tc.type: FUNC 104 * @tc.require: issueNumber 105 */ 106 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_003, TestSize.Level1) 107 { 108 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; 109 const char *test_method_name = "func_main_0"; 110 bool status = false; __anond946d00f0302(Graph* graph, std::string &method_name) 111 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 112 if (test_method_name != method_name) { 113 return; 114 } 115 116 for (auto bb : graph->GetBlocksRPO()) { 117 if (bb->IsStartBlock() || bb->IsEndBlock() || bb->IsTryEnd()) { 118 status = true; 119 EXPECT_FALSE(bb->Clone(graph)->IsTry()); 120 } 121 } 122 }); 123 EXPECT_TRUE(status); 124 } 125 126 /** 127 * @tc.name: compiler_basicblock_test_004 128 * @tc.desc: Verify the CreateImmediateDominator function. 129 * @tc.type: FUNC 130 * @tc.require: issueNumber 131 */ 132 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_004, TestSize.Level1) 133 { 134 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; 135 const char *test_method_name = "func_main_0"; 136 bool status = false; __anond946d00f0402(Graph* graph, std::string &method_name) 137 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 138 if (test_method_name != method_name) { 139 return; 140 } 141 142 status = true; 143 EXPECT_TRUE(graph->GetStartBlock()->CreateImmediateDominator()->IsEmpty()); 144 }); 145 EXPECT_TRUE(status); 146 } 147 148 /** 149 * @tc.name: compiler_basicblock_test_005 150 * @tc.desc: Verify the IsDominate function. 151 * @tc.type: FUNC 152 * @tc.require: issueNumber 153 */ 154 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_005, TestSize.Level1) 155 { 156 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; 157 const char *test_method_name = "func_main_0"; 158 bool status = false; __anond946d00f0502(Graph* graph, std::string &method_name) 159 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 160 if (test_method_name != method_name) { 161 return; 162 } 163 status = true; 164 auto start_block = graph->GetStartBlock(); 165 auto end_block = graph->GetEndBlock(); 166 167 EXPECT_TRUE(start_block->IsDominate(end_block)); 168 EXPECT_FALSE(end_block->IsDominate(start_block)); 169 }); 170 EXPECT_TRUE(status); 171 } 172 173 /** 174 * @tc.name: compiler_basicblock_test_006 175 * @tc.desc: Verify the EraseInst function. 176 * @tc.type: FUNC 177 * @tc.require: issueNumber 178 */ 179 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_006, TestSize.Level1) 180 { 181 std::string pfile = GRAPH_TEST_ABC_DIR "styleTryCatch.abc"; 182 const char *test_method_name = "func_main_0"; 183 bool status = false; 184 options.SetCompilerUseSafepoint(false); __anond946d00f0602(Graph* graph, std::string &method_name) 185 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 186 if (test_method_name != method_name) { 187 return; 188 } 189 190 EXPECT_NE(graph, nullptr); 191 for (auto bb : graph->GetBlocksRPO()) { 192 for (auto inst : bb->PhiInsts()) { 193 status = true; 194 bb->EraseInst(inst, true); 195 EXPECT_EQ(inst->GetNext(), nullptr); 196 break; 197 } 198 } 199 }); 200 EXPECT_TRUE(status); 201 } 202 203 /** 204 * @tc.name: compiler_basicblock_test_007 205 * @tc.desc: Verify the RemoveInst function. 206 * @tc.type: FUNC 207 * @tc.require: issueNumber 208 */ 209 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_007, TestSize.Level1) 210 { 211 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; 212 const char *test_method_name = "func_main_0"; 213 bool status = false; 214 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, __anond946d00f0702(Graph* graph, std::string &method_name) 215 std::string &method_name) { 216 if (test_method_name != method_name) { 217 return; 218 } 219 status = true; 220 EXPECT_NE(graph, nullptr); 221 auto start_block = graph->GetStartBlock(); 222 start_block->RemoveInst(graph->GetFirstConstInst()); 223 for (auto bb : graph->GetBlocksRPO()) { 224 for (auto inst : bb->AllInsts()) { 225 status = true; 226 bb->RemoveInst(inst); 227 EXPECT_EQ(inst->GetNext(), nullptr); 228 } 229 } 230 }); 231 EXPECT_TRUE(status); 232 } 233 234 /** 235 * @tc.name: compiler_basicblock_test_008 236 * @tc.desc: Verify the IsInverted function. 237 * @tc.type: FUNC 238 * @tc.require: issueNumber 239 */ 240 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_008, TestSize.Level1) 241 { 242 std::string pfile = GRAPH_TEST_ABC_DIR "testTryCatch.abc"; 243 const char *test_method_name = "func_main_0"; 244 bool status = false; __anond946d00f0802(Graph* graph, std::string &method_name) 245 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 246 if (test_method_name != method_name) { 247 return; 248 } 249 status = true; 250 auto bb = graph->GetStartBlock(); 251 bb->InstsSafe(); 252 EXPECT_EQ(bb->GetPredsBlocks().size(), 0); 253 bb->PhiInstsSafeReverse(); 254 EXPECT_FALSE(bb->IsInverted()); 255 }); 256 EXPECT_TRUE(status); 257 } 258 259 /** 260 * @tc.name: compiler_basicblock_test_009 261 * @tc.desc: Verify the ReplaceInst function. 262 * @tc.type: FUNC 263 * @tc.require: issueNumber 264 */ 265 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_009, TestSize.Level1) 266 { 267 std::string pfile = GRAPH_TEST_ABC_DIR "styleTryCatch.abc"; 268 const char *test_method_name = "func_main_0"; 269 bool status = false; 270 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, __anond946d00f0902(Graph* graph, std::string &method_name) 271 std::string &method_name) { 272 if (test_method_name != method_name) { 273 return; 274 } 275 276 EXPECT_NE(graph, nullptr); 277 for (auto bb : graph->GetBlocksRPO()) { 278 for (auto phi : bb->PhiInsts()) { 279 status = true; 280 auto phi1 = graph->CreateInstPhi(DataType::ANY, 0U); 281 bb->ReplaceInst(phi, phi1); 282 } 283 } 284 }); 285 EXPECT_TRUE(status); 286 } 287 288 /** 289 * @tc.name: compiler_basicblock_test_010 290 * @tc.desc: Verify the InsertRangeBefore function. 291 * @tc.type: FUNC 292 * @tc.require: issueNumber 293 */ 294 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_010, TestSize.Level1) 295 { 296 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; 297 const char *test_method_name = "func2"; 298 bool status = false; __anond946d00f0a02(Graph* graph, std::string &method_name) 299 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 300 if (test_method_name != method_name) { 301 return; 302 } 303 304 status = true; 305 auto block = graph->GetBlocksRPO()[0]; 306 block->InsertRangeBefore(block->GetFirstInst(), block->GetLastInst(), graph->GetFirstConstInst()); 307 EXPECT_EQ(block->GetLastInst()->GetNext(), graph->GetFirstConstInst()); 308 }); 309 EXPECT_TRUE(status); 310 } 311 312 /** 313 * @tc.name: compiler_basicblock_test_011 314 * @tc.desc: Verify the InvalidateLoopIfIrreducible function. 315 * @tc.type: FUNC 316 * @tc.require: issueNumber 317 */ 318 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_011, TestSize.Level1) 319 { 320 std::string pfile = GRAPH_TEST_ABC_DIR "styleTryCatch.abc"; 321 const char *test_method_name = "func_main_0"; 322 bool status = false; 323 bool status1 = false; 324 bool status2 = false; 325 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status, &status1, &status2](Graph* graph, __anond946d00f0b02(Graph* graph, std::string &method_name) 326 std::string &method_name) { 327 if (test_method_name != method_name) { 328 return; 329 } 330 331 EXPECT_NE(graph, nullptr); 332 uint32_t id = 2; 333 for (auto block : graph->GetBlocksRPO()) { 334 if (block->IsTry()) { 335 status = true; 336 Loop loop(graph->GetAllocator(), block, id); 337 loop.SetIsIrreducible(true); 338 EXPECT_TRUE(loop.IsIrreducible()); 339 block->SetLoop(&loop); 340 EXPECT_NE(block->GetLoop(), nullptr); 341 block->InvalidateLoopIfIrreducible(); 342 } 343 if (block->IsTryBegin()) { 344 status1 = true; 345 Loop loop1(graph->GetAllocator(), block, id); 346 block->SetLoop(&loop1); 347 EXPECT_NE(block->GetLoop(), nullptr); 348 block->InvalidateLoopIfIrreducible(); 349 } 350 if (block->IsTryEnd()) { 351 status2 = true; 352 Loop loop2(graph->GetAllocator(), graph->GetEndBlock(), id); 353 loop2.SetIsIrreducible(true); 354 EXPECT_TRUE(loop2.IsIrreducible()); 355 block->SetLoop(&loop2); 356 EXPECT_NE(block->GetLoop(), nullptr); 357 } 358 } 359 }); 360 EXPECT_TRUE(status); 361 EXPECT_TRUE(status1); 362 EXPECT_TRUE(status2); 363 } 364 365 /** 366 * @tc.name: compiler_basicblock_test_012 367 * @tc.desc: Verify the InsertAfter function. 368 * @tc.type: FUNC 369 * @tc.require: issueNumber 370 */ 371 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_012, TestSize.Level1) 372 { 373 std::string pfile = GRAPH_TEST_ABC_DIR "moduleTryCatch.abc"; 374 const char *test_method_name = "func2"; 375 bool status = false; __anond946d00f0c02(Graph* graph, std::string &method_name) 376 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 377 if (test_method_name != method_name) { 378 return; 379 } 380 status = true; 381 382 for (auto block : graph->GetBlocksRPO()) { 383 auto inst = graph->CreateInstSaveState(DataType::ANY, 0); 384 graph->GetFirstConstInst()->SetBasicBlock(block); 385 EXPECT_EQ(graph->GetFirstConstInst()->GetBasicBlock(), block); 386 block->InsertAfter(inst, graph->GetFirstConstInst()); 387 EXPECT_EQ(graph->GetFirstConstInst()->GetNext(), inst); 388 } 389 }); 390 EXPECT_TRUE(status); 391 } 392 393 /** 394 * @tc.name: compiler_basicblock_test_013 395 * @tc.desc: Verify the AppendRangeInst function. 396 * @tc.type: FUNC 397 * @tc.require: issueNumber 398 */ 399 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_013, TestSize.Level1) 400 { 401 std::string pfile = GRAPH_TEST_ABC_DIR "styleTryCatch.abc"; 402 const char *test_method_name = "func_main_0"; 403 bool status = false; __anond946d00f0d02(Graph* graph, std::string &method_name) 404 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 405 if (test_method_name != method_name) { 406 return; 407 } 408 409 EXPECT_NE(graph, nullptr); 410 status = true; 411 auto start_block = graph->GetStartBlock(); 412 auto end_block = graph->GetEndBlock(); 413 414 graph->GetFirstConstInst()->SetPrev(nullptr); 415 EXPECT_EQ(graph->GetFirstConstInst()->GetPrev(), nullptr); 416 start_block->AppendRangeInst(graph->GetFirstConstInst(), start_block->GetLastInst()); 417 EXPECT_EQ(graph->GetFirstConstInst()->GetPrev(), start_block->GetLastInst()); 418 start_block->AddSucc(end_block); 419 EXPECT_NE(start_block->InsertNewBlockToSuccEdge(end_block), nullptr); 420 }); 421 EXPECT_TRUE(status); 422 } 423 424 /** 425 * @tc.name: compiler_basicblock_test_014 426 * @tc.desc: Verify the SplitBlockAfterInstruction function. 427 * @tc.type: FUNC 428 * @tc.require: issueNumber 429 */ 430 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_014, TestSize.Level1) 431 { 432 std::string pfile = GRAPH_TEST_ABC_DIR "styleTryCatch.abc"; 433 const char *test_method_name = "func_main_0"; 434 bool status = false; 435 bool status1 = false; 436 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status, &status1](Graph* graph, __anond946d00f0e02(Graph* graph, std::string &method_name) 437 std::string &method_name) { 438 if (test_method_name != method_name) { 439 return; 440 } 441 442 EXPECT_NE(graph, nullptr); 443 for (auto bb : graph->GetBlocksRPO()) { 444 if (bb->IsTry() && bb->IsLoopValid()) { 445 auto inst = bb->GetLastInst(); 446 EXPECT_NE(bb->SplitBlockAfterInstruction(inst, false), nullptr); 447 EXPECT_NE(bb->SplitBlockAfterInstruction(inst, true), nullptr); 448 status = true; 449 break; 450 } 451 } 452 453 for (auto bb : graph->GetVectorBlocks()) { 454 for (auto inst : bb->AllInsts()) { 455 if (inst->IsPhi() || bb->IsStartBlock() || bb->IsEndBlock()) { 456 continue; 457 } 458 status1 = true; 459 EXPECT_NE(bb->SplitBlockAfterInstruction(inst, true), nullptr); 460 } 461 } 462 }); 463 EXPECT_TRUE(status); 464 EXPECT_TRUE(status1); 465 } 466 467 /** 468 * @tc.name: compiler_basicblock_test_015 469 * @tc.desc: Verify the IsIfBlock function. 470 * @tc.type: FUNC 471 * @tc.require: issueNumber 472 */ 473 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_015, TestSize.Level1) 474 { 475 std::string pfile = GRAPH_TEST_ABC_DIR "styleTryCatch.abc"; 476 const char *test_method_name = "func_main_0"; 477 bool status = false; 478 bool status1 = false; 479 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status, &status1](Graph* graph, __anond946d00f0f02(Graph* graph, std::string &method_name) 480 std::string &method_name) { 481 if (test_method_name != method_name) { 482 return; 483 } 484 EXPECT_NE(graph, nullptr); 485 auto end_block = graph->GetEndBlock(); 486 for (auto bb : graph->GetBlocksRPO()) { 487 for (auto inst : bb->AllInsts()) { 488 if (inst->GetOpcode() == Opcode::IfImm) { 489 status = true; 490 EXPECT_TRUE(bb->IsIfBlock()); 491 bb->GetLastInst()->SetOpcode(Opcode::If); 492 EXPECT_TRUE(bb->IsIfBlock()); 493 } 494 if (inst->IsTry()) { 495 status1 = true; 496 EXPECT_FALSE(bb->IsIfBlock()); 497 } 498 499 EXPECT_FALSE(end_block->IsIfBlock()); 500 } 501 } 502 }); 503 EXPECT_TRUE(status); 504 } 505 506 /** 507 * @tc.name: compiler_basicblock_test_016 508 * @tc.desc: Verify the CopyTryCatchProps function. 509 * @tc.type: FUNC 510 * @tc.require: issueNumber 511 */ 512 HWTEST_F(CompilerBasicBlockTest, compiler_basicblock_test_016, TestSize.Level1) 513 { 514 std::string pfile = GRAPH_TEST_ABC_DIR "testTryCatch.abc"; 515 const char *test_method_name = "func_main_0"; 516 bool status = false; __anond946d00f1002(Graph* graph, std::string &method_name) 517 graph_test_.TestBuildGraphFromFile(pfile, [&test_method_name, &status](Graph* graph, std::string &method_name) { 518 if (test_method_name != method_name) { 519 return; 520 } 521 auto bb = graph->GetStartBlock(); 522 status = true; 523 bb->SetTry(true); 524 bb->CopyTryCatchProps(bb); 525 EXPECT_EQ(bb->GetTryId(), INVALID_ID); 526 EXPECT_FALSE(bb->IsOsrEntry()); 527 }); 528 EXPECT_TRUE(status); 529 } 530 } // namespace panda::compiler 531