748 lines · cpp
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-exception6//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/IR/Module.h"26#include "llvm/Support/SourceMgr.h"27#include "gtest/gtest.h"28 29using namespace llvm;30 31static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {32 SMDiagnostic Err;33 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);34 if (!Mod)35 Err.print("BasicBlockUtilsTests", errs());36 return Mod;37}38 39static BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {40 for (BasicBlock &BB : F)41 if (BB.getName() == Name)42 return &BB;43 llvm_unreachable("Expected to find basic block!");44}45 46TEST(BasicBlockUtils, EliminateUnreachableBlocks) {47 LLVMContext C;48 std::unique_ptr<Module> M = parseIR(C, R"IR(49define i32 @has_unreachable(i1 %cond) {50entry:51 br i1 %cond, label %bb0, label %bb152bb0:53 br label %bb154bb1:55 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]56 ret i32 %phi57bb2:58 ret i32 4259}60)IR");61 Function *F = M->getFunction("has_unreachable");62 DominatorTree DT(*F);63 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);64 65 EXPECT_EQ(F->size(), (size_t)4);66 bool Result = EliminateUnreachableBlocks(*F, &DTU);67 EXPECT_TRUE(Result);68 EXPECT_EQ(F->size(), (size_t)3);69 EXPECT_TRUE(DT.verify());70}71 72TEST(BasicBlockUtils, SplitEdge_ex1) {73 LLVMContext C;74 std::unique_ptr<Module> M = parseIR(C, R"IR(75define void @foo(i1 %cond0) {76entry:77 br i1 %cond0, label %bb0, label %bb178bb0:79 %0 = mul i32 1, 280 br label %bb181bb1:82 br label %bb283bb2:84 ret void85}86)IR");87 Function *F = M->getFunction("foo");88 DominatorTree DT(*F);89 BasicBlock *SrcBlock;90 BasicBlock *DestBlock;91 BasicBlock *NewBB;92 93 SrcBlock = getBasicBlockByName(*F, "entry");94 DestBlock = getBasicBlockByName(*F, "bb0");95 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);96 97 EXPECT_TRUE(DT.verify());98 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);99 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);100 EXPECT_EQ(NewBB->getParent(), F);101 102 bool BBFlag = false;103 for (BasicBlock &BB : *F) {104 if (BB.getName() == NewBB->getName()) {105 BBFlag = true;106 }107 }108 EXPECT_TRUE(BBFlag);109}110 111TEST(BasicBlockUtils, SplitEdge_ex2) {112 LLVMContext C;113 std::unique_ptr<Module> M = parseIR(C, R"IR(114define void @foo() {115bb0:116 br label %bb2117bb1:118 br label %bb2119bb2:120 ret void121}122)IR");123 Function *F = M->getFunction("foo");124 DominatorTree DT(*F);125 126 BasicBlock *SrcBlock;127 BasicBlock *DestBlock;128 BasicBlock *NewBB;129 130 SrcBlock = getBasicBlockByName(*F, "bb0");131 DestBlock = getBasicBlockByName(*F, "bb2");132 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, nullptr, nullptr);133 134 EXPECT_TRUE(DT.verify());135 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);136 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);137 EXPECT_EQ(NewBB->getParent(), F);138 139 bool BBFlag = false;140 for (BasicBlock &BB : *F) {141 if (BB.getName() == NewBB->getName()) {142 BBFlag = true;143 }144 }145 EXPECT_TRUE(BBFlag);146}147 148TEST(BasicBlockUtils, SplitEdge_ex3) {149 LLVMContext C;150 std::unique_ptr<Module> M = parseIR(C, R"IR(151define i32 @foo(i32 %n) {152entry:153 br label %header154header:155 %sum.02 = phi i32 [ 0, %entry ], [ %sum.1, %bb3 ]156 %0 = phi i32 [ 0, %entry ], [ %4, %bb3 ]157 %1 = icmp slt i32 %0, %n158 br i1 %1, label %bb0, label %bb1159bb0:160 %2 = add nsw i32 %sum.02, 2161 br label %bb2162bb1:163 %3 = add nsw i32 %sum.02, 1164 br label %bb2165bb2:166 %sum.1 = phi i32 [ %2, %bb0 ], [ %3, %bb1 ]167 br label %bb3168bb3:169 %4 = add nsw i32 %0, 1170 %5 = icmp slt i32 %4, 100171 br i1 %5, label %header, label %bb4172bb4:173 %sum.0.lcssa = phi i32 [ %sum.1, %bb3 ]174 ret i32 %sum.0.lcssa175}176)IR");177 Function *F = M->getFunction("foo");178 DominatorTree DT(*F);179 180 LoopInfo LI(DT);181 182 DataLayout DL("e-i64:64-f80:128-n8:16:32:64-S128");183 TargetLibraryInfoImpl TLII(M->getTargetTriple());184 TargetLibraryInfo TLI(TLII);185 AssumptionCache AC(*F);186 AAResults AA(TLI);187 188 BasicAAResult BAA(DL, *F, TLI, AC, &DT);189 AA.addAAResult(BAA);190 191 MemorySSA MSSA(*F, &AA, &DT);192 MemorySSAUpdater Updater(&MSSA);193 194 BasicBlock *SrcBlock;195 BasicBlock *DestBlock;196 BasicBlock *NewBB;197 198 SrcBlock = getBasicBlockByName(*F, "header");199 DestBlock = getBasicBlockByName(*F, "bb0");200 NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &Updater);201 202 Updater.getMemorySSA()->verifyMemorySSA();203 EXPECT_TRUE(DT.verify());204 EXPECT_NE(LI.getLoopFor(SrcBlock), nullptr);205 EXPECT_NE(LI.getLoopFor(DestBlock), nullptr);206 EXPECT_NE(LI.getLoopFor(NewBB), nullptr);207 EXPECT_EQ(NewBB->getSinglePredecessor(), SrcBlock);208 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);209 EXPECT_EQ(NewBB->getParent(), F);210 211 bool BBFlag = false;212 for (BasicBlock &BB : *F) {213 if (BB.getName() == NewBB->getName()) {214 BBFlag = true;215 }216 }217 EXPECT_TRUE(BBFlag);218}219 220TEST(BasicBlockUtils, SplitEdge_ex4) {221 LLVMContext C;222 std::unique_ptr<Module> M = parseIR(C, R"IR(223define void @bar(i32 %cond) personality i8 0 {224entry:225 switch i32 %cond, label %exit [226 i32 -1, label %continue227 i32 0, label %continue228 i32 1, label %continue_alt229 i32 2, label %continue_alt230 ]231exit:232 ret void233continue:234 invoke void @sink() to label %normal unwind label %exception235continue_alt:236 invoke void @sink_alt() to label %normal unwind label %exception237exception:238 %cleanup = landingpad i8 cleanup239 br label %trivial-eh-handler240trivial-eh-handler:241 call void @sideeffect(i32 1)242 br label %normal243normal:244 call void @sideeffect(i32 0)245 ret void246}247 248declare void @sideeffect(i32)249declare void @sink() cold250declare void @sink_alt() cold251)IR");252 Function *F = M->getFunction("bar");253 254 DominatorTree DT(*F);255 256 LoopInfo LI(DT);257 258 TargetLibraryInfoImpl TLII(M->getTargetTriple());259 TargetLibraryInfo TLI(TLII);260 261 AAResults AA(TLI);262 263 MemorySSA MSSA(*F, &AA, &DT);264 MemorySSAUpdater MSSAU(&MSSA);265 266 BasicBlock *SrcBlock;267 BasicBlock *DestBlock;268 269 SrcBlock = getBasicBlockByName(*F, "continue");270 DestBlock = getBasicBlockByName(*F, "exception");271 272 unsigned SuccNum = GetSuccessorNumber(SrcBlock, DestBlock);273 Instruction *LatchTerm = SrcBlock->getTerminator();274 275 const CriticalEdgeSplittingOptions Options =276 CriticalEdgeSplittingOptions(&DT, &LI, &MSSAU);277 278 // Check that the following edge is both critical and the destination block is279 // an exception block. These must be handled differently by SplitEdge280 bool CriticalEdge =281 isCriticalEdge(LatchTerm, SuccNum, Options.MergeIdenticalEdges);282 EXPECT_TRUE(CriticalEdge);283 284 bool Ehpad = DestBlock->isEHPad();285 EXPECT_TRUE(Ehpad);286 287 BasicBlock *NewBB = SplitEdge(SrcBlock, DestBlock, &DT, &LI, &MSSAU, "");288 // SplitEdge cannot split an eh pad edge.289 EXPECT_EQ(NewBB, nullptr);290}291 292TEST(BasicBlockUtils, splitBasicBlockBefore_ex1) {293 LLVMContext C;294 std::unique_ptr<Module> M = parseIR(C, R"IR(295define void @foo() {296bb0:297 %0 = mul i32 1, 2298 br label %bb2299bb1:300 br label %bb3301bb2:302 %1 = phi i32 [ %0, %bb0 ]303 br label %bb3304bb3:305 ret void306}307)IR");308 Function *F = M->getFunction("foo");309 DominatorTree DT(*F);310 311 BasicBlock *DestBlock;312 BasicBlock *NewBB;313 314 DestBlock = getBasicBlockByName(*F, "bb2");315 316 NewBB = DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),317 "test");318 319 PHINode *PN = dyn_cast<PHINode>(&(DestBlock->front()));320 EXPECT_EQ(PN->getIncomingBlock(0), NewBB);321 EXPECT_EQ(NewBB->getName(), "test");322 EXPECT_EQ(NewBB->getSingleSuccessor(), DestBlock);323 EXPECT_EQ(DestBlock->getSinglePredecessor(), NewBB);324}325 326#ifndef NDEBUG327TEST(BasicBlockUtils, splitBasicBlockBefore_ex2) {328 LLVMContext C;329 std::unique_ptr<Module> M = parseIR(C, R"IR(330define void @foo() {331bb0:332 %0 = mul i32 1, 2333 br label %bb2334bb1:335 br label %bb2336bb2:337 %1 = phi i32 [ %0, %bb0 ], [ 1, %bb1 ]338 br label %bb3339bb3:340 ret void341}342)IR");343 Function *F = M->getFunction("foo");344 DominatorTree DT(*F);345 346 BasicBlock *DestBlock = getBasicBlockByName(*F, "bb2");347 348 ASSERT_DEATH(349 {350 DestBlock->splitBasicBlockBefore(DestBlock->front().getIterator(),351 "test");352 },353 "cannot split on multi incoming phis");354}355#endif356 357TEST(BasicBlockUtils, NoUnreachableBlocksToEliminate) {358 LLVMContext C;359 std::unique_ptr<Module> M = parseIR(C, R"IR(360define i32 @no_unreachable(i1 %cond) {361entry:362 br i1 %cond, label %bb0, label %bb1363bb0:364 br label %bb1365bb1:366 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]367 ret i32 %phi368}369)IR");370 Function *F = M->getFunction("no_unreachable");371 DominatorTree DT(*F);372 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);373 374 EXPECT_EQ(F->size(), (size_t)3);375 bool Result = EliminateUnreachableBlocks(*F, &DTU);376 EXPECT_FALSE(Result);377 EXPECT_EQ(F->size(), (size_t)3);378 EXPECT_TRUE(DT.verify());379}380 381TEST(BasicBlockUtils, SplitBlockPredecessors) {382 LLVMContext C;383 std::unique_ptr<Module> M = parseIR(C, R"IR(384define i32 @basic_func(i1 %cond) {385entry:386 br i1 %cond, label %bb0, label %bb1387bb0:388 br label %bb1389bb1:390 %phi = phi i32 [ 0, %entry ], [ 1, %bb0 ]391 ret i32 %phi392}393)IR");394 Function *F = M->getFunction("basic_func");395 DominatorTree DT(*F);396 397 // Make sure the dominator tree is properly updated if calling this on the398 // entry block.399 SplitBlockPredecessors(&F->getEntryBlock(), {}, "split.entry", &DT);400 EXPECT_TRUE(DT.verify());401}402 403TEST(BasicBlockUtils, SplitCriticalEdge) {404 LLVMContext C;405 std::unique_ptr<Module> M = parseIR(C, R"IR(406define void @crit_edge(i1 %cond0, i1 %cond1) {407entry:408 br i1 %cond0, label %bb0, label %bb1409bb0:410 br label %bb1411bb1:412 br label %bb2413bb2:414 ret void415}416)IR");417 Function *F = M->getFunction("crit_edge");418 DominatorTree DT(*F);419 PostDominatorTree PDT(*F);420 421 CriticalEdgeSplittingOptions CESO(&DT, nullptr, nullptr, &PDT);422 EXPECT_EQ(1u, SplitAllCriticalEdges(*F, CESO));423 EXPECT_TRUE(DT.verify());424 EXPECT_TRUE(PDT.verify());425}426 427TEST(BasicBlockUtils, SplitLoopCriticalEdge) {428 LLVMContext C;429 std::unique_ptr<Module> M = parseIR(C, R"IR(430declare i1 @predicate(ptr %p)431 432define ptr @Parse(ptr %gp) {433entry:434 br label %for.inc435 436for.inc:437 %phi = phi ptr [ %gp, %entry ], [ %cp, %while.cond ], [ %cp, %while.cond ]438 %cond = call i1 @predicate(ptr %phi)439 %inc= getelementptr inbounds i8, ptr %phi, i64 1440 br i1 %cond, label %while.cond, label %exit441 442while.cond:443 %cp = phi ptr [ %inc, %for.inc ], [ %incdec, %while.body ]444 %val = load i8, ptr %cp, align 1445 switch i8 %val, label %while.body [446 i8 10, label %for.inc447 i8 0, label %for.inc448 ]449 450while.body:451 %incdec = getelementptr inbounds i8, ptr %cp, i64 1452 br label %while.cond453 454exit:455 ret ptr %phi456}457)IR");458 Function *F = M->getFunction("Parse");459 DominatorTree DT(*F);460 LoopInfo LI(DT);461 462 CriticalEdgeSplittingOptions CESO =463 CriticalEdgeSplittingOptions(nullptr, &LI, nullptr)464 .setMergeIdenticalEdges()465 .setPreserveLCSSA();466 EXPECT_EQ(2u, SplitAllCriticalEdges(*F, CESO));467 468 BasicBlock *WhileBB = getBasicBlockByName(*F, "while.cond");469 BasicBlock *SplitBB = WhileBB->getTerminator()->getSuccessor(1);470 // The only 1 successor of SplitBB is %for.inc471 EXPECT_EQ(1u, SplitBB->getTerminator()->getNumSuccessors());472 // MergeIdenticalEdges: SplitBB has two identical predecessors, %while.cond.473 EXPECT_EQ(WhileBB, SplitBB->getUniquePredecessor());474 EXPECT_TRUE(SplitBB->hasNPredecessors(2));475 476 auto *PN = dyn_cast<PHINode>(&SplitBB->front());477 // PreserveLCSSA: should insert a PHI node in front of SplitBB478 EXPECT_NE(nullptr, PN);479 // The PHI node should have 2 identical incoming blocks.480 EXPECT_EQ(2u, PN->getNumIncomingValues());481 EXPECT_EQ(PN->getIncomingBlock(0), PN->getIncomingBlock(1));482}483 484TEST(BasicBlockUtils, SplitIndirectBrCriticalEdgesIgnorePHIs) {485 LLVMContext C;486 std::unique_ptr<Module> M = parseIR(C, R"IR(487define void @crit_edge(ptr %tgt, i1 %cond0, i1 %cond1) {488entry:489 indirectbr ptr %tgt, [label %bb0, label %bb1, label %bb2]490bb0:491 br i1 %cond0, label %bb1, label %bb2492bb1:493 %p = phi i32 [0, %bb0], [0, %entry]494 br i1 %cond1, label %bb3, label %bb4495bb2:496 ret void497bb3:498 ret void499bb4:500 ret void501}502)IR");503 Function *F = M->getFunction("crit_edge");504 DominatorTree DT(*F);505 LoopInfo LI(DT);506 BranchProbabilityInfo BPI(*F, LI);507 BlockFrequencyInfo BFI(*F, BPI, LI);508 509 ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/true,510 &BPI, &BFI));511 512 // Check that successors of the split block get their probability correct.513 BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");514 BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);515 ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());516 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));517 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));518 519 // bb2 has no PHI, so we shouldn't split bb0 -> bb2520 BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");521 ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());522 EXPECT_EQ(BB0->getTerminator()->getSuccessor(1),523 getBasicBlockByName(*F, "bb2"));524}525 526TEST(BasicBlockUtils, SplitIndirectBrCriticalEdges) {527 LLVMContext C;528 std::unique_ptr<Module> M = parseIR(C, R"IR(529define void @crit_edge(ptr %tgt, i1 %cond0, i1 %cond1) {530entry:531 indirectbr ptr %tgt, [label %bb0, label %bb1, label %bb2]532bb0:533 br i1 %cond0, label %bb1, label %bb2534bb1:535 %p = phi i32 [0, %bb0], [0, %entry]536 br i1 %cond1, label %bb3, label %bb4537bb2:538 ret void539bb3:540 ret void541bb4:542 ret void543}544)IR");545 Function *F = M->getFunction("crit_edge");546 DominatorTree DT(*F);547 LoopInfo LI(DT);548 BranchProbabilityInfo BPI(*F, LI);549 BlockFrequencyInfo BFI(*F, BPI, LI);550 551 ASSERT_TRUE(SplitIndirectBrCriticalEdges(*F, /*IgnoreBlocksWithoutPHI=*/false,552 &BPI, &BFI));553 554 // Check that successors of the split block get their probability correct.555 BasicBlock *BB1 = getBasicBlockByName(*F, "bb1");556 BasicBlock *SplitBB = BB1->getTerminator()->getSuccessor(0);557 ASSERT_EQ(2u, SplitBB->getTerminator()->getNumSuccessors());558 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 0u));559 EXPECT_EQ(BranchProbability(1, 2), BPI.getEdgeProbability(SplitBB, 1u));560 561 // Should split, resulting in:562 // bb0 -> bb2.clone; bb2 -> split1; bb2.clone -> split,563 BasicBlock *BB0 = getBasicBlockByName(*F, "bb0");564 ASSERT_EQ(2u, BB0->getTerminator()->getNumSuccessors());565 BasicBlock *BB2Clone = BB0->getTerminator()->getSuccessor(1);566 BasicBlock *BB2 = getBasicBlockByName(*F, "bb2");567 EXPECT_NE(BB2Clone, BB2);568 ASSERT_EQ(1u, BB2->getTerminator()->getNumSuccessors());569 ASSERT_EQ(1u, BB2Clone->getTerminator()->getNumSuccessors());570 EXPECT_EQ(BB2->getTerminator()->getSuccessor(0),571 BB2Clone->getTerminator()->getSuccessor(0));572}573 574TEST(BasicBlockUtils, SetEdgeProbability) {575 LLVMContext C;576 std::unique_ptr<Module> M = parseIR(C, R"IR(577define void @edge_probability(i32 %0) {578entry:579switch i32 %0, label %LD [580 i32 700, label %L0581 i32 701, label %L1582 i32 702, label %L2583 i32 703, label %L3584 i32 704, label %L4585 i32 705, label %L5586 i32 706, label %L6587 i32 707, label %L7588 i32 708, label %L8589 i32 709, label %L9590 i32 710, label %L10591 i32 711, label %L11592 i32 712, label %L12593 i32 713, label %L13594 i32 714, label %L14595 i32 715, label %L15596 i32 716, label %L16597 i32 717, label %L17598 i32 718, label %L18599 i32 719, label %L19600], !prof !{!"branch_weights", i32 1, i32 1, i32 1, i32 1, i32 1, i32 451, i32 1,601 i32 12, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1,602 i32 1, i32 1, i32 1, i32 1, i32 1}603LD:604 unreachable605L0:606 ret void607L1:608 ret void609L2:610 ret void611L3:612 ret void613L4:614 ret void615L5:616 ret void617L6:618 ret void619L7:620 ret void621L8:622 ret void623L9:624 ret void625L10:626 ret void627L11:628 ret void629L12:630 ret void631L13:632 ret void633L14:634 ret void635L15:636 ret void637L16:638 ret void639L17:640 ret void641L18:642 ret void643L19:644 ret void645}646)IR");647 Function *F = M->getFunction("edge_probability");648 DominatorTree DT(*F);649 LoopInfo LI(DT);650 BranchProbabilityInfo BPI(*F, LI);651 652 // Check that the unreachable block has the minimal probability.653 const BasicBlock *EntryBB = getBasicBlockByName(*F, "entry");654 const BasicBlock *UnreachableBB = getBasicBlockByName(*F, "LD");655 EXPECT_EQ(BranchProbability::getRaw(1),656 BPI.getEdgeProbability(EntryBB, UnreachableBB));657}658 659TEST(BasicBlockUtils, IsPresplitCoroSuspendExitTest) {660 LLVMContext C;661 std::unique_ptr<Module> M = parseIR(C, R"IR(662define void @positive_case(i32 %0) #0 {663entry:664 %save = call token @llvm.coro.save(ptr null)665 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)666 switch i8 %suspend, label %exit [667 i8 0, label %resume668 i8 1, label %destroy669 ]670resume:671 ret void672destroy:673 ret void674exit:675 call void @llvm.coro.end(ptr null, i1 false, token none)676 ret void677}678 679define void @notpresplit(i32 %0) {680entry:681 %save = call token @llvm.coro.save(ptr null)682 %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)683 switch i8 %suspend, label %exit [684 i8 0, label %resume685 i8 1, label %destroy686 ]687resume:688 ret void689destroy:690 ret void691exit:692 call void @llvm.coro.end(ptr null, i1 false, token none)693 ret void694}695 696declare token @llvm.coro.save(ptr)697declare i8 @llvm.coro.suspend(token, i1)698declare void @llvm.coro.end(ptr, i1, token)699 700attributes #0 = { presplitcoroutine }701)IR");702 703 auto FindExit = [](const Function &F) -> const BasicBlock * {704 for (const auto &BB : F)705 if (BB.getName() == "exit")706 return &BB;707 return nullptr;708 };709 Function *P = M->getFunction("positive_case");710 const auto &ExitP = *FindExit(*P);711 EXPECT_TRUE(llvm::isPresplitCoroSuspendExitEdge(*ExitP.getSinglePredecessor(),712 ExitP));713 714 Function *N = M->getFunction("notpresplit");715 const auto &ExitN = *FindExit(*N);716 EXPECT_FALSE(llvm::isPresplitCoroSuspendExitEdge(717 *ExitN.getSinglePredecessor(), ExitN));718}719 720TEST(BasicBlockUtils, BasicBlockPrintable) {721 std::string S;722 std::string SCheck;723 llvm::raw_string_ostream OS{S};724 llvm::raw_string_ostream OSCheck{SCheck};725 726 LLVMContext C;727 std::unique_ptr<Module> M = parseIR(C, R"IR(728define void @foo() {729 br label %bb0730bb0:731 br label %.exit732.exit:733 ret void734}735)IR");736 737 Function *F = M->getFunction("foo");738 for (const BasicBlock &BB : *F) {739 OS << printBasicBlock(&BB);740 BB.printAsOperand(OSCheck);741 EXPECT_EQ(OS.str(), OSCheck.str());742 S.clear();743 SCheck.clear();744 }745 OS << printBasicBlock(nullptr);746 EXPECT_EQ(OS.str(), "<nullptr>");747}748