1 //===- BasicBlockUtils.cpp - Unit tests for BasicBlockUtils ---------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 10 #include "llvm/Analysis/AssumptionCache.h" 11 #include "llvm/Analysis/BasicAliasAnalysis.h" 12 #include "llvm/Analysis/BlockFrequencyInfo.h" 13 #include "llvm/Analysis/BranchProbabilityInfo.h" 14 #include "llvm/Analysis/CFG.h" 15 #include "llvm/Analysis/DomTreeUpdater.h" 16 #include "llvm/Analysis/LoopInfo.h" 17 #include "llvm/Analysis/MemorySSA.h" 18 #include "llvm/Analysis/MemorySSAUpdater.h" 19 #include "llvm/Analysis/PostDominators.h" 20 #include "llvm/Analysis/TargetLibraryInfo.h" 21 #include "llvm/AsmParser/Parser.h" 22 #include "llvm/IR/BasicBlock.h" 23 #include "llvm/IR/Dominators.h" 24 #include "llvm/IR/LLVMContext.h" 25 #include "llvm/Support/SourceMgr.h" 26 #include "gtest/gtest.h" 27 28 using namespace llvm; 29 30 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 31 SMDiagnostic Err; 32 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 33 if (!Mod) 34 Err.print("BasicBlockUtilsTests", errs()); 35 return Mod; 36 } 37 38 static BasicBlock *getBasicBlockByName(Function &F, StringRef Name) { 39 for (BasicBlock &BB : F) 40 if (BB.getName() == Name) 41 return &BB; 42 llvm_unreachable("Expected to find basic block!"); 43 } 44 45 TEST(BasicBlockUtils, EliminateUnreachableBlocks) { 46 LLVMContext C; 47 std::unique_ptr<Module> M = parseIR(C, R"IR( 48 define i32 @has_unreachable(i1 %cond) { 49 entry: 50 br i1 %cond, label %bb0, label %bb1 51 bb0: 52 br label %bb1 53 bb1: 54 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ] 55 ret i32 %phi 56 bb2: 57 ret i32 42 58 } 59 )IR"); 60 Function *F = M->getFunction("has_unreachable"); 61 DominatorTree DT(*F); 62 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); 63 64 EXPECT_EQ(F->size(), (size_t)4); 65 bool Result = EliminateUnreachableBlocks(*F, &DTU); 66 EXPECT_TRUE(Result); 67 EXPECT_EQ(F->size(), (size_t)3); 68 EXPECT_TRUE(DT.verify()); 69 } 70 71 TEST(BasicBlockUtils, SplitEdge_ex1) { 72 LLVMContext C; 73 std::unique_ptr<Module> M = parseIR(C, R"IR( 74 define void @foo(i1 %cond0) { 75 entry: 76 br i1 %cond0, label %bb0, label %bb1 77 bb0: 78 %0 = mul i32 1, 2 79 br label %bb1 80 bb1: 81 br label %bb2 82 bb2: 83 ret void 84 } 85 )IR"); 86 Function *F = M->getFunction("foo"); 87 DominatorTree DT(*F); 88 BasicBlock *SrcBlock; 89 BasicBlock *DestBlock; 90 BasicBlock *NewBB; 91 92 SrcBlock = getBasicBlockByName(*F, "entry"); 93 DestBlock = getBasicBlockByName(*F, "bb0"); 94 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr); 95 96 EXPECT_TRUE(DT.verify()); 97 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock); 98 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock); 99 EXPECT_EQ(NewBB->getParent(), F); 100 101 bool BBFlag = false; 102 for (BasicBlock &BB : *F) { 103 if (BB.getName() == NewBB->getName()) { 104 BBFlag = true; 105 } 106 } 107 EXPECT_TRUE(BBFlag); 108 } 109 110 TEST(BasicBlockUtils, SplitEdge_ex2) { 111 LLVMContext C; 112 std::unique_ptr<Module> M = parseIR(C, R"IR( 113 define void @foo() { 114 bb0: 115 br label %bb2 116 bb1: 117 br label %bb2 118 bb2: 119 ret void 120 } 121 )IR"); 122 Function *F = M->getFunction("foo"); 123 DominatorTree DT(*F); 124 125 BasicBlock *SrcBlock; 126 BasicBlock *DestBlock; 127 BasicBlock *NewBB; 128 129 SrcBlock = getBasicBlockByName(*F, "bb0"); 130 DestBlock = getBasicBlockByName(*F, "bb2"); 131 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr); 132 133 EXPECT_TRUE(DT.verify()); 134 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock); 135 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock); 136 EXPECT_EQ(NewBB->getParent(), F); 137 138 bool BBFlag = false; 139 for (BasicBlock &BB : *F) { 140 if (BB.getName() == NewBB->getName()) { 141 BBFlag = true; 142 } 143 } 144 EXPECT_TRUE(BBFlag); 145 } 146 147 TEST(BasicBlockUtils, SplitEdge_ex3) { 148 LLVMContext C; 149 std::unique_ptr<Module> M = parseIR(C, R"IR( 150 define i32 @foo(i32 %n) { 151 entry: 152 br label %header 153 header: 154 %sum.02 = phi i32 [ 0, %entry ], [ %sum.1, %bb3 ] 155 %0 = phi i32 [ 0, %entry ], [ %4, %bb3 ] 156 %1 = icmp slt i32 %0, %n 157 br i1 %1, label %bb0, label %bb1 158 bb0: 159 %2 = add nsw i32 %sum.02, 2 160 br label %bb2 161 bb1: 162 %3 = add nsw i32 %sum.02, 1 163 br label %bb2 164 bb2: 165 %sum.1 = phi i32 [ %2, %bb0 ], [ %3, %bb1 ] 166 br label %bb3 167 bb3: 168 %4 = add nsw i32 %0, 1 169 %5 = icmp slt i32 %4, 100 170 br i1 %5, label %header, label %bb4 171 bb4: 172 %sum.0.lcssa = phi i32 [ %sum.1, %bb3 ] 173 ret i32 %sum.0.lcssa 174 } 175 )IR"); 176 Function *F = M->getFunction("foo"); 177 DominatorTree DT(*F); 178 179 LoopInfo LI(DT); 180 181 DataLayout DL("e-i64:64-f80:128-n8:16:32:64-S128"); 182 TargetLibraryInfoImpl TLII; 183 TargetLibraryInfo TLI(TLII); 184 AssumptionCache AC(*F); 185 AAResults AA(TLI); 186 187 BasicAAResult BAA(DL, *F, TLI, AC, &DT); 188 AA.addAAResult(BAA); 189 190 MemorySSA MSSA(*F, &AA, &DT); 191 MemorySSAUpdater Updater(&MSSA); 192 193 BasicBlock *SrcBlock; 194 BasicBlock *DestBlock; 195 BasicBlock *NewBB; 196 197 SrcBlock = getBasicBlockByName(*F, "header"); 198 DestBlock = getBasicBlockByName(*F, "bb0"); 199 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &Updater); 200 201 Updater.getMemorySSA()->verifyMemorySSA(); 202 EXPECT_TRUE(DT.verify()); 203 EXPECT_NE(LI.getLoopFor(SrcBlock), nullptr); 204 EXPECT_NE(LI.getLoopFor(DestBlock), nullptr); 205 EXPECT_NE(LI.getLoopFor(NewBB), nullptr); 206 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock); 207 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock); 208 EXPECT_EQ(NewBB->getParent(), F); 209 210 bool BBFlag = false; 211 for (BasicBlock &BB : *F) { 212 if (BB.getName() == NewBB->getName()) { 213 BBFlag = true; 214 } 215 } 216 EXPECT_TRUE(BBFlag); 217 } 218 219 TEST(BasicBlockUtils, SplitEdge_ex4) { 220 LLVMContext C; 221 std::unique_ptr<Module> M = parseIR(C, R"IR( 222 define void @bar(i32 %cond) personality i8 0 { 223 entry: 224 switch i32 %cond, label %exit [ 225 i32 -1, label %continue 226 i32 0, label %continue 227 i32 1, label %continue_alt 228 i32 2, label %continue_alt 229 ] 230 exit: 231 ret void 232 continue: 233 invoke void @sink() to label %normal unwind label %exception 234 continue_alt: 235 invoke void @sink_alt() to label %normal unwind label %exception 236 exception: 237 %cleanup = landingpad i8 cleanup 238 br label %trivial-eh-handler 239 trivial-eh-handler: 240 call void @sideeffect(i32 1) 241 br label %normal 242 normal: 243 call void @sideeffect(i32 0) 244 ret void 245 } 246 247 declare void @sideeffect(i32) 248 declare void @sink() cold 249 declare void @sink_alt() cold 250 )IR"); 251 Function *F = M->getFunction("bar"); 252 253 DominatorTree DT(*F); 254 255 LoopInfo LI(DT); 256 257 TargetLibraryInfoImpl TLII; 258 TargetLibraryInfo TLI(TLII); 259 260 AAResults AA(TLI); 261 262 MemorySSA MSSA(*F, &AA, &DT); 263 MemorySSAUpdater MSSAU(&MSSA); 264 265 BasicBlock *SrcBlock; 266 BasicBlock *DestBlock; 267 268 SrcBlock = getBasicBlockByName(*F, "continue"); 269 DestBlock = getBasicBlockByName(*F, "exception"); 270 271 unsigned SuccNum = GetSuccessorNumber(SrcBlock, DestBlock); 272 Instruction *LatchTerm = SrcBlock->getTerminator(); 273 274 const CriticalEdgeSplittingOptions Options = 275 CriticalEdgeSplittingOptions(&DT, &LI, &MSSAU); 276 277 // Check that the following edge is both critical and the destination block is 278 // an exception block. These must be handled differently by SplitEdge 279 bool CriticalEdge = 280 isCriticalEdge(LatchTerm, SuccNum, Options.MergeIdenticalEdges); 281 EXPECT_TRUE(CriticalEdge); 282 283 bool Ehpad = DestBlock->isEHPad(); 284 EXPECT_TRUE(Ehpad); 285 286 BasicBlock *NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &MSSAU, ""); 287 288 MSSA.verifyMemorySSA(); 289 EXPECT_TRUE(DT.verify()); 290 EXPECT_NE(NewBB, nullptr); 291 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock); 292 EXPECT_EQ(NewBB, SrcBlock->getTerminator()->getSuccessor(SuccNum)); 293 EXPECT_EQ(NewBB->getParent(), F); 294 295 bool BBFlag = false; 296 for (BasicBlock &BB : *F) { 297 if (BB.getName() == NewBB->getName()) { 298 BBFlag = true; 299 break; 300 } 301 } 302 EXPECT_TRUE(BBFlag); 303 } 304 305 TEST(BasicBlockUtils, splitBasicBlockBefore_ex1) { 306 LLVMContext C; 307 std::unique_ptr<Module> M = parseIR(C, R"IR( 308 define void @foo() { 309 bb0: 310 %0 = mul i32 1, 2 311 br label %bb2 312 bb1: 313 br label %bb3 314 bb2: 315 %1 = phi i32 [ %0, %bb0 ] 316 br label %bb3 317 bb3: 318 ret void 319 } 320 )IR"); 321 Function *F = M->getFunction("foo"); 322 DominatorTree DT(*F); 323 324 BasicBlock *DestBlock; 325 BasicBlock *NewBB; 326 327 DestBlock = getBasicBlockByName(*F, "bb2"); 328 329 NewBB = DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(), 330 "test"); 331 332 PHINode *PN = dyn_cast<PHINode>(&(DestBlock->front())); 333 EXPECT_EQ(PN->getIncomingBlock(0), NewBB); 334 EXPECT_EQ(NewBB->getName(), "test"); 335 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock); 336 EXPECT_EQ(DestBlock->getSinglePredecessor(), NewBB); 337 } 338 339 #ifndef NDEBUG 340 TEST(BasicBlockUtils, splitBasicBlockBefore_ex2) { 341 LLVMContext C; 342 std::unique_ptr<Module> M = parseIR(C, R"IR( 343 define void @foo() { 344 bb0: 345 %0 = mul i32 1, 2 346 br label %bb2 347 bb1: 348 br label %bb2 349 bb2: 350 %1 = phi i32 [ %0, %bb0 ], [ 1, %bb1 ] 351 br label %bb3 352 bb3: 353 ret void 354 } 355 )IR"); 356 Function *F = M->getFunction("foo"); 357 DominatorTree DT(*F); 358 359 BasicBlock *DestBlock = getBasicBlockByName(*F, "bb2"); 360 361 ASSERT_DEATH( 362 { 363 DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(), 364 "test"); 365 }, 366 "cannot split on multi incoming phis"); 367 } 368 #endif 369 370 TEST(BasicBlockUtils, NoUnreachableBlocksToEliminate) { 371 LLVMContext C; 372 std::unique_ptr<Module> M = parseIR(C, R"IR( 373 define i32 @no_unreachable(i1 %cond) { 374 entry: 375 br i1 %cond, label %bb0, label %bb1 376 bb0: 377 br label %bb1 378 bb1: 379 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ] 380 ret i32 %phi 381 } 382 )IR"); 383 Function *F = M->getFunction("no_unreachable"); 384 DominatorTree DT(*F); 385 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); 386 387 EXPECT_EQ(F->size(), (size_t)3); 388 bool Result = EliminateUnreachableBlocks(*F, &DTU); 389 EXPECT_FALSE(Result); 390 EXPECT_EQ(F->size(), (size_t)3); 391 EXPECT_TRUE(DT.verify()); 392 } 393 394 TEST(BasicBlockUtils, SplitBlockPredecessors) { 395 LLVMContext C; 396 std::unique_ptr<Module> M = parseIR(C, R"IR( 397 define i32 @basic_func(i1 %cond) { 398 entry: 399 br i1 %cond, label %bb0, label %bb1 400 bb0: 401 br label %bb1 402 bb1: 403 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ] 404 ret i32 %phi 405 } 406 )IR"); 407 Function *F = M->getFunction("basic_func"); 408 DominatorTree DT(*F); 409 410 // Make sure the dominator tree is properly updated if calling this on the 411 // entry block. 412 SplitBlockPredecessors(&F->getEntryBlock(), {}, "split.entry", &DT); 413 EXPECT_TRUE(DT.verify()); 414 } 415 416 TEST(BasicBlockUtils, SplitCriticalEdge) { 417 LLVMContext C; 418 std::unique_ptr<Module> M = parseIR(C, R"IR( 419 define void @crit_edge(i1 %cond0, i1 %cond1) { 420 entry: 421 br i1 %cond0, label %bb0, label %bb1 422 bb0: 423 br label %bb1 424 bb1: 425 br label %bb2 426 bb2: 427 ret void 428 } 429 )IR"); 430 Function *F = M->getFunction("crit_edge"); 431 DominatorTree DT(*F); 432 PostDominatorTree PDT(*F); 433 434 CriticalEdgeSplittingOptions CESO(&DT, nullptr, nullptr, &PDT); 435 EXPECT_EQ(1u, SplitAllCriticalEdges(*F, CESO)); 436 EXPECT_TRUE(DT.verify()); 437 EXPECT_TRUE(PDT.verify()); 438 } 439 440 TEST(BasicBlockUtils, SplitIndirectBrCriticalEdgesIgnorePHIs) { 441 LLVMContext C; 442 std::unique_ptr<Module> M = parseIR(C, R"IR( 443 define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) { 444 entry: 445 indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2] 446 bb0: 447 br i1 %cond0, label %bb1, label %bb2 448 bb1: 449 %p = phi i32 [0, %bb0], [0, %entry] 450 br i1 %cond1, label %bb3, label %bb4 451 bb2: 452 ret void 453 bb3: 454 ret void 455 bb4: 456 ret void 457 } 458 )IR"); 459 Function *F = M->getFunction("crit_edge"); 460 DominatorTree DT(*F); 461 LoopInfo LI(DT); 462 BranchProbabilityInfo BPI(*F, LI); 463 BlockFrequencyInfo BFI(*F, BPI, LI); 464 465 ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/true, 466 &BPI, &BFI)); 467 468 // Check that successors of the split block get their probability correct. 469 BasicBlock *BB1 = getBasicBlockByName(*F, "bb1"); 470 BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0); 471 ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors()); 472 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u)); 473 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u)); 474 475 // bb2 has no PHI, so we shouldn't split bb0 -> bb2 476 BasicBlock *BB0 = getBasicBlockByName(*F, "bb0"); 477 ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors()); 478 EXPECT_EQ(BB0->getTerminator()->getSuccessor(1), 479 getBasicBlockByName(*F, "bb2")); 480 } 481 482 TEST(BasicBlockUtils, SplitIndirectBrCriticalEdges) { 483 LLVMContext C; 484 std::unique_ptr<Module> M = parseIR(C, R"IR( 485 define void @crit_edge(i8* %tgt, i1 %cond0, i1 %cond1) { 486 entry: 487 indirectbr i8* %tgt, [label %bb0, label %bb1, label %bb2] 488 bb0: 489 br i1 %cond0, label %bb1, label %bb2 490 bb1: 491 %p = phi i32 [0, %bb0], [0, %entry] 492 br i1 %cond1, label %bb3, label %bb4 493 bb2: 494 ret void 495 bb3: 496 ret void 497 bb4: 498 ret void 499 } 500 )IR"); 501 Function *F = M->getFunction("crit_edge"); 502 DominatorTree DT(*F); 503 LoopInfo LI(DT); 504 BranchProbabilityInfo BPI(*F, LI); 505 BlockFrequencyInfo BFI(*F, BPI, LI); 506 507 ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/false, 508 &BPI, &BFI)); 509 510 // Check that successors of the split block get their probability correct. 511 BasicBlock *BB1 = getBasicBlockByName(*F, "bb1"); 512 BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0); 513 ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors()); 514 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u)); 515 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u)); 516 517 // Should split, resulting in: 518 // bb0 -> bb2.clone; bb2 -> split1; bb2.clone -> split, 519 BasicBlock *BB0 = getBasicBlockByName(*F, "bb0"); 520 ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors()); 521 BasicBlock *BB2Clone = BB0->getTerminator()->getSuccessor(1); 522 BasicBlock *BB2 = getBasicBlockByName(*F, "bb2"); 523 EXPECT_NE(BB2Clone, BB2); 524 ASSERT_EQ(1u, BB2->getTerminator()->getNumSuccessors()); 525 ASSERT_EQ(1u, BB2Clone->getTerminator()->getNumSuccessors()); 526 EXPECT_EQ(BB2->getTerminator()->getSuccessor(0), 527 BB2Clone->getTerminator()->getSuccessor(0)); 528 } 529 530 TEST(BasicBlockUtils, SetEdgeProbability) { 531 LLVMContext C; 532 std::unique_ptr<Module> M = parseIR(C, R"IR( 533 define void @edge_probability(i32 %0) { 534 entry: 535 switch i32 %0, label %LD [ 536 i32 700, label %L0 537 i32 701, label %L1 538 i32 702, label %L2 539 i32 703, label %L3 540 i32 704, label %L4 541 i32 705, label %L5 542 i32 706, label %L6 543 i32 707, label %L7 544 i32 708, label %L8 545 i32 709, label %L9 546 i32 710, label %L10 547 i32 711, label %L11 548 i32 712, label %L12 549 i32 713, label %L13 550 i32 714, label %L14 551 i32 715, label %L15 552 i32 716, label %L16 553 i32 717, label %L17 554 i32 718, label %L18 555 i32 719, label %L19 556 ], !prof !{!"branch_weights", i32 1, i32 1, i32 1, i32 1, i32 1, i32 451, i32 1, 557 i32 12, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, 558 i32 1, i32 1, i32 1, i32 1, i32 1} 559 LD: 560 unreachable 561 L0: 562 ret void 563 L1: 564 ret void 565 L2: 566 ret void 567 L3: 568 ret void 569 L4: 570 ret void 571 L5: 572 ret void 573 L6: 574 ret void 575 L7: 576 ret void 577 L8: 578 ret void 579 L9: 580 ret void 581 L10: 582 ret void 583 L11: 584 ret void 585 L12: 586 ret void 587 L13: 588 ret void 589 L14: 590 ret void 591 L15: 592 ret void 593 L16: 594 ret void 595 L17: 596 ret void 597 L18: 598 ret void 599 L19: 600 ret void 601 } 602 )IR"); 603 Function *F = M->getFunction("edge_probability"); 604 DominatorTree DT(*F); 605 LoopInfo LI(DT); 606 BranchProbabilityInfo BPI(*F, LI); 607 608 // Check that the unreachable block has the minimal probability. 609 const BasicBlock *EntryBB = getBasicBlockByName(*F, "entry"); 610 const BasicBlock *UnreachableBB = getBasicBlockByName(*F, "LD"); 611 EXPECT_EQ(BranchProbability::getRaw(1), 612 BPI.getEdgeProbability(EntryBB, UnreachableBB)); 613 } 614 615 TEST(BasicBlockUtils, IsPresplitCoroSuspendExitTest) { 616 LLVMContext C; 617 std::unique_ptr<Module> M = parseIR(C, R"IR( 618 define void @positive_case(i32 %0) #0 { 619 entry: 620 %save = call token @llvm.coro.save(ptr null) 621 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) 622 switch i8 %suspend, label %exit [ 623 i8 0, label %resume 624 i8 1, label %destroy 625 ] 626 resume: 627 ret void 628 destroy: 629 ret void 630 exit: 631 call i1 @llvm.coro.end(ptr null, i1 false, token none) 632 ret void 633 } 634 635 define void @notpresplit(i32 %0) { 636 entry: 637 %save = call token @llvm.coro.save(ptr null) 638 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false) 639 switch i8 %suspend, label %exit [ 640 i8 0, label %resume 641 i8 1, label %destroy 642 ] 643 resume: 644 ret void 645 destroy: 646 ret void 647 exit: 648 call i1 @llvm.coro.end(ptr null, i1 false, token none) 649 ret void 650 } 651 652 declare token @llvm.coro.save(ptr) 653 declare i8 @llvm.coro.suspend(token, i1) 654 declare i1 @llvm.coro.end(ptr, i1, token) 655 656 attributes #0 = { presplitcoroutine } 657 )IR"); 658 659 auto FindExit = [](const Function &F) -> const BasicBlock * { 660 for (const auto &BB : F) 661 if (BB.getName() == "exit") 662 return &BB; 663 return nullptr; 664 }; 665 Function *P = M->getFunction("positive_case"); 666 const auto &ExitP = *FindExit(*P); 667 EXPECT_TRUE(llvm::isPresplitCoroSuspendExitEdge(*ExitP.getSinglePredecessor(), 668 ExitP)); 669 670 Function *N = M->getFunction("notpresplit"); 671 const auto &ExitN = *FindExit(*N); 672 EXPECT_FALSE(llvm::isPresplitCoroSuspendExitEdge( 673 *ExitN.getSinglePredecessor(), ExitN)); 674 } 675